wok-server 0.4.13 → 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 (376) 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 -29
  31. package/dist/log/date.js +21 -21
  32. package/dist/log/file.js +198 -72
  33. package/dist/log/index.js +135 -105
  34. package/dist/log/level.js +33 -33
  35. package/dist/log/log.js +56 -0
  36. package/dist/log/store.js +19 -16
  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 -231
  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 -130
  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 -100
  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/engineering.md +1 -1
  129. package/documentation/zh-cn/log.md +81 -8
  130. package/documentation/zh-cn/mvc.md +66 -24
  131. package/documentation/zh-cn/mysql.md +24 -23
  132. package/documentation/zh-cn/validate.md +2 -2
  133. package/package.json +3 -1
  134. package/skills/wok-server-api-rules/SKILL.md +350 -0
  135. package/skills/wok-server-cache/SKILL.md +216 -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 +315 -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 +285 -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 +412 -0
  232. package/src/mysql/manager/ops/delete.ts +96 -0
  233. package/src/mysql/manager/ops/exist.ts +41 -0
  234. package/src/mysql/manager/ops/find.ts +226 -0
  235. package/src/mysql/manager/ops/index.ts +11 -0
  236. package/src/mysql/manager/ops/insert.ts +120 -0
  237. package/src/mysql/manager/ops/modify.ts +14 -0
  238. package/src/mysql/manager/ops/paginate.ts +60 -0
  239. package/src/mysql/manager/ops/query.ts +13 -0
  240. package/src/mysql/manager/ops/update.ts +294 -0
  241. package/src/mysql/manager/ops/utils.ts +20 -0
  242. package/src/mysql/manager/tx-strict.ts +138 -0
  243. package/src/mysql/manager/tx.ts +31 -0
  244. package/src/mysql/manager/utils.ts +75 -0
  245. package/src/mysql/migration.ts +149 -0
  246. package/src/mysql/table-info.ts +41 -0
  247. package/src/task/daily.ts +70 -0
  248. package/src/task/fixed-delay.ts +45 -0
  249. package/src/task/fixed-rate.ts +49 -0
  250. package/src/task/index.ts +4 -0
  251. package/src/task/task.ts +70 -0
  252. package/src/validation/exception.ts +27 -0
  253. package/src/validation/index.ts +61 -0
  254. package/src/validation/validator/array.ts +32 -0
  255. package/src/validation/validator/enum.ts +25 -0
  256. package/src/validation/validator/index.ts +11 -0
  257. package/src/validation/validator/length.ts +42 -0
  258. package/src/validation/validator/max-length.ts +33 -0
  259. package/src/validation/validator/max.ts +26 -0
  260. package/src/validation/validator/min-length.ts +31 -0
  261. package/src/validation/validator/min.ts +26 -0
  262. package/src/validation/validator/not-blank.ts +31 -0
  263. package/src/validation/validator/not-null.ts +19 -0
  264. package/src/validation/validator/plain-obj.ts +30 -0
  265. package/src/validation/validator/regexp.ts +32 -0
  266. package/types/cache/cache.d.ts +52 -52
  267. package/types/cache/config.d.ts +32 -32
  268. package/types/cache/index.d.ts +2 -2
  269. package/types/cache/purge-task.d.ts +11 -11
  270. package/types/cache/stat.d.ts +26 -26
  271. package/types/config/convert.d.ts +6 -6
  272. package/types/config/exception.d.ts +7 -7
  273. package/types/config/index.d.ts +25 -25
  274. package/types/http-client/index.d.ts +71 -71
  275. package/types/i18n/ar.d.ts +2 -2
  276. package/types/i18n/de.d.ts +2 -2
  277. package/types/i18n/en-us.d.ts +2 -2
  278. package/types/i18n/es.d.ts +2 -2
  279. package/types/i18n/fr.d.ts +2 -2
  280. package/types/i18n/i18n.d.ts +102 -102
  281. package/types/i18n/index.d.ts +9 -9
  282. package/types/i18n/ja.d.ts +2 -2
  283. package/types/i18n/ko.d.ts +2 -2
  284. package/types/i18n/msg.d.ts +50 -50
  285. package/types/i18n/pt.d.ts +2 -2
  286. package/types/i18n/ru.d.ts +2 -2
  287. package/types/i18n/tag.d.ts +11 -11
  288. package/types/i18n/zh-HK.d.ts +2 -2
  289. package/types/i18n/zh-TW.d.ts +2 -2
  290. package/types/i18n/zh-cn.d.ts +2 -2
  291. package/types/index.d.ts +11 -11
  292. package/types/lock/index.d.ts +64 -64
  293. package/types/log/config.d.ts +35 -27
  294. package/types/log/date.d.ts +2 -2
  295. package/types/log/file.d.ts +13 -5
  296. package/types/log/index.d.ts +53 -34
  297. package/types/log/level.d.ts +14 -14
  298. package/types/log/log.d.ts +40 -0
  299. package/types/log/store.d.ts +19 -12
  300. package/types/mongodb/collection.d.ts +25 -25
  301. package/types/mongodb/config.d.ts +45 -45
  302. package/types/mongodb/doc.d.ts +11 -11
  303. package/types/mongodb/exception.d.ts +7 -7
  304. package/types/mongodb/index.d.ts +29 -29
  305. package/types/mongodb/manager/base.d.ts +188 -188
  306. package/types/mongodb/manager/index.d.ts +38 -38
  307. package/types/mongodb/manager/tx-strict.d.ts +41 -41
  308. package/types/mongodb/manager/tx.d.ts +21 -21
  309. package/types/mongodb/migration.d.ts +12 -12
  310. package/types/mvc/access-log.d.ts +7 -7
  311. package/types/mvc/config.d.ts +42 -42
  312. package/types/mvc/exchange.d.ts +72 -72
  313. package/types/mvc/handler/index.d.ts +4 -3
  314. package/types/mvc/handler/json.d.ts +44 -44
  315. package/types/mvc/handler/restful.d.ts +11 -11
  316. package/types/mvc/handler/sse.d.ts +34 -0
  317. package/types/mvc/handler/upload.d.ts +36 -36
  318. package/types/mvc/index.d.ts +22 -22
  319. package/types/mvc/interceptor.d.ts +11 -11
  320. package/types/mvc/query.d.ts +13 -13
  321. package/types/mvc/render/file.d.ts +10 -10
  322. package/types/mvc/render/html/html.d.ts +98 -98
  323. package/types/mvc/render/html/index.d.ts +11 -11
  324. package/types/mvc/render/html/style.d.ts +1201 -1201
  325. package/types/mvc/render/index.d.ts +4 -4
  326. package/types/mvc/render/json.d.ts +17 -17
  327. package/types/mvc/render/text.d.ts +10 -10
  328. package/types/mvc/router.d.ts +11 -11
  329. package/types/mvc/server.d.ts +90 -90
  330. package/types/mvc/static/header.d.ts +27 -27
  331. package/types/mvc/static/index.d.ts +3 -3
  332. package/types/mvc/static/mime-type.d.ts +2 -2
  333. package/types/mvc/static/server-cache-config.d.ts +30 -30
  334. package/types/mvc/static/server-cache.d.ts +76 -76
  335. package/types/mvc/static/static-handler.d.ts +77 -77
  336. package/types/mysql/config.d.ts +90 -90
  337. package/types/mysql/exception.d.ts +7 -7
  338. package/types/mysql/index.d.ts +16 -16
  339. package/types/mysql/manager/base.d.ts +165 -159
  340. package/types/mysql/manager/index.d.ts +36 -36
  341. package/types/mysql/manager/ops/count.d.ts +13 -13
  342. package/types/mysql/manager/ops/criteria.d.ts +134 -134
  343. package/types/mysql/manager/ops/delete.d.ts +46 -46
  344. package/types/mysql/manager/ops/exist.d.ts +6 -6
  345. package/types/mysql/manager/ops/find.d.ts +86 -70
  346. package/types/mysql/manager/ops/index.d.ts +10 -10
  347. package/types/mysql/manager/ops/insert.d.ts +18 -18
  348. package/types/mysql/manager/ops/modify.d.ts +3 -3
  349. package/types/mysql/manager/ops/paginate.d.ts +36 -36
  350. package/types/mysql/manager/ops/query.d.ts +3 -3
  351. package/types/mysql/manager/ops/update.d.ts +76 -76
  352. package/types/mysql/manager/ops/utils.d.ts +5 -5
  353. package/types/mysql/manager/tx-strict.d.ts +36 -35
  354. package/types/mysql/manager/tx.d.ts +15 -15
  355. package/types/mysql/manager/utils.d.ts +17 -17
  356. package/types/mysql/migration.d.ts +8 -8
  357. package/types/mysql/table-info.d.ts +36 -36
  358. package/types/task/daily.d.ts +16 -16
  359. package/types/task/fixed-delay.d.ts +9 -9
  360. package/types/task/fixed-rate.d.ts +9 -9
  361. package/types/task/index.d.ts +4 -4
  362. package/types/task/task.d.ts +34 -34
  363. package/types/validation/exception.d.ts +38 -38
  364. package/types/validation/index.d.ts +32 -32
  365. package/types/validation/validator/array.d.ts +5 -5
  366. package/types/validation/validator/enum.d.ts +8 -8
  367. package/types/validation/validator/index.d.ts +11 -11
  368. package/types/validation/validator/length.d.ts +10 -10
  369. package/types/validation/validator/max-length.d.ts +8 -8
  370. package/types/validation/validator/max.d.ts +7 -7
  371. package/types/validation/validator/min-length.d.ts +6 -6
  372. package/types/validation/validator/min.d.ts +7 -7
  373. package/types/validation/validator/not-blank.d.ts +7 -7
  374. package/types/validation/validator/not-null.d.ts +6 -6
  375. package/types/validation/validator/plain-obj.d.ts +7 -7
  376. package/types/validation/validator/regexp.d.ts +8 -8
@@ -0,0 +1,80 @@
1
+ import { Db, MongoClient, ReadConcernLike, ReadPreferenceLike, WriteConcern } from 'mongodb'
2
+ import { MongoDBConfig } from '../config'
3
+ import { MongoDBException } from '../exception'
4
+ import { BaseMongoManager } from './base'
5
+ import { MongoTxSession } from './tx'
6
+ import { MongoStrictTxSession } from './tx-strict'
7
+
8
+ /**
9
+ * mysql 分页查询结果
10
+ */
11
+ export interface MongoPage<T> {
12
+ total: number
13
+ list: T[]
14
+ }
15
+
16
+ /**
17
+ * mongodb 管理器,目前尚未实现事务的处理.
18
+ */
19
+ export class MongoDBManager extends BaseMongoManager {
20
+ /**
21
+ * mongodb 管理器构建
22
+ * @param db 库
23
+ */
24
+ constructor(config: MongoDBConfig, db: Db, private readonly client: MongoClient) {
25
+ super(config, db)
26
+ }
27
+ /**
28
+ * 事务操作。mongodb 的版本必须在 4.0 以上,连接的必须是副本集节点或分片集群的mongos节点。
29
+ * @param ops 操作逻辑,所有事务相关的操作都必须使用函数提供的 session 对象
30
+ * @param opts mongo 事务选项
31
+ */
32
+ async tx<T>(
33
+ ops: (session: MongoTxSession) => Promise<T>,
34
+ opts?: {
35
+ /** 超时时间,单位毫秒,设置后会覆盖全局设置,设置为0表示不限制 */
36
+ timeout?: number
37
+ /** A default read concern for commands in this transaction */
38
+ readConcern?: ReadConcernLike
39
+ /** A default writeConcern for commands in this transaction */
40
+ writeConcern?: WriteConcern
41
+ /** A default read preference for commands in this transaction */
42
+ readPreference?: ReadPreferenceLike
43
+ }
44
+ ): Promise<T> {
45
+ const timeout =
46
+ opts && typeof opts.timeout === 'number' ? opts.timeout : this.config.transactionTimeout
47
+ const nativeSession = this.client.startSession()
48
+ nativeSession.startTransaction(opts)
49
+ const txSesssion = this.config.transactionStrict
50
+ ? new MongoStrictTxSession(this.config, this.db, nativeSession)
51
+ : new MongoTxSession(this.config, this.db, nativeSession)
52
+ try {
53
+ const result =
54
+ timeout > 0
55
+ ? await Promise.race([
56
+ ops(txSesssion),
57
+ new Promise<T>((resolve, reject) => {
58
+ setTimeout(() => {
59
+ // 立即中止会话,防止再有后续操作
60
+ txSesssion.abort()
61
+ reject(new MongoDBException('Transaction timeout !'))
62
+ }, timeout)
63
+ })
64
+ ])
65
+ : await ops(txSesssion)
66
+ await nativeSession.commitTransaction()
67
+ return result
68
+ } catch (error) {
69
+ await nativeSession.abortTransaction()
70
+ // 将原错误抛出,如果有需要,调用处可对异常做进一步的处理
71
+ throw error
72
+ } finally {
73
+ // 无论如何中止会话,离开事务,会话就不能再被使用
74
+ txSesssion.abort()
75
+ await nativeSession.endSession()
76
+ }
77
+ }
78
+ }
79
+
80
+ export { BaseMongoManager, MongoTxSession }
@@ -0,0 +1,153 @@
1
+ import { ClientSession, Db, Document, Filter, UpdateFilter } from 'mongodb'
2
+ import { MongoCollection } from '../collection'
3
+ import { MongoDBConfig } from '../config'
4
+ import { MongoDocId, MongoDocWithId } from '../doc'
5
+ import { MongoDBException } from '../exception'
6
+ import { MongoPage } from './base'
7
+ import { MongoTxSession } from './tx'
8
+
9
+ /**
10
+ * 严格事务会话
11
+ */
12
+ export class MongoStrictTxSession extends MongoTxSession {
13
+ #opsCount = 0
14
+ constructor(config: MongoDBConfig, db: Db, session: ClientSession) {
15
+ super(config, db, session)
16
+ }
17
+ /**
18
+ * 为操作计数,检查是否操作次数过多.
19
+ */
20
+ #checkAndAddOpsCount() {
21
+ if (this.#opsCount >= 10) {
22
+ throw new MongoDBException('Too many operations in a strict transaction.')
23
+ }
24
+ this.#opsCount++
25
+ }
26
+
27
+ findById<T extends Document>(
28
+ coll: MongoCollection<T>,
29
+ id: MongoDocId
30
+ ): Promise<MongoDocWithId<T> | null> {
31
+ this.#checkAndAddOpsCount()
32
+ return super.findById(coll, id)
33
+ }
34
+
35
+ findByIdIn<T extends Document>(
36
+ coll: MongoCollection<T>,
37
+ ids: MongoDocId[]
38
+ ): Promise<MongoDocWithId<T>[]> {
39
+ if (ids.length > 100) {
40
+ throw new MongoDBException(
41
+ `The augument ids length(${ids.length}) passed to findByIdIn in a strict transaction is too large .`
42
+ )
43
+ }
44
+ this.#checkAndAddOpsCount()
45
+ return super.findByIdIn(coll, ids)
46
+ }
47
+
48
+ existsBy<T extends Document>(
49
+ coll: MongoCollection<T>,
50
+ filter: Filter<MongoDocWithId<T>>
51
+ ): Promise<boolean> {
52
+ this.#checkAndAddOpsCount()
53
+ return super.existsBy(coll, filter)
54
+ }
55
+
56
+ deleteById<T extends Document>(coll: MongoCollection<T>, id: MongoDocId): Promise<boolean> {
57
+ this.#checkAndAddOpsCount()
58
+ return super.deleteById(coll, id)
59
+ }
60
+
61
+ deleteOne<T extends Document>(coll: MongoCollection<T>, filter: Partial<T>): Promise<boolean> {
62
+ this.#checkAndAddOpsCount()
63
+ return super.deleteOne(coll, filter)
64
+ }
65
+
66
+ deleteMany<T extends Document>(
67
+ coll: MongoCollection<T>,
68
+ filter: Filter<MongoDocWithId<T>>
69
+ ): Promise<number> {
70
+ throw new MongoDBException('Prohibited to use deleteMany in a strict transaction.')
71
+ }
72
+
73
+ findAll<T extends Document>(coll: MongoCollection<T>): Promise<MongoDocWithId<T>[]> {
74
+ throw new MongoDBException('Prohibited to use findAll in a strict transaction.')
75
+ }
76
+
77
+ findFirst<T extends Document>(
78
+ coll: MongoCollection<T>,
79
+ filter: Filter<MongoDocWithId<T>>
80
+ ): Promise<MongoDocWithId<T> | null> {
81
+ this.#checkAndAddOpsCount()
82
+ return super.findFirst(coll, filter)
83
+ }
84
+
85
+ insert<T extends Document>(
86
+ coll: MongoCollection<T>,
87
+ data: T & { _id?: MongoDocId | undefined }
88
+ ): Promise<MongoDocWithId<T>> {
89
+ this.#checkAndAddOpsCount()
90
+ return super.insert(coll, data)
91
+ }
92
+
93
+ insertMany<T extends Document>(
94
+ coll: MongoCollection<T>,
95
+ list: (T & { _id?: MongoDocId | undefined })[]
96
+ ): Promise<MongoDocWithId<T>[]> {
97
+ throw new MongoDBException('Prohibited to use insertMany in a strict transaction.')
98
+ }
99
+
100
+ update<T extends Document>(
101
+ coll: MongoCollection<T>,
102
+ data: MongoDocWithId<T>
103
+ ): Promise<MongoDocWithId<T>> {
104
+ this.#checkAndAddOpsCount()
105
+ return super.update(coll, data)
106
+ }
107
+
108
+ partialUpdate<T extends Document>(
109
+ coll: MongoCollection<T>,
110
+ id: MongoDocId,
111
+ updator: UpdateFilter<T>
112
+ ): Promise<boolean> {
113
+ this.#checkAndAddOpsCount()
114
+ return super.partialUpdate(coll, id, updator)
115
+ }
116
+
117
+ updateMany<T extends Document>(
118
+ coll: MongoCollection<T>,
119
+ filter: Filter<MongoDocWithId<T>>,
120
+ updator: UpdateFilter<T>
121
+ ): Promise<number> {
122
+ throw new MongoDBException('Prohibited to use updateMany in a strict transaction.')
123
+ }
124
+
125
+ find<T extends Document>(
126
+ coll: MongoCollection<T>,
127
+ filter: Filter<MongoDocWithId<T>>,
128
+ opts?:
129
+ | {
130
+ offset?: number | undefined
131
+ limit?: number | undefined
132
+ orderBy?: ['_id' | keyof T, 'asc' | 'desc'][] | undefined
133
+ }
134
+ | undefined
135
+ ): Promise<MongoDocWithId<T>[]> {
136
+ throw new MongoDBException('Prohibited to use find in a strict transaction.')
137
+ }
138
+
139
+ count<T extends Document>(
140
+ coll: MongoCollection<T>,
141
+ filter: Filter<MongoDocWithId<T>>
142
+ ): Promise<number> {
143
+ throw new MongoDBException('Prohibited to use count in a strict transaction.')
144
+ }
145
+
146
+ paginate<T extends Document>(
147
+ coll: MongoCollection<T>,
148
+ filter: Filter<MongoDocWithId<T>>,
149
+ opts: { pn: number; pz: number; orderBy?: ['_id' | keyof T, 'asc' | 'desc'][] | undefined }
150
+ ): Promise<MongoPage<MongoDocWithId<T>>> {
151
+ throw new MongoDBException('Prohibited to use paginate in a strict transaction.')
152
+ }
153
+ }
@@ -0,0 +1,34 @@
1
+ import { ClientSession, Db } from 'mongodb'
2
+ import { MongoDBConfig } from '../config'
3
+ import { MongoDBException } from '../exception'
4
+ import { BaseMongoManager } from './base'
5
+ /**
6
+ * 事务会话
7
+ */
8
+ export class MongoTxSession extends BaseMongoManager {
9
+ /**
10
+ * 中止标识
11
+ */
12
+ #aborted = false
13
+
14
+ constructor(config: MongoDBConfig, db: Db, session: ClientSession) {
15
+ super(config, db, session)
16
+ }
17
+
18
+ protected timingQuery<T, D extends { op: string; coll: string }>(opts: {
19
+ query: () => Promise<T>
20
+ desc: () => D
21
+ }): Promise<T> {
22
+ if (this.#aborted) {
23
+ throw new MongoDBException('Session has been aborted!')
24
+ }
25
+ return super.timingQuery(opts)
26
+ }
27
+
28
+ /**
29
+ * 中止,被中止后的会话不能再进行任何操作
30
+ */
31
+ abort() {
32
+ this.#aborted = true
33
+ }
34
+ }
@@ -0,0 +1,66 @@
1
+ import { Db } from 'mongodb'
2
+ import { MongoDBException } from './exception'
3
+ import { getLogger } from '../log'
4
+
5
+ /**
6
+ * 迁移版本,是一个函数,可以在函数的内部通过 mongodb 驱动提升的 api 来完成操作。
7
+ * 注:驱动里有些 api 是没有的,和 mongodb 的脚本有区分,但是有些是可以通过 db.command() 来替代的。
8
+ */
9
+ export type MongoMigrationVersion = (db: Db) => Promise<void>
10
+
11
+ /**
12
+ * 迁移
13
+ * @param db
14
+ * @param versionList
15
+ */
16
+ export async function migrate(db: Db, versionList: MongoMigrationVersion[]) {
17
+ let currentVersion = await getCurrentVersion(db)
18
+ // 逐个执行,迁移执行的逻辑是无法提供事务支持的
19
+ // 版本管理代码是自定义的,无法做到强制绑定 session
20
+ // 一旦出错,只能手动处理数据库,然后再重新执行程序,和 mysql 一样
21
+ for (let idx = 0; idx < versionList.length; idx++) {
22
+ if (idx <= currentVersion) {
23
+ continue
24
+ }
25
+ const migrationVersion = versionList[idx]
26
+ getLogger().info(`MongoDB migrating, version: ${idx}`)
27
+ await migrationVersion(db)
28
+ await updateVersion(db, idx)
29
+ }
30
+ }
31
+
32
+ /**
33
+ * 版本管理集合.
34
+ */
35
+ interface VersionColl {
36
+ _id: string
37
+ version: number
38
+ }
39
+
40
+ const VERSION_COLLECTION_NAME = 'db_version'
41
+ const VERSION_RECORD_ID = 'db_version'
42
+
43
+ async function getCurrentVersion(db: Db): Promise<number> {
44
+ const res = await db
45
+ .collection<VersionColl>(VERSION_COLLECTION_NAME)
46
+ .findOne({ _id: VERSION_RECORD_ID })
47
+ return res ? res.version : -1
48
+ }
49
+
50
+ /**
51
+ * 更新版本号
52
+ * @param db
53
+ * @param version
54
+ */
55
+ async function updateVersion(db: Db, version: number) {
56
+ const collection = db.collection<VersionColl>(VERSION_COLLECTION_NAME)
57
+ const res = await collection.findOne({ _id: VERSION_RECORD_ID })
58
+ if (res) {
59
+ const rs = await collection.updateOne({ _id: VERSION_RECORD_ID }, { $set: { version } })
60
+ if (rs.modifiedCount !== 1) {
61
+ throw new MongoDBException('Failed to update version.')
62
+ }
63
+ } else {
64
+ await collection.insertOne({ _id: VERSION_RECORD_ID, version: version })
65
+ }
66
+ }
@@ -0,0 +1,33 @@
1
+ import { getLogger } from '../log'
2
+ import { formatDateTime } from '../log/date'
3
+ import { Interceptor } from './interceptor'
4
+
5
+ /**
6
+ * 访问日志拦截器,记录请求信息
7
+ * @param exchange
8
+ * @param next
9
+ */
10
+ export const accessLogInterceptor: Interceptor = async (exchange, next) => {
11
+ const start = new Date().getTime()
12
+ exchange.response.once('close', () => {
13
+ const userAgent = exchange.request.headers['user-agent']
14
+ const referer = exchange.request.headers['referer']
15
+ const ip = exchange.request.socket.remoteAddress
16
+ const { url, method } = exchange.request
17
+ const status = exchange.response.statusCode
18
+ const rt = new Date().getTime() - start
19
+ getLogger().info(
20
+ `[access-log]${JSON.stringify({
21
+ method,
22
+ url,
23
+ ip,
24
+ userAgent,
25
+ referer,
26
+ start: formatDateTime(new Date(start)),
27
+ rt,
28
+ status
29
+ })}`
30
+ )
31
+ })
32
+ await next()
33
+ }
@@ -0,0 +1,70 @@
1
+ import { generateConfig } from '../config'
2
+ import { max, min, notBlank, notNull } from '../validation'
3
+
4
+ /**
5
+ * mvc 模块配置.
6
+ */
7
+ export interface WebConfig {
8
+ /**
9
+ * 端口号
10
+ */
11
+ port: number
12
+ /**
13
+ * 超时时间
14
+ */
15
+ timeout: number
16
+ /**
17
+ * 是否开启访问日志.
18
+ */
19
+ accessLog: boolean
20
+ /**
21
+ * 跨域允许的源域名
22
+ */
23
+ corsAllowOrigin: string
24
+ /**
25
+ * 跨域允许的消息头
26
+ */
27
+ corsAllowHeaders: string
28
+ /**
29
+ * 跨域允许的请求方法
30
+ */
31
+ corsAllowMethods: string
32
+ /**
33
+ * 是否激活安全传输层
34
+ */
35
+ tlsEnable: boolean
36
+ /**
37
+ * pem 格式证书公钥文件路径
38
+ */
39
+ tlsCert: string
40
+ /**
41
+ * pem 格式证书私钥文件路径
42
+ */
43
+ tlsKey: string
44
+ }
45
+
46
+ export function getConfig() {
47
+ return generateConfig<WebConfig>(
48
+ {
49
+ port: 8080,
50
+ timeout: 30000,
51
+ accessLog: false,
52
+ corsAllowHeaders: '*',
53
+ corsAllowMethods: '*',
54
+ corsAllowOrigin: '*',
55
+ tlsEnable: false,
56
+ tlsKey: '',
57
+ tlsCert: ''
58
+ },
59
+ 'SERVER',
60
+ {
61
+ port: [notNull(), min(80), max(65535)],
62
+ timeout: [notNull(), min(1000), max(600000)],
63
+ accessLog: [notNull()],
64
+ corsAllowOrigin: [notBlank()],
65
+ corsAllowHeaders: [notBlank()],
66
+ corsAllowMethods: [notBlank()],
67
+ tlsEnable: [notNull()]
68
+ }
69
+ )
70
+ }
@@ -0,0 +1,126 @@
1
+ import { IncomingMessage, ServerResponse } from 'http'
2
+ import { QueryString } from './query'
3
+ import { HtmlStuct, renderError, renderFile, renderHtml, renderJson } from './render'
4
+ import { renderText } from './render/text'
5
+
6
+ /**
7
+ * 服务的数据交换对象.
8
+ */
9
+ export class ServerExchange {
10
+ #bufferPromise?: Promise<Buffer>
11
+
12
+ constructor(readonly request: IncomingMessage, readonly response: ServerResponse) {}
13
+
14
+ bodyBuffer(): Promise<Buffer> {
15
+ if (this.#bufferPromise) {
16
+ return this.#bufferPromise
17
+ }
18
+ this.#bufferPromise = new Promise<Buffer>((resolve, reject) => {
19
+ if (this.request.readableEnded) {
20
+ throw new Error('Request has ended!')
21
+ }
22
+ let body: Buffer[] = []
23
+ this.request
24
+ .resume()
25
+ .on('error', reject)
26
+ .on('data', chunk => body.push(chunk))
27
+ .on('end', () => resolve(Buffer.concat(body)))
28
+ })
29
+ return this.#bufferPromise
30
+ }
31
+
32
+ async bodyText(): Promise<string> {
33
+ const buffer = await this.bodyBuffer()
34
+ return buffer.toString('utf-8')
35
+ }
36
+
37
+ async bodyJson<T>(): Promise<T> {
38
+ const buffer = await this.bodyBuffer()
39
+ const bodyText = buffer.toString('utf-8')
40
+ if (!bodyText || !bodyText.trim()) {
41
+ return {} as any
42
+ }
43
+ return JSON.parse(bodyText)
44
+ }
45
+ /**
46
+ * 响应纯文本
47
+ * @param text 文本内容
48
+ * @param status 状态码,可选,默认 200
49
+ */
50
+ respondText(text: string, status?: number) {
51
+ renderText(this.response, text, status)
52
+ }
53
+
54
+ /**
55
+ * 响应 json
56
+ * @param json 任意可被 json 序列化的对象
57
+ * @param status 状态码,可选,默认 200
58
+ */
59
+ respondJson(json: any, status?: number) {
60
+ renderJson(this.response, json, status)
61
+ }
62
+ /**
63
+ * 响应错误信息提示,提供一个统一的格式封装,json 格式
64
+ * @param message 消息
65
+ * @param status 状态码,默认 400 ,表示业务错误
66
+ * @returns
67
+ */
68
+ respondErrMsg(message: string, status?: number) {
69
+ renderError(this.response, message, status)
70
+ }
71
+ /**
72
+ * 响应文件
73
+ * @param filePath 文件路径,绝对路径
74
+ * @param download 是否下载模式
75
+ * @returns
76
+ */
77
+ respondFile(filePath: string, download?: boolean) {
78
+ return renderFile(this.request, this.response, filePath, download)
79
+ }
80
+ /**
81
+ * 响应 html
82
+ * @param html html 内容,一个特定结构的对象或者是字符串
83
+ * @param status 状态码,可选,默认 200
84
+ */
85
+ respondHtml(html: HtmlStuct | string, status?: number) {
86
+ renderHtml(this.response, html, status)
87
+ }
88
+
89
+ /**
90
+ * 响应
91
+ * @param opts
92
+ */
93
+ respond(opts: {
94
+ /**
95
+ * 状态码.
96
+ */
97
+ statusCode: number
98
+ /**
99
+ * 响应正文内容.
100
+ */
101
+ body?: string | Buffer | Uint8Array
102
+ /**
103
+ * 自定义消息头
104
+ */
105
+ headers?: Record<string, string>
106
+ }) {
107
+ this.response.statusCode = opts.statusCode
108
+ if (opts.headers) {
109
+ for (const key in opts.headers) {
110
+ this.response.setHeader(key, opts.headers[key])
111
+ }
112
+ }
113
+ if (opts.body) {
114
+ this.response.write(opts.body)
115
+ }
116
+ this.response.end()
117
+ }
118
+
119
+ /**
120
+ * 解析 queryString
121
+ * @returns
122
+ */
123
+ parseQueryString() {
124
+ return new QueryString(this.request.url || '')
125
+ }
126
+ }
@@ -0,0 +1,4 @@
1
+ export * from './json'
2
+ export * from './upload'
3
+ export * from './restful'
4
+ export * from './sse'
@@ -0,0 +1,96 @@
1
+ import { IncomingMessage } from 'http'
2
+ import { getCache } from '../../cache'
3
+ import { getI18n } from '../../i18n'
4
+ import { validate, ValidationOpts } from '../../validation'
5
+ import { ServerExchange } from '../exchange'
6
+ import { RouterHandler } from '../router'
7
+
8
+ export interface JsonHandlerExchange {
9
+ /**
10
+ * 请求信息
11
+ */
12
+ request: IncomingMessage
13
+ }
14
+
15
+ /**
16
+ * 创建 json 处理器..
17
+ * @param <REQ> 表示请求的 json 数据格式类型
18
+ * @param <RES> 表示响应的类型,可选,如果不需要响应 json 数据,则方法可以不返回任何值
19
+ * @param opts
20
+ * @returns
21
+ */
22
+ export function createJsonHandler<REQ, RES = void>(opts: {
23
+ /**
24
+ * 缓存设置,通过框架的 cache 模块来缓存响应信息,只能缓存有效的响应信息,如果没有响应正文则不会进行缓存,
25
+ * 参数和 handle 是一样的
26
+ * @param body
27
+ * @param exchange
28
+ * @returns 返回缓存的 key 和缓存秒数
29
+ */
30
+ cache?: (
31
+ body: REQ,
32
+ exchange: JsonHandlerExchange
33
+ ) =>
34
+ | Promise<{ key: string; expiresInSeconds?: number }>
35
+ | { key: string; expiresInSeconds?: number }
36
+ /**
37
+ * 校验信息,可选,用于检查请求信息.对于一些特殊情况,无法使用校验器的,可以在 handle 中继续处理.
38
+ */
39
+ validation?: ValidationOpts<REQ> | (() => ValidationOpts<REQ>)
40
+ /**
41
+ * 处理请求.
42
+ * @param body 正文内容
43
+ * @param exchange 请求传输对象,用于获取请求的基本信息
44
+ * @returns
45
+ */
46
+ handle: (body: REQ, exchange: JsonHandlerExchange) => Promise<RES>
47
+ }): RouterHandler {
48
+ return async function (exchange: ServerExchange) {
49
+ if (!exchange.request.method || exchange.request.method.toUpperCase() !== 'POST') {
50
+ exchange.respondErrMsg('Method Not Allowed', 405)
51
+ return
52
+ }
53
+ const body: REQ = await exchange.bodyJson()
54
+ if (opts.validation) {
55
+ // 切换语言
56
+ getI18n().switchByRequest(exchange.request.headers)
57
+ if (typeof opts.validation === 'function') {
58
+ validate(body, opts.validation())
59
+ } else {
60
+ validate(body, opts.validation)
61
+ }
62
+ }
63
+ // 缓存处理
64
+ if (opts.cache) {
65
+ const cacheInfo = await opts.cache(body, exchange)
66
+ const buffer = getCache().get(cacheInfo.key)
67
+ if (buffer && buffer instanceof Buffer) {
68
+ renderJsonBuffer(exchange, buffer)
69
+ } else {
70
+ const res = await opts.handle(body, { request: exchange.request })
71
+ if (!res) {
72
+ // 无结果不缓存
73
+ exchange.respond({ statusCode: 200 })
74
+ return
75
+ }
76
+ const buffer = Buffer.from(JSON.stringify(res), 'utf-8')
77
+ getCache().put(cacheInfo.key, buffer, cacheInfo.expiresInSeconds)
78
+ renderJsonBuffer(exchange, buffer)
79
+ }
80
+ return
81
+ }
82
+ const res = await opts.handle(body, { request: exchange.request })
83
+ if (!res) {
84
+ exchange.respond({ statusCode: 200 })
85
+ return
86
+ }
87
+ exchange.respondJson(res)
88
+ }
89
+ }
90
+
91
+ function renderJsonBuffer(exchange: ServerExchange, buffer: Buffer) {
92
+ const { response } = exchange
93
+ response.setHeader('content-type', 'application/json; charset=UTF-8')
94
+ response.statusCode = 200
95
+ response.end(buffer)
96
+ }