wok-server 0.5.0 → 0.7.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 (380) 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 +278 -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 +381 -356
  80. package/dist/mysql/manager/ops/delete.js +59 -65
  81. package/dist/mysql/manager/ops/exist.js +26 -26
  82. package/dist/mysql/manager/ops/find.js +149 -169
  83. package/dist/mysql/manager/ops/index.js +16 -14
  84. package/dist/mysql/manager/ops/insert.js +132 -106
  85. package/dist/mysql/manager/ops/modify.js +10 -10
  86. package/dist/mysql/manager/ops/order-by.js +28 -0
  87. package/dist/mysql/manager/ops/paginate.js +48 -23
  88. package/dist/mysql/manager/ops/query.js +9 -9
  89. package/dist/mysql/manager/ops/update.js +222 -216
  90. package/dist/mysql/manager/ops/upsert.js +178 -0
  91. package/dist/mysql/manager/ops/utils.js +28 -24
  92. package/dist/mysql/manager/tx-strict.js +103 -103
  93. package/dist/mysql/manager/tx.js +30 -30
  94. package/dist/mysql/manager/utils.js +56 -56
  95. package/dist/mysql/migration.js +136 -136
  96. package/dist/mysql/table-info.js +8 -8
  97. package/dist/task/daily.js +59 -59
  98. package/dist/task/fixed-delay.js +38 -38
  99. package/dist/task/fixed-rate.js +42 -42
  100. package/dist/task/index.js +9 -9
  101. package/dist/task/task.js +56 -56
  102. package/dist/validation/exception.js +36 -36
  103. package/dist/validation/index.js +40 -40
  104. package/dist/validation/validator/array.js +34 -34
  105. package/dist/validation/validator/enum.js +28 -28
  106. package/dist/validation/validator/index.js +14 -14
  107. package/dist/validation/validator/length.js +40 -40
  108. package/dist/validation/validator/max-length.js +35 -35
  109. package/dist/validation/validator/max.js +29 -29
  110. package/dist/validation/validator/min-length.js +33 -33
  111. package/dist/validation/validator/min.js +29 -29
  112. package/dist/validation/validator/not-blank.js +33 -33
  113. package/dist/validation/validator/not-null.js +21 -21
  114. package/dist/validation/validator/plain-obj.js +32 -32
  115. package/dist/validation/validator/regexp.js +34 -34
  116. package/documentation/en/cache.md +56 -0
  117. package/documentation/en/config.md +96 -0
  118. package/documentation/en/engineering.md +256 -0
  119. package/documentation/en/http-client.md +32 -0
  120. package/documentation/en/i18n.md +143 -0
  121. package/documentation/en/index.md +24 -0
  122. package/documentation/en/lock.md +51 -0
  123. package/documentation/en/log.md +109 -0
  124. package/documentation/en/mongodb.md +256 -0
  125. package/documentation/en/mvc.md +688 -0
  126. package/documentation/en/mysql.md +682 -0
  127. package/documentation/en/task.md +45 -0
  128. package/documentation/en/test.md +56 -0
  129. package/documentation/en/validate.md +130 -0
  130. package/documentation/zh-cn/mvc.md +66 -24
  131. package/documentation/zh-cn/mysql.md +146 -17
  132. package/package.json +4 -1
  133. package/skills/wok-server-api-rules/SKILL.md +350 -0
  134. package/skills/wok-server-cache/SKILL.md +216 -0
  135. package/skills/wok-server-code-navigation/SKILL.md +153 -0
  136. package/skills/wok-server-config/SKILL.md +200 -0
  137. package/skills/wok-server-getting-started/SKILL.md +123 -0
  138. package/skills/wok-server-getting-started/references/engineering.md +169 -0
  139. package/skills/wok-server-http-client/SKILL.md +164 -0
  140. package/skills/wok-server-i18n/SKILL.md +214 -0
  141. package/skills/wok-server-lock/SKILL.md +144 -0
  142. package/skills/wok-server-log/SKILL.md +218 -0
  143. package/skills/wok-server-mongodb/SKILL.md +235 -0
  144. package/skills/wok-server-mvc/SKILL.md +251 -0
  145. package/skills/wok-server-mvc/references/respond-html.md +157 -0
  146. package/skills/wok-server-mvc/references/sse.md +121 -0
  147. package/skills/wok-server-mvc/references/static-files.md +47 -0
  148. package/skills/wok-server-mvc/references/upload.md +62 -0
  149. package/skills/wok-server-mvc/references/websocket.md +30 -0
  150. package/skills/wok-server-mysql/SKILL.md +388 -0
  151. package/skills/wok-server-mysql/references/multi-datasource.md +76 -0
  152. package/skills/wok-server-mysql/references/version-control.md +22 -0
  153. package/skills/wok-server-task/SKILL.md +158 -0
  154. package/skills/wok-server-validate/SKILL.md +167 -0
  155. package/src/cache/cache.ts +118 -0
  156. package/src/cache/config.ts +53 -0
  157. package/src/cache/index.ts +27 -0
  158. package/src/cache/purge-task.ts +53 -0
  159. package/src/cache/stat.ts +47 -0
  160. package/src/config/convert.ts +27 -0
  161. package/src/config/exception.ts +8 -0
  162. package/src/config/index.ts +92 -0
  163. package/src/http-client/index.ts +202 -0
  164. package/src/i18n/ar.ts +16 -0
  165. package/src/i18n/de.ts +16 -0
  166. package/src/i18n/en-us.ts +16 -0
  167. package/src/i18n/es.ts +16 -0
  168. package/src/i18n/fr.ts +16 -0
  169. package/src/i18n/i18n.ts +230 -0
  170. package/src/i18n/index.ts +50 -0
  171. package/src/i18n/ja.ts +16 -0
  172. package/src/i18n/ko.ts +16 -0
  173. package/src/i18n/msg.ts +50 -0
  174. package/src/i18n/pt.ts +16 -0
  175. package/src/i18n/ru.ts +16 -0
  176. package/src/i18n/tag.ts +18 -0
  177. package/src/i18n/zh-HK.ts +16 -0
  178. package/src/i18n/zh-TW.ts +16 -0
  179. package/src/i18n/zh-cn.ts +16 -0
  180. package/src/index.ts +11 -0
  181. package/src/lock/index.ts +164 -0
  182. package/src/log/config.ts +71 -0
  183. package/src/log/date.ts +19 -0
  184. package/src/log/file.ts +215 -0
  185. package/src/log/index.ts +136 -0
  186. package/src/log/level.ts +29 -0
  187. package/src/log/log.ts +77 -0
  188. package/src/log/store.ts +31 -0
  189. package/src/mongodb/collection.ts +25 -0
  190. package/src/mongodb/config.ts +69 -0
  191. package/src/mongodb/doc.ts +12 -0
  192. package/src/mongodb/exception.ts +8 -0
  193. package/src/mongodb/index.ts +71 -0
  194. package/src/mongodb/manager/base.ts +674 -0
  195. package/src/mongodb/manager/index.ts +80 -0
  196. package/src/mongodb/manager/tx-strict.ts +153 -0
  197. package/src/mongodb/manager/tx.ts +34 -0
  198. package/src/mongodb/migration.ts +66 -0
  199. package/src/mvc/access-log.ts +33 -0
  200. package/src/mvc/config.ts +70 -0
  201. package/src/mvc/exchange.ts +126 -0
  202. package/src/mvc/handler/index.ts +4 -0
  203. package/src/mvc/handler/json.ts +96 -0
  204. package/src/mvc/handler/restful.ts +39 -0
  205. package/src/mvc/handler/sse.ts +90 -0
  206. package/src/mvc/handler/upload.ts +54 -0
  207. package/src/mvc/index.ts +48 -0
  208. package/src/mvc/interceptor.ts +12 -0
  209. package/src/mvc/query.ts +36 -0
  210. package/src/mvc/render/file.ts +148 -0
  211. package/src/mvc/render/html/html.ts +187 -0
  212. package/src/mvc/render/html/index.ts +16 -0
  213. package/src/mvc/render/html/style.ts +1201 -0
  214. package/src/mvc/render/index.ts +4 -0
  215. package/src/mvc/render/json.ts +24 -0
  216. package/src/mvc/render/text.ts +14 -0
  217. package/src/mvc/router.ts +13 -0
  218. package/src/mvc/server.ts +315 -0
  219. package/src/mvc/static/header.ts +86 -0
  220. package/src/mvc/static/index.ts +3 -0
  221. package/src/mvc/static/mime-type.ts +81 -0
  222. package/src/mvc/static/server-cache-config.ts +92 -0
  223. package/src/mvc/static/server-cache.ts +171 -0
  224. package/src/mvc/static/static-handler.ts +445 -0
  225. package/src/mysql/config.ts +130 -0
  226. package/src/mysql/exception.ts +8 -0
  227. package/src/mysql/index.ts +88 -0
  228. package/src/mysql/manager/base.ts +332 -0
  229. package/src/mysql/manager/index.ts +112 -0
  230. package/src/mysql/manager/ops/count.ts +30 -0
  231. package/src/mysql/manager/ops/criteria.ts +446 -0
  232. package/src/mysql/manager/ops/delete.ts +91 -0
  233. package/src/mysql/manager/ops/exist.ts +41 -0
  234. package/src/mysql/manager/ops/find.ts +209 -0
  235. package/src/mysql/manager/ops/index.ts +13 -0
  236. package/src/mysql/manager/ops/insert.ts +158 -0
  237. package/src/mysql/manager/ops/modify.ts +14 -0
  238. package/src/mysql/manager/ops/order-by.ts +58 -0
  239. package/src/mysql/manager/ops/paginate.ts +100 -0
  240. package/src/mysql/manager/ops/query.ts +13 -0
  241. package/src/mysql/manager/ops/update.ts +318 -0
  242. package/src/mysql/manager/ops/upsert.ts +224 -0
  243. package/src/mysql/manager/ops/utils.ts +24 -0
  244. package/src/mysql/manager/tx-strict.ts +138 -0
  245. package/src/mysql/manager/tx.ts +31 -0
  246. package/src/mysql/manager/utils.ts +75 -0
  247. package/src/mysql/migration.ts +149 -0
  248. package/src/mysql/table-info.ts +41 -0
  249. package/src/task/daily.ts +70 -0
  250. package/src/task/fixed-delay.ts +45 -0
  251. package/src/task/fixed-rate.ts +49 -0
  252. package/src/task/index.ts +4 -0
  253. package/src/task/task.ts +70 -0
  254. package/src/validation/exception.ts +27 -0
  255. package/src/validation/index.ts +61 -0
  256. package/src/validation/validator/array.ts +32 -0
  257. package/src/validation/validator/enum.ts +25 -0
  258. package/src/validation/validator/index.ts +11 -0
  259. package/src/validation/validator/length.ts +42 -0
  260. package/src/validation/validator/max-length.ts +33 -0
  261. package/src/validation/validator/max.ts +26 -0
  262. package/src/validation/validator/min-length.ts +31 -0
  263. package/src/validation/validator/min.ts +26 -0
  264. package/src/validation/validator/not-blank.ts +31 -0
  265. package/src/validation/validator/not-null.ts +19 -0
  266. package/src/validation/validator/plain-obj.ts +30 -0
  267. package/src/validation/validator/regexp.ts +32 -0
  268. package/types/cache/cache.d.ts +52 -52
  269. package/types/cache/config.d.ts +32 -32
  270. package/types/cache/index.d.ts +2 -2
  271. package/types/cache/purge-task.d.ts +11 -11
  272. package/types/cache/stat.d.ts +26 -26
  273. package/types/config/convert.d.ts +6 -6
  274. package/types/config/exception.d.ts +7 -7
  275. package/types/config/index.d.ts +25 -25
  276. package/types/http-client/index.d.ts +71 -71
  277. package/types/i18n/ar.d.ts +2 -2
  278. package/types/i18n/de.d.ts +2 -2
  279. package/types/i18n/en-us.d.ts +2 -2
  280. package/types/i18n/es.d.ts +2 -2
  281. package/types/i18n/fr.d.ts +2 -2
  282. package/types/i18n/i18n.d.ts +102 -102
  283. package/types/i18n/index.d.ts +9 -9
  284. package/types/i18n/ja.d.ts +2 -2
  285. package/types/i18n/ko.d.ts +2 -2
  286. package/types/i18n/msg.d.ts +50 -50
  287. package/types/i18n/pt.d.ts +2 -2
  288. package/types/i18n/ru.d.ts +2 -2
  289. package/types/i18n/tag.d.ts +11 -11
  290. package/types/i18n/zh-HK.d.ts +2 -2
  291. package/types/i18n/zh-TW.d.ts +2 -2
  292. package/types/i18n/zh-cn.d.ts +2 -2
  293. package/types/index.d.ts +11 -11
  294. package/types/lock/index.d.ts +64 -64
  295. package/types/log/config.d.ts +35 -35
  296. package/types/log/date.d.ts +2 -2
  297. package/types/log/file.d.ts +13 -13
  298. package/types/log/index.d.ts +53 -53
  299. package/types/log/level.d.ts +14 -14
  300. package/types/log/log.d.ts +40 -40
  301. package/types/log/store.d.ts +19 -19
  302. package/types/mongodb/collection.d.ts +25 -25
  303. package/types/mongodb/config.d.ts +45 -45
  304. package/types/mongodb/doc.d.ts +11 -11
  305. package/types/mongodb/exception.d.ts +7 -7
  306. package/types/mongodb/index.d.ts +29 -29
  307. package/types/mongodb/manager/base.d.ts +188 -188
  308. package/types/mongodb/manager/index.d.ts +38 -38
  309. package/types/mongodb/manager/tx-strict.d.ts +41 -41
  310. package/types/mongodb/manager/tx.d.ts +21 -21
  311. package/types/mongodb/migration.d.ts +12 -12
  312. package/types/mvc/access-log.d.ts +7 -7
  313. package/types/mvc/config.d.ts +42 -42
  314. package/types/mvc/exchange.d.ts +72 -72
  315. package/types/mvc/handler/index.d.ts +4 -3
  316. package/types/mvc/handler/json.d.ts +44 -44
  317. package/types/mvc/handler/restful.d.ts +11 -11
  318. package/types/mvc/handler/sse.d.ts +34 -0
  319. package/types/mvc/handler/upload.d.ts +36 -36
  320. package/types/mvc/index.d.ts +22 -22
  321. package/types/mvc/interceptor.d.ts +11 -11
  322. package/types/mvc/query.d.ts +13 -13
  323. package/types/mvc/render/file.d.ts +10 -10
  324. package/types/mvc/render/html/html.d.ts +98 -98
  325. package/types/mvc/render/html/index.d.ts +11 -11
  326. package/types/mvc/render/html/style.d.ts +1201 -1201
  327. package/types/mvc/render/index.d.ts +4 -4
  328. package/types/mvc/render/json.d.ts +17 -17
  329. package/types/mvc/render/text.d.ts +10 -10
  330. package/types/mvc/router.d.ts +11 -11
  331. package/types/mvc/server.d.ts +90 -90
  332. package/types/mvc/static/header.d.ts +27 -27
  333. package/types/mvc/static/index.d.ts +3 -3
  334. package/types/mvc/static/mime-type.d.ts +2 -2
  335. package/types/mvc/static/server-cache-config.d.ts +30 -30
  336. package/types/mvc/static/server-cache.d.ts +76 -76
  337. package/types/mvc/static/static-handler.d.ts +77 -77
  338. package/types/mysql/config.d.ts +90 -90
  339. package/types/mysql/exception.d.ts +7 -7
  340. package/types/mysql/index.d.ts +16 -16
  341. package/types/mysql/manager/base.d.ts +196 -165
  342. package/types/mysql/manager/index.d.ts +36 -36
  343. package/types/mysql/manager/ops/count.d.ts +13 -13
  344. package/types/mysql/manager/ops/criteria.d.ts +144 -134
  345. package/types/mysql/manager/ops/delete.d.ts +47 -46
  346. package/types/mysql/manager/ops/exist.d.ts +6 -6
  347. package/types/mysql/manager/ops/find.d.ts +87 -86
  348. package/types/mysql/manager/ops/index.d.ts +12 -10
  349. package/types/mysql/manager/ops/insert.d.ts +32 -18
  350. package/types/mysql/manager/ops/modify.d.ts +3 -3
  351. package/types/mysql/manager/ops/order-by.d.ts +38 -0
  352. package/types/mysql/manager/ops/paginate.d.ts +53 -36
  353. package/types/mysql/manager/ops/query.d.ts +3 -3
  354. package/types/mysql/manager/ops/update.d.ts +99 -76
  355. package/types/mysql/manager/ops/upsert.d.ts +36 -0
  356. package/types/mysql/manager/ops/utils.d.ts +5 -5
  357. package/types/mysql/manager/tx-strict.d.ts +36 -36
  358. package/types/mysql/manager/tx.d.ts +15 -15
  359. package/types/mysql/manager/utils.d.ts +17 -17
  360. package/types/mysql/migration.d.ts +8 -8
  361. package/types/mysql/table-info.d.ts +36 -36
  362. package/types/task/daily.d.ts +16 -16
  363. package/types/task/fixed-delay.d.ts +9 -9
  364. package/types/task/fixed-rate.d.ts +9 -9
  365. package/types/task/index.d.ts +4 -4
  366. package/types/task/task.d.ts +34 -34
  367. package/types/validation/exception.d.ts +38 -38
  368. package/types/validation/index.d.ts +32 -32
  369. package/types/validation/validator/array.d.ts +5 -5
  370. package/types/validation/validator/enum.d.ts +8 -8
  371. package/types/validation/validator/index.d.ts +11 -11
  372. package/types/validation/validator/length.d.ts +10 -10
  373. package/types/validation/validator/max-length.d.ts +8 -8
  374. package/types/validation/validator/max.d.ts +7 -7
  375. package/types/validation/validator/min-length.d.ts +6 -6
  376. package/types/validation/validator/min.d.ts +7 -7
  377. package/types/validation/validator/not-blank.d.ts +7 -7
  378. package/types/validation/validator/not-null.d.ts +6 -6
  379. package/types/validation/validator/plain-obj.d.ts +7 -7
  380. package/types/validation/validator/regexp.d.ts +8 -8
@@ -0,0 +1,31 @@
1
+ import { PoolConnection } from 'mysql2'
2
+ import { BaseMysqlManager } from './base'
3
+ import { MysqlConfig } from '../config'
4
+ import { MysqlException } from '../exception'
5
+
6
+ /**
7
+ * mysql 事务会话.
8
+ */
9
+ export class MysqlTxSession extends BaseMysqlManager {
10
+ /**
11
+ * 中止标识
12
+ */
13
+ #aborted = false
14
+
15
+ constructor(config: MysqlConfig, conn: PoolConnection) {
16
+ super({ config, connection: conn })
17
+ }
18
+
19
+ protected queryWithConnection<T>(queryFn: (conn: PoolConnection) => Promise<T>): Promise<T> {
20
+ if (this.#aborted) {
21
+ throw new MysqlException('Session has been aborted!')
22
+ }
23
+ return super.queryWithConnection(queryFn)
24
+ }
25
+ /**
26
+ * 中止,被中止后的会话不能再进行任何操作
27
+ */
28
+ abort() {
29
+ this.#aborted = true
30
+ }
31
+ }
@@ -0,0 +1,75 @@
1
+ // 工具集,将一些驱动的方法进行 promise 封装,方便操作
2
+ // 程序中没有使用 mysql2/promise ,主要是在测试中发现 mysql2/promise 不是很可靠
3
+ // mysql2/promise 在查询方便处理的不是很好
4
+ // query 查询在没有记录的情况下仍然会返回列表,里面会包含列定义信息,不符合预期
5
+
6
+ import {
7
+ Connection,
8
+ OkPacket,
9
+ Pool,
10
+ PoolConnection,
11
+ ProcedureCallPacket,
12
+ ResultSetHeader,
13
+ RowDataPacket,
14
+ format
15
+ } from 'mysql2'
16
+ import { MysqlConfig } from '../config'
17
+ import { getLogger } from '../../log'
18
+
19
+ /**
20
+ * 查询,适用于各种 sql 的执行
21
+ * @param config
22
+ * @param conn
23
+ * @param sql
24
+ * @param values
25
+ * @returns
26
+ */
27
+ export function promiseQuery(
28
+ config: MysqlConfig,
29
+ conn: Connection,
30
+ sql: string,
31
+ values: any[] = []
32
+ ) {
33
+ return new Promise<
34
+ | OkPacket
35
+ | ResultSetHeader
36
+ | ResultSetHeader[]
37
+ | RowDataPacket[]
38
+ | RowDataPacket[][]
39
+ | OkPacket[]
40
+ | ProcedureCallPacket
41
+ >((res, rej) => {
42
+ const start = new Date().getTime()
43
+ conn.query(sql, values, (err, result) => {
44
+ if (config.slowSqlWarn) {
45
+ const cost = new Date().getTime() - start
46
+ // 慢 sql 警告
47
+ if (cost > config.slowSqlMs) {
48
+ getLogger().warn(`[mysql slow sql] ${cost}ms ${format(sql, values)}`)
49
+ }
50
+ }
51
+ if (err) {
52
+ rej(err)
53
+ } else {
54
+ res(result)
55
+ }
56
+ })
57
+ })
58
+ }
59
+
60
+ /**
61
+ * 获取连接
62
+ * @param pool
63
+ * @returns
64
+ */
65
+ export function promiseGetConnection(pool: Pool) {
66
+ return new Promise<PoolConnection>((res, rej) => {
67
+ pool.getConnection((err, conn) => {
68
+ if (err) {
69
+ rej(err)
70
+ } else {
71
+ res(conn)
72
+ }
73
+ })
74
+ })
75
+ }
@@ -0,0 +1,149 @@
1
+ import { existsSync, readdirSync, readFileSync, statSync } from 'fs'
2
+ import { Connection, RowDataPacket } from 'mysql2'
3
+ import { isAbsolute, resolve } from 'path'
4
+ import { getLogger } from '../log'
5
+ import { MysqlConfig } from './config'
6
+ import { MysqlException } from './exception'
7
+ import { promiseQuery } from './manager/utils'
8
+
9
+ /**
10
+ * 版本信息.
11
+ */
12
+ interface MysqlVersion {
13
+ version: number
14
+ filePath: string
15
+ }
16
+
17
+ /**
18
+ * 迁移.
19
+ * @param config
20
+ * @param conn
21
+ */
22
+ export async function migrate(config: MysqlConfig, conn: Connection) {
23
+ const versionDir = config.versionControlDir
24
+ // 查找文件
25
+ const dir = isAbsolute(versionDir) ? versionDir : resolve(process.cwd(), versionDir)
26
+ if (!existsSync(dir)) {
27
+ throw new Error(`Directory ${versionDir} does not exist`)
28
+ }
29
+ const versions: MysqlVersion[] = []
30
+ // 忽略隐藏文件
31
+ const files = readdirSync(dir).filter(file => !file.startsWith('.'))
32
+ for (const file of files) {
33
+ const filePath = resolve(dir, file)
34
+ const stat = statSync(filePath)
35
+ if (!stat.isFile()) {
36
+ continue
37
+ }
38
+ if (!file.endsWith('.sql')) {
39
+ throw new Error(`版本文件名没有以 .sql 为后缀:${file}`)
40
+ }
41
+ const version = parseInt(file.substring(0, file.length - 4))
42
+ if (isNaN(version)) {
43
+ throw new Error(`Version file is not named with a number:${file}`)
44
+ }
45
+ versions.push({ version, filePath })
46
+ }
47
+ // 排序,判定顺序
48
+ versions.sort((o1, o2) => o1.version - o2.version)
49
+ for (let i = 0; i < versions.length; i++) {
50
+ const version = versions[i]
51
+ if (version.version !== i + 1) {
52
+ throw new Error(
53
+ `The SQL version number must start from 1 and increment one by one,error version:${version.version}`
54
+ )
55
+ }
56
+ }
57
+ await createVersionTableIfNotExist(config, conn)
58
+
59
+ // 在事务中执行版本管理,主要目的是为了通过锁来协调多个进程同时启动的情况
60
+ // 事务不能保存一个版本处理成功就完整回退,如有错误,仍然需要手动调整后再操作
61
+ await promiseQuery(config, conn, `SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED`)
62
+ await new Promise<void>((resolve, reject) => {
63
+ conn.beginTransaction(err => {
64
+ if (err) {
65
+ reject(err)
66
+ } else {
67
+ resolve()
68
+ }
69
+ })
70
+ })
71
+ try {
72
+ // 执行 sql, 判定当前版本
73
+ let currentVersion = await getCurrentVersion(config, conn)
74
+ if (typeof currentVersion !== 'number') {
75
+ // 插入初始版本号
76
+ await promiseQuery(config, conn, 'insert `db_version`(`version`) values (0)')
77
+ }
78
+ const filnalCurrentVersion = currentVersion || 0
79
+ const pendingVersions = versions.filter(ver => ver.version > filnalCurrentVersion)
80
+ if (!pendingVersions.length) {
81
+ getLogger().info('The SQL version is already the latest.')
82
+ return
83
+ }
84
+ const nextVersion = filnalCurrentVersion + 1
85
+ if (pendingVersions[0].version !== nextVersion) {
86
+ throw new MysqlException(
87
+ `MySQL migration error, the next version should be ${nextVersion},but current is ${pendingVersions[0].version}`
88
+ )
89
+ }
90
+
91
+ for (const verion of pendingVersions) {
92
+ getLogger().info(`Mysql migrating, version: ${verion.version}`)
93
+ let sql = readFileSync(verion.filePath, { encoding: 'utf-8' })
94
+ await promiseQuery(config, conn, sql)
95
+ // 版本号
96
+ await promiseQuery(config, conn, `UPDATE db_version SET version=${verion.version};`)
97
+ }
98
+ // 提交
99
+ await new Promise<void>((resolve, reject) => {
100
+ conn.commit(err => {
101
+ if (err) {
102
+ reject(err)
103
+ } else {
104
+ resolve()
105
+ }
106
+ })
107
+ })
108
+ getLogger().info('Mysql migration finished.')
109
+ } catch (e) {
110
+ // 异常回退,仅能回退 dml 操作,对 ddl 无效
111
+ await new Promise<void>((resolve, reject) => {
112
+ conn.rollback(err => {
113
+ if (err) {
114
+ reject(err)
115
+ } else {
116
+ resolve()
117
+ }
118
+ })
119
+ })
120
+ throw e
121
+ }
122
+ }
123
+
124
+ async function createVersionTableIfNotExist(config: MysqlConfig, conn: Connection): Promise<void> {
125
+ await promiseQuery(
126
+ config,
127
+ conn,
128
+ 'CREATE TABLE IF NOT EXISTS `db_version` (' +
129
+ ' `version` int NOT NULL,' +
130
+ ' PRIMARY KEY (`version`)' +
131
+ ') ENGINE = innodb DEFAULT CHARACTER SET = "utf8mb4" ' +
132
+ 'COLLATE = "utf8mb4_unicode_ci";'
133
+ )
134
+ }
135
+ /**
136
+ * 获取当前版本,使用 for update 加锁,用于协调多进程并发场景
137
+ * @param config
138
+ * @param conn
139
+ * @returns
140
+ */
141
+ async function getCurrentVersion(config: MysqlConfig, conn: Connection): Promise<number | null> {
142
+ const res = await promiseQuery(config, conn, 'select version from `db_version` for update')
143
+ const rows = res as RowDataPacket[]
144
+ if (rows.length >= 1) {
145
+ return rows[0].version
146
+ } else {
147
+ return null
148
+ }
149
+ }
@@ -0,0 +1,41 @@
1
+ import { notBlank, ValidationOpts } from '../validation'
2
+
3
+ /**
4
+ * 表信息. 表的字段分为三个部分:主键、普通列、时间列,分别对应的属性是:id、columns
5
+ * 和 createDate 还有 updatedDate,这三部分配置的字段名称不允许有重叠,否则会产生错误.
6
+ */
7
+ export interface Table<T> {
8
+ /**
9
+ * 表名.
10
+ */
11
+ tableName: string
12
+ /**
13
+ * id 字段名称.
14
+ */
15
+ id: keyof T
16
+ /**
17
+ * 列字段名称.只有配置了名称的字段才会参与数据库的查询与更新,没有配置的其它字段可作其它用途。
18
+ * 注意:columns 配置的字段不能和 id 或更新时间和创建时间重叠,否则在更新时产生错误,将数据改错。
19
+ * 程序本身是不会做检查的,编写的时候必须要注意。
20
+ */
21
+ columns: Array<keyof T>
22
+ /**
23
+ * 创建时间字段信息.
24
+ */
25
+ createdDate?: {
26
+ column: keyof T
27
+ type: 'number' | 'date'
28
+ }
29
+ /**
30
+ * 更新时间字段信息.
31
+ */
32
+ updatedDate?: {
33
+ column: keyof T
34
+ type: 'number' | 'date'
35
+ }
36
+ }
37
+
38
+ export const tableValidation: ValidationOpts<Table<any>> = {
39
+ tableName: [notBlank('表名不能为空')],
40
+ id: [notBlank('id 不能为空')]
41
+ }
@@ -0,0 +1,70 @@
1
+ import { max, min, notNull, validate } from '../validation'
2
+ import { Task, TaskController, execTask } from './task'
3
+
4
+ /**
5
+ * 每日任务.
6
+ * @param hours 时
7
+ * @param minutes 分
8
+ * @param task 要执行的任务
9
+ * @param timeout 任务超时时间,单位毫秒
10
+ * @returns
11
+ */
12
+ export function scheduleDailyTask(
13
+ hours: number,
14
+ minutes: number,
15
+ task: Task,
16
+ timeout?: number
17
+ ): TaskController {
18
+ // 校验
19
+ validate(
20
+ { hours, minutes },
21
+ {
22
+ hours: [notNull(), min(0), max(23)],
23
+ minutes: [notNull(), min(0), max(59)]
24
+ }
25
+ )
26
+ const taskController = new TaskController()
27
+ const delay = dailyTaskDelay(hours, minutes)
28
+ setTimeout(() => exec(hours, minutes, task, taskController, timeout), delay)
29
+ return taskController
30
+ }
31
+ /**
32
+ * 计算到下次指定时间点的延迟
33
+ * @param hours
34
+ * @param minutes
35
+ */
36
+ export function dailyTaskDelay(hours: number, minutes: number): number {
37
+ const now = new Date()
38
+ let todayTime = new Date()
39
+ todayTime.setHours(hours)
40
+ todayTime.setMinutes(minutes)
41
+ todayTime.setSeconds(0)
42
+ todayTime.setMilliseconds(0)
43
+ // 如果今天还没有到指定的点,今天就执行,否则明天执行
44
+ if (todayTime > now) {
45
+ return todayTime.getTime() - now.getTime()
46
+ }
47
+ // 明天时间
48
+ const oneDayMilliseconds = 1000 * 3600 * 24
49
+ const tomorrowTime = todayTime.getTime() + oneDayMilliseconds
50
+ return tomorrowTime - now.getTime()
51
+ }
52
+
53
+ function exec(
54
+ hours: number,
55
+ minutes: number,
56
+ task: Task,
57
+ controller: TaskController,
58
+ timeout?: number
59
+ ) {
60
+ Promise.resolve()
61
+ .then(async () => {
62
+ if (controller.isStopped()) {
63
+ return
64
+ }
65
+ await execTask(task, timeout)
66
+ const delay = dailyTaskDelay(hours, minutes)
67
+ setTimeout(() => exec(hours, minutes, task, controller), delay)
68
+ })
69
+ .catch(console.error)
70
+ }
@@ -0,0 +1,45 @@
1
+ import { getLockManager } from '../lock'
2
+ import { getLogger } from '../log'
3
+ import { max, min, notNull, validate } from '../validation'
4
+ import { Task, TaskController, execTask } from './task'
5
+
6
+ /**
7
+ * 固定延迟执行任务
8
+ * @param initialDelay 第一次执行延迟的时间,单位秒
9
+ * @param delay 每次的延迟时间,单位秒
10
+ * @param task 任务
11
+ * @param timeout 任务超时时间,单位毫秒
12
+ */
13
+ export function scheduleWithFixedDelay(
14
+ initialDelay: number,
15
+ delay: number,
16
+ task: Task,
17
+ timeout?: number
18
+ ): TaskController {
19
+ validate(
20
+ { initialDelay, delay },
21
+ {
22
+ initialDelay: [notNull(), min(0), max(3600 * 24)],
23
+ delay: [notNull(), min(1), max(3600 * 24)]
24
+ }
25
+ )
26
+ const controller = new TaskController()
27
+ setTimeout(() => exec(delay, task, controller, timeout), initialDelay * 1000)
28
+ return controller
29
+ }
30
+
31
+ function exec(delay: number, task: Task, controller: TaskController, timeout?: number) {
32
+ Promise.resolve()
33
+ .then(async () => {
34
+ if (controller.isStopped()) {
35
+ return
36
+ }
37
+ await execTask(task, timeout)
38
+ // 下次执行
39
+ setTimeout(() => exec(delay, task, controller), delay * 1000)
40
+ })
41
+ .catch(e => {
42
+ getLogger().error(`EXEC TASK ERROR: ${task.name}`, e)
43
+ })
44
+ .catch(console.error)
45
+ }
@@ -0,0 +1,49 @@
1
+ import { getLogger } from '../log'
2
+ import { max, min, notNull, validate } from '../validation'
3
+ import { Task, TaskController, execTask } from './task'
4
+
5
+ /**
6
+ * 固定延迟执行任务
7
+ * @param initialDelay 第一次执行延迟的时间,单位秒
8
+ * @param period 每次的延迟时间,单位秒
9
+ * @param task 任务
10
+ * @param timeout 任务超时时间,单位毫秒
11
+ */
12
+ export function scheduleWithFixedRate(
13
+ initialDelay: number,
14
+ period: number,
15
+ task: Task,
16
+ timeout?: number
17
+ ): TaskController {
18
+ validate(
19
+ { initialDelay, period },
20
+ {
21
+ initialDelay: [notNull(), min(0), max(3600 * 24)],
22
+ period: [notNull(), min(1), max(3600 * 24)]
23
+ }
24
+ )
25
+
26
+ const taskController = new TaskController()
27
+ setTimeout(() => exec(period, task, taskController, timeout), initialDelay * 1000)
28
+ return taskController
29
+ }
30
+
31
+ function exec(fixedDelay: number, task: Task, controller: TaskController, timeout?: number) {
32
+ Promise.resolve()
33
+ .then(async () => {
34
+ if (controller.isStopped()) {
35
+ return
36
+ }
37
+ const res = await execTask(task, timeout)
38
+ // 下次执行
39
+ let delay = res.start + fixedDelay * 1000 - new Date().getTime()
40
+ if (delay < 0) {
41
+ delay = 0
42
+ }
43
+ setTimeout(() => exec(fixedDelay, task, controller), delay)
44
+ })
45
+ .catch(e => {
46
+ getLogger().error(`EXEC TASK ERROR: ${task.name}`, e)
47
+ })
48
+ .catch(console.error)
49
+ }
@@ -0,0 +1,4 @@
1
+ export { Task, TaskController } from './task'
2
+ export * from './fixed-delay'
3
+ export * from './fixed-rate'
4
+ export * from './daily'
@@ -0,0 +1,70 @@
1
+ import { getLogger } from '../log'
2
+
3
+ /**
4
+ * 任务.
5
+ */
6
+ export interface Task {
7
+ /**
8
+ * 任务的名称,用于跟踪任务的执行情况,定位错误.
9
+ * 当任务执行时间过长或任务失败时,相关的错误提示信息会显示名称,以便于排查.
10
+ */
11
+ name: string
12
+ /**
13
+ * 任务运行.
14
+ * @returns
15
+ */
16
+ run: () => Promise<void>
17
+ }
18
+
19
+ /**
20
+ * 任务控制器
21
+ */
22
+ export class TaskController {
23
+ #stopped = false
24
+ isStopped() {
25
+ return this.#stopped
26
+ }
27
+
28
+ stop() {
29
+ this.#stopped = true
30
+ }
31
+ }
32
+
33
+ /**
34
+ * 任务执行,封装任务执行过程中的一些通用信息输出和异常控制.
35
+ * @param task
36
+ * @param timeout 任务超时时间,单位毫秒
37
+ * @returns
38
+ */
39
+ export async function execTask(
40
+ task: Task,
41
+ timeout?: number
42
+ ): Promise<{ start: number; cost: number; end: number }> {
43
+ const start = new Date().getTime()
44
+ try {
45
+ getLogger().debug(`START TASK:${task.name}`)
46
+ // 支持任务超时设置
47
+ if (timeout && timeout > 0) {
48
+ await Promise.race([
49
+ task.run(),
50
+ new Promise<void>((_, reject) => {
51
+ setTimeout(() => {
52
+ reject('The task has timed out.')
53
+ }, timeout)
54
+ })
55
+ ])
56
+ } else {
57
+ await task.run()
58
+ }
59
+ } catch (e) {
60
+ getLogger().error(`TASK ERROR: ${task.name}`, e)
61
+ }
62
+ const end = Date.now()
63
+ const cost = end - start
64
+ if (cost > 1000 * 60 * 5) {
65
+ getLogger().warn(`Task "${task.name}" takes too long ,cost ${cost}ms`)
66
+ } else {
67
+ getLogger().debug(`Task "${task.name}" has finished, taking a total of ${cost} milliseconds.`)
68
+ }
69
+ return { start, cost, end }
70
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * 校验异常.
3
+ */
4
+ export class ValidationException extends Error {
5
+ constructor(
6
+ /**
7
+ * 异常信息,如 “不能为空” 之类的.
8
+ */
9
+ readonly errMsg: string,
10
+ /**
11
+ * 校验器名称,如 length 、notNull 之类的.
12
+ */
13
+ readonly validator: string,
14
+ /**
15
+ * 校验出错的路径.
16
+ */
17
+ readonly propertyPath: string,
18
+ /**
19
+ * 值
20
+ */
21
+ readonly val: any
22
+ ) {
23
+ super(
24
+ `Field "${propertyPath}" failed to validate by validator ${validator} ,value:${val},info:${errMsg}`
25
+ )
26
+ }
27
+ }
@@ -0,0 +1,61 @@
1
+ import { ValidationException } from './exception'
2
+ /**
3
+ * 校验结果。message:错误信息,反馈给调用处;validator 校验器名称,用于记录错误信息来自哪个校验器,
4
+ * 以便于程序在出错时知道信息来自哪里。
5
+ */
6
+ export type ValidationResult =
7
+ | { ok: true }
8
+ | {
9
+ ok: false
10
+ message: string
11
+ validator: string
12
+ /**
13
+ * 如果校验的是层级深的对象,内部的属性发生了错误,可用于标记属性的路径
14
+ */
15
+ propPath?: string[]
16
+ }
17
+ /**
18
+ * 校验器.
19
+ */
20
+ export type PropValidator<T> = (val: T) => ValidationResult
21
+
22
+ /**
23
+ * 对象的校验选项
24
+ */
25
+ export type ValidationOpts<T> = Partial<{ [key in keyof T]: PropValidator<T[key]>[] }>
26
+
27
+ /**
28
+ * 校验对象.
29
+ * @param obj
30
+ */
31
+ export function validate<T>(obj: T, opts: ValidationOpts<T>) {
32
+ for (const entry of Object.entries(opts)) {
33
+ const [prop, validators] = entry
34
+ const val = obj[prop as keyof T]
35
+ for (const validator of validators as PropValidator<any>[]) {
36
+ const result = validator(val)
37
+ if (!result.ok) {
38
+ const propPath = [prop]
39
+ if (result.propPath) {
40
+ propPath.push(...result.propPath)
41
+ }
42
+ const fullPath = propPath
43
+ .map((prop, idx) => {
44
+ if (idx === 0) {
45
+ return prop
46
+ }
47
+ if (prop.startsWith('[') && prop.endsWith(']')) {
48
+ return prop
49
+ }
50
+ return '.' + prop
51
+ })
52
+ .join('')
53
+ throw new ValidationException(result.message, result.validator, fullPath, val)
54
+ }
55
+ }
56
+ }
57
+ }
58
+
59
+ // 导出
60
+ export * from './exception'
61
+ export * from './validator'
@@ -0,0 +1,32 @@
1
+ import { PropValidator } from '..'
2
+ import { getI18n } from '../../i18n'
3
+
4
+ /**
5
+ * 校验数组的条目.
6
+ */
7
+ export function array<T>(opts: PropValidator<T>[]): PropValidator<T[] | undefined> {
8
+ const validator = 'array'
9
+ return val => {
10
+ if (!val) {
11
+ return { ok: true }
12
+ }
13
+ if (!Array.isArray(val)) {
14
+ return { ok: false, validator, message: getI18n().buildMsg('validate-err-array') }
15
+ }
16
+ // 条目处理
17
+ for (let i = 0; i < val.length; i++) {
18
+ const item = val[i] as T
19
+ for (const validation of opts) {
20
+ const result = validation(item)
21
+ if (!result.ok) {
22
+ const propPath = [`[${i}]`]
23
+ if (result.propPath) {
24
+ propPath.push(...result.propPath)
25
+ }
26
+ return { ok: false, validator, message: result.message, propPath }
27
+ }
28
+ }
29
+ }
30
+ return { ok: true }
31
+ }
32
+ }
@@ -0,0 +1,25 @@
1
+ import { PropValidator } from '..'
2
+ import { getI18n } from '../../i18n'
3
+ /**
4
+ * 枚举,校验值必须是指定列表中的一个.
5
+ * @param list 支持的值列表,仅支持数字和字符串类型
6
+ * @param msg
7
+ * @returns
8
+ */
9
+ export function enumerate<T>(list: (number | string)[], msg?: string): PropValidator<T> {
10
+ const validator = 'enumerate'
11
+ return val => {
12
+ if (!val) {
13
+ return { ok: true }
14
+ }
15
+ if (!list.some(item => item === val)) {
16
+ return {
17
+ ok: false,
18
+ validator,
19
+ // must be one of [1,2,3]
20
+ message: msg || getI18n().buildMsg('validate-err-enum', `[${list.join(',')}]`)
21
+ }
22
+ }
23
+ return { ok: true }
24
+ }
25
+ }
@@ -0,0 +1,11 @@
1
+ export * from './not-null'
2
+ export * from './not-blank'
3
+ export * from './max'
4
+ export * from './min'
5
+ export * from './regexp'
6
+ export * from './length'
7
+ export * from './enum'
8
+ export * from './array'
9
+ export * from './plain-obj'
10
+ export * from './max-length'
11
+ export * from './min-length'