wok-server 0.1.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 (216) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +47 -0
  3. package/dist/cache/cache.js +94 -0
  4. package/dist/cache/config.js +19 -0
  5. package/dist/cache/index.js +27 -0
  6. package/dist/cache/purge-task.js +56 -0
  7. package/dist/cache/stat.js +47 -0
  8. package/dist/config/convert.js +36 -0
  9. package/dist/config/exception.js +14 -0
  10. package/dist/config/index.js +67 -0
  11. package/dist/http-client/index.js +132 -0
  12. package/dist/i18n/ar.js +17 -0
  13. package/dist/i18n/de.js +17 -0
  14. package/dist/i18n/en-us.js +17 -0
  15. package/dist/i18n/es.js +17 -0
  16. package/dist/i18n/fr.js +17 -0
  17. package/dist/i18n/i18n.js +231 -0
  18. package/dist/i18n/index.js +52 -0
  19. package/dist/i18n/ja.js +17 -0
  20. package/dist/i18n/ko.js +17 -0
  21. package/dist/i18n/msg.js +2 -0
  22. package/dist/i18n/pt.js +17 -0
  23. package/dist/i18n/ru.js +17 -0
  24. package/dist/i18n/tag.js +18 -0
  25. package/dist/i18n/zh-HK.js +17 -0
  26. package/dist/i18n/zh-TW.js +17 -0
  27. package/dist/i18n/zh-cn.js +17 -0
  28. package/dist/index.js +13 -0
  29. package/dist/log/config.js +28 -0
  30. package/dist/log/date.js +21 -0
  31. package/dist/log/file.js +79 -0
  32. package/dist/log/index.js +109 -0
  33. package/dist/log/level.js +39 -0
  34. package/dist/log/store.js +16 -0
  35. package/dist/mongodb/collection.js +2 -0
  36. package/dist/mongodb/config.js +34 -0
  37. package/dist/mongodb/doc.js +2 -0
  38. package/dist/mongodb/exception.js +14 -0
  39. package/dist/mongodb/index.js +58 -0
  40. package/dist/mongodb/manager/base.js +563 -0
  41. package/dist/mongodb/manager/index.js +63 -0
  42. package/dist/mongodb/manager/tx-strict.js +84 -0
  43. package/dist/mongodb/manager/tx.js +30 -0
  44. package/dist/mongodb/migration.js +52 -0
  45. package/dist/mvc/access-log.js +31 -0
  46. package/dist/mvc/config.js +20 -0
  47. package/dist/mvc/exchange.js +113 -0
  48. package/dist/mvc/handler/index.js +6 -0
  49. package/dist/mvc/handler/json.js +33 -0
  50. package/dist/mvc/handler/restful.js +35 -0
  51. package/dist/mvc/handler/upload.js +33 -0
  52. package/dist/mvc/index.js +316 -0
  53. package/dist/mvc/interceptor.js +2 -0
  54. package/dist/mvc/query.js +43 -0
  55. package/dist/mvc/render/file.js +177 -0
  56. package/dist/mvc/render/html/html.js +90 -0
  57. package/dist/mvc/render/html/index.js +18 -0
  58. package/dist/mvc/render/html/style.js +2 -0
  59. package/dist/mvc/render/index.js +7 -0
  60. package/dist/mvc/render/json.js +26 -0
  61. package/dist/mvc/render/text.js +16 -0
  62. package/dist/mvc/router.js +2 -0
  63. package/dist/mysql/config.js +49 -0
  64. package/dist/mysql/exception.js +14 -0
  65. package/dist/mysql/index.js +85 -0
  66. package/dist/mysql/manager/base.js +233 -0
  67. package/dist/mysql/manager/index.js +107 -0
  68. package/dist/mysql/manager/ops/count.js +20 -0
  69. package/dist/mysql/manager/ops/criteria.js +326 -0
  70. package/dist/mysql/manager/ops/delete.js +65 -0
  71. package/dist/mysql/manager/ops/exist.js +26 -0
  72. package/dist/mysql/manager/ops/find.js +111 -0
  73. package/dist/mysql/manager/ops/index.js +14 -0
  74. package/dist/mysql/manager/ops/insert.js +101 -0
  75. package/dist/mysql/manager/ops/modify.js +10 -0
  76. package/dist/mysql/manager/ops/paginate.js +23 -0
  77. package/dist/mysql/manager/ops/query.js +9 -0
  78. package/dist/mysql/manager/ops/update.js +201 -0
  79. package/dist/mysql/manager/tx-strict.js +98 -0
  80. package/dist/mysql/manager/tx.js +30 -0
  81. package/dist/mysql/manager/utils.js +56 -0
  82. package/dist/mysql/migration.js +136 -0
  83. package/dist/mysql/table-info.js +8 -0
  84. package/dist/task/daily.js +58 -0
  85. package/dist/task/fixed-delay.js +33 -0
  86. package/dist/task/fixed-rate.js +37 -0
  87. package/dist/task/index.js +9 -0
  88. package/dist/task/task.js +39 -0
  89. package/dist/validation/exception.js +44 -0
  90. package/dist/validation/index.js +29 -0
  91. package/dist/validation/validator/array.js +38 -0
  92. package/dist/validation/validator/enum.js +28 -0
  93. package/dist/validation/validator/index.js +14 -0
  94. package/dist/validation/validator/length.js +40 -0
  95. package/dist/validation/validator/max-length.js +35 -0
  96. package/dist/validation/validator/max.js +29 -0
  97. package/dist/validation/validator/min-length.js +33 -0
  98. package/dist/validation/validator/min.js +29 -0
  99. package/dist/validation/validator/not-blank.js +33 -0
  100. package/dist/validation/validator/not-null.js +21 -0
  101. package/dist/validation/validator/plain-obj.js +32 -0
  102. package/dist/validation/validator/regexp.js +30 -0
  103. package/documentation/en/index.md +1 -0
  104. package/documentation/zh-cn/cache.md +59 -0
  105. package/documentation/zh-cn/config.md +68 -0
  106. package/documentation/zh-cn/http-client.md +33 -0
  107. package/documentation/zh-cn/i18n.md +154 -0
  108. package/documentation/zh-cn/index.md +25 -0
  109. package/documentation/zh-cn/log.md +40 -0
  110. package/documentation/zh-cn/mongodb.md +262 -0
  111. package/documentation/zh-cn/mvc.md +430 -0
  112. package/documentation/zh-cn/mysql.md +389 -0
  113. package/documentation/zh-cn/task.md +50 -0
  114. package/documentation/zh-cn/test.md +57 -0
  115. package/documentation/zh-cn/validate.md +125 -0
  116. package/package.json +46 -0
  117. package/types/cache/cache.d.ts +52 -0
  118. package/types/cache/config.d.ts +32 -0
  119. package/types/cache/index.d.ts +2 -0
  120. package/types/cache/purge-task.d.ts +11 -0
  121. package/types/cache/stat.d.ts +26 -0
  122. package/types/config/convert.d.ts +6 -0
  123. package/types/config/exception.d.ts +7 -0
  124. package/types/config/index.d.ts +15 -0
  125. package/types/http-client/index.d.ts +71 -0
  126. package/types/i18n/ar.d.ts +2 -0
  127. package/types/i18n/de.d.ts +2 -0
  128. package/types/i18n/en-us.d.ts +2 -0
  129. package/types/i18n/es.d.ts +2 -0
  130. package/types/i18n/fr.d.ts +2 -0
  131. package/types/i18n/i18n.d.ts +102 -0
  132. package/types/i18n/index.d.ts +9 -0
  133. package/types/i18n/ja.d.ts +2 -0
  134. package/types/i18n/ko.d.ts +2 -0
  135. package/types/i18n/msg.d.ts +50 -0
  136. package/types/i18n/pt.d.ts +2 -0
  137. package/types/i18n/ru.d.ts +2 -0
  138. package/types/i18n/tag.d.ts +11 -0
  139. package/types/i18n/zh-HK.d.ts +2 -0
  140. package/types/i18n/zh-TW.d.ts +2 -0
  141. package/types/i18n/zh-cn.d.ts +2 -0
  142. package/types/index.d.ts +10 -0
  143. package/types/log/config.d.ts +27 -0
  144. package/types/log/date.d.ts +2 -0
  145. package/types/log/file.d.ts +5 -0
  146. package/types/log/index.d.ts +34 -0
  147. package/types/log/level.d.ts +15 -0
  148. package/types/log/store.d.ts +12 -0
  149. package/types/mongodb/collection.d.ts +25 -0
  150. package/types/mongodb/config.d.ts +45 -0
  151. package/types/mongodb/doc.d.ts +11 -0
  152. package/types/mongodb/exception.d.ts +7 -0
  153. package/types/mongodb/index.d.ts +29 -0
  154. package/types/mongodb/manager/base.d.ts +188 -0
  155. package/types/mongodb/manager/index.d.ts +38 -0
  156. package/types/mongodb/manager/tx-strict.d.ts +41 -0
  157. package/types/mongodb/manager/tx.d.ts +21 -0
  158. package/types/mongodb/migration.d.ts +12 -0
  159. package/types/mvc/access-log.d.ts +7 -0
  160. package/types/mvc/config.d.ts +30 -0
  161. package/types/mvc/exchange.d.ts +72 -0
  162. package/types/mvc/handler/index.d.ts +3 -0
  163. package/types/mvc/handler/json.d.ts +23 -0
  164. package/types/mvc/handler/restful.d.ts +11 -0
  165. package/types/mvc/handler/upload.d.ts +40 -0
  166. package/types/mvc/index.d.ts +49 -0
  167. package/types/mvc/interceptor.d.ts +11 -0
  168. package/types/mvc/query.d.ts +13 -0
  169. package/types/mvc/render/file.d.ts +10 -0
  170. package/types/mvc/render/html/html.d.ts +98 -0
  171. package/types/mvc/render/html/index.d.ts +11 -0
  172. package/types/mvc/render/html/style.d.ts +1201 -0
  173. package/types/mvc/render/index.d.ts +4 -0
  174. package/types/mvc/render/json.d.ts +17 -0
  175. package/types/mvc/render/text.d.ts +10 -0
  176. package/types/mvc/router.d.ts +11 -0
  177. package/types/mysql/config.d.ts +86 -0
  178. package/types/mysql/exception.d.ts +7 -0
  179. package/types/mysql/index.d.ts +16 -0
  180. package/types/mysql/manager/base.d.ts +158 -0
  181. package/types/mysql/manager/index.d.ts +36 -0
  182. package/types/mysql/manager/ops/count.d.ts +13 -0
  183. package/types/mysql/manager/ops/criteria.d.ts +120 -0
  184. package/types/mysql/manager/ops/delete.d.ts +46 -0
  185. package/types/mysql/manager/ops/exist.d.ts +6 -0
  186. package/types/mysql/manager/ops/find.d.ts +66 -0
  187. package/types/mysql/manager/ops/index.d.ts +10 -0
  188. package/types/mysql/manager/ops/insert.d.ts +18 -0
  189. package/types/mysql/manager/ops/modify.d.ts +3 -0
  190. package/types/mysql/manager/ops/paginate.d.ts +36 -0
  191. package/types/mysql/manager/ops/query.d.ts +3 -0
  192. package/types/mysql/manager/ops/update.d.ts +70 -0
  193. package/types/mysql/manager/tx-strict.d.ts +34 -0
  194. package/types/mysql/manager/tx.d.ts +15 -0
  195. package/types/mysql/manager/utils.d.ts +17 -0
  196. package/types/mysql/migration.d.ts +8 -0
  197. package/types/mysql/table-info.d.ts +36 -0
  198. package/types/task/daily.d.ts +15 -0
  199. package/types/task/fixed-delay.d.ts +8 -0
  200. package/types/task/fixed-rate.d.ts +8 -0
  201. package/types/task/index.d.ts +4 -0
  202. package/types/task/task.d.ts +33 -0
  203. package/types/validation/exception.d.ts +43 -0
  204. package/types/validation/index.d.ts +32 -0
  205. package/types/validation/validator/array.d.ts +5 -0
  206. package/types/validation/validator/enum.d.ts +8 -0
  207. package/types/validation/validator/index.d.ts +11 -0
  208. package/types/validation/validator/length.d.ts +10 -0
  209. package/types/validation/validator/max-length.d.ts +8 -0
  210. package/types/validation/validator/max.d.ts +7 -0
  211. package/types/validation/validator/min-length.d.ts +6 -0
  212. package/types/validation/validator/min.d.ts +7 -0
  213. package/types/validation/validator/not-blank.d.ts +7 -0
  214. package/types/validation/validator/not-null.d.ts +6 -0
  215. package/types/validation/validator/plain-obj.d.ts +7 -0
  216. package/types/validation/validator/regexp.d.ts +8 -0
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.min = void 0;
4
+ const i18n_1 = require("../../i18n");
5
+ /**
6
+ * 最大值校验.
7
+ * @param max 最大值
8
+ * @param msg 错误消息
9
+ */
10
+ function min(min, msg) {
11
+ const validator = 'min';
12
+ return val => {
13
+ if (val == undefined || val === null) {
14
+ return { ok: true };
15
+ }
16
+ if (typeof val !== 'number') {
17
+ return { ok: false, validator, message: (0, i18n_1.getI18n)().buildMsg('validate-err-numer') };
18
+ }
19
+ if (val < min) {
20
+ return {
21
+ ok: false,
22
+ validator,
23
+ message: msg || (0, i18n_1.getI18n)().buildMsg('validate-err-min', `${min}`)
24
+ };
25
+ }
26
+ return { ok: true };
27
+ };
28
+ }
29
+ exports.min = min;
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.notBlank = void 0;
4
+ const i18n_1 = require("../../i18n");
5
+ /**
6
+ * 字符串非空校验,以下的情况不会通过校验:undefined,null,非 string 类型,空白字符串.
7
+ * @param message
8
+ * @returns
9
+ */
10
+ function notBlank(message) {
11
+ const validator = 'notBlank';
12
+ return val => {
13
+ if (val === undefined || val === null) {
14
+ return {
15
+ ok: false,
16
+ validator,
17
+ message: message || (0, i18n_1.getI18n)().buildMsg('validate-err-empty')
18
+ };
19
+ }
20
+ if (typeof val !== 'string') {
21
+ return { ok: false, validator, message: (0, i18n_1.getI18n)().buildMsg('validate-err-string') };
22
+ }
23
+ if (!val.trim()) {
24
+ return {
25
+ ok: false,
26
+ validator,
27
+ message: message || (0, i18n_1.getI18n)().buildMsg('validate-err-empty')
28
+ };
29
+ }
30
+ return { ok: true };
31
+ };
32
+ }
33
+ exports.notBlank = notBlank;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.notNull = void 0;
4
+ const i18n_1 = require("../../i18n");
5
+ /**
6
+ * 非空校验.
7
+ * @param message
8
+ */
9
+ function notNull(message) {
10
+ return val => {
11
+ if (val === null || val === undefined) {
12
+ return {
13
+ ok: false,
14
+ message: message || (0, i18n_1.getI18n)().buildMsg('validate-err-empty'),
15
+ validator: 'notNull'
16
+ };
17
+ }
18
+ return { ok: true };
19
+ };
20
+ }
21
+ exports.notNull = notNull;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.plainObject = void 0;
4
+ /**
5
+ * 普通对象校验.
6
+ * @param opts
7
+ * @returns
8
+ */
9
+ function plainObject(opts) {
10
+ const validator = 'plainObject';
11
+ return val => {
12
+ if (!val) {
13
+ return { ok: true };
14
+ }
15
+ for (const entry of Object.entries(opts)) {
16
+ const [prop, validators] = entry;
17
+ const v = val[prop];
18
+ for (const validate of validators) {
19
+ const result = validate(v);
20
+ if (!result.ok) {
21
+ const propPath = [prop];
22
+ if (result.propPath) {
23
+ propPath.push(...result.propPath);
24
+ }
25
+ return { ok: false, validator, message: result.message, propPath };
26
+ }
27
+ }
28
+ }
29
+ return { ok: true };
30
+ };
31
+ }
32
+ exports.plainObject = plainObject;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.regexp = void 0;
4
+ const i18n_1 = require("../../i18n");
5
+ /**
6
+ * 正则校验
7
+ * @param pattern 正则表达式
8
+ * @param msg 错误消息
9
+ * @returns
10
+ */
11
+ function regexp(pattern, msg) {
12
+ const validator = 'regexp';
13
+ return val => {
14
+ if (val === undefined || val === null) {
15
+ return { ok: true };
16
+ }
17
+ if (typeof val !== 'string') {
18
+ return { ok: false, validator, message: (0, i18n_1.getI18n)().buildMsg('validate-err-string') };
19
+ }
20
+ if (!pattern.test(val)) {
21
+ return {
22
+ ok: false,
23
+ validator,
24
+ message: msg || (0, i18n_1.getI18n)().buildMsg('validate-err-incorrect-format')
25
+ };
26
+ }
27
+ return { ok: true };
28
+ };
29
+ }
30
+ exports.regexp = regexp;
@@ -0,0 +1 @@
1
+ # node-server
@@ -0,0 +1,59 @@
1
+ # 缓存
2
+
3
+ 缓存组件提供了简单的内存缓存,采用随机淘汰的驱逐策略,支持过期时间。
4
+
5
+ ## 环境变量
6
+
7
+ | 环境变量 | 说明 |
8
+ | :------------------------------ | :------------------------------------------------------------------- |
9
+ | CACHE_DEFAULT_EXPIRE_IN_SECONDS | 默认的存活时长,取值:1-3600,默认 60 |
10
+ | CACHE_STAT_TASK_ENABLED | 是否启用统计任务,启用后每隔指定的时间打印一次缓存统计信息,用于观察 |
11
+ | CACHE_STAT_INTERVAL | 统计任务执行的周期,单位秒.取值 1-86400 |
12
+ | CACHE_CLEANING_INTERVAL | 过期数据清理间隔,单位秒.取值 1-3600,默认 60 |
13
+ | CACHE_MAX_ELEMENTS | 最大元素数,取值 1- Number.MAX_VALUE,默认 1024 |
14
+
15
+ 开启缓存的统计后,会按指定的周期,定时输出统计信息到日志。
16
+
17
+ ```
18
+ [2023/09/27 11:31:35.690][INFO]Cache statistics,
19
+ time window :2023/09/27 11:31:35.442 - now, hit :4/4,capacity:120/100
20
+ ```
21
+
22
+ 上面是统计日志的示例,内容包含了命中情况,以及容量使用情况。上面的示例中容量超出了,这是因为清理任务还没有来的及清理导致的,属于正常。
23
+ 统计是有时间窗口的,只统计这个周期内的情况,所以日志里会有窗口时间信息。
24
+
25
+ ## 性能相关问题
26
+
27
+ CACHE_CLEANING_INTERVAL 用于控制缓存清理任务的周期,如果项目中缓存的内容较多,则必须需要设置的小一些,及时清理掉无效数据。
28
+ 缓存的数据过多,会影响 gc ,因为回收器无法回收被缓存的对象,为此所做的标记和整理内存工作却有很大的消耗。除了清理要频繁一些外,
29
+ 缓存记录时也尽可能将过期时间设置的短一些。
30
+
31
+ 为了减少开销,缓存组件采用随机淘汰的驱逐策略,暂不支持设置驱逐策略。
32
+
33
+ 如果需要大量数据的缓存,又不想不影响 gc,可以考虑其它方案,如堆外内存(Buffer),或者外部缓存服务(Redis 等)。
34
+ 内存缓存只适合缓存少量短期数据。
35
+
36
+ ## 示例
37
+
38
+ 通过 getCache 函数可以获取到全局的缓存对象,通过对象的相关方法来使用缓存。
39
+
40
+ ```ts
41
+ // 获取缓存对象
42
+ const cache = getCache()
43
+
44
+ // 使用默认过期时间
45
+ cache.put('abc', 123)
46
+ let value = cache.get('abc') // 123
47
+
48
+ // 指定过期时间(第三个参数,单位秒)
49
+ cache.put('d', 2233, 1)
50
+ // 删除缓存内容
51
+ cache.remove('d')
52
+ ```
53
+
54
+ 缓存对象有个 computeIfAbsent 方法,可以指定生成缓存内容的方法,
55
+ 如果没有缓存数据则进行生成,有则直接返回缓存数据。
56
+
57
+ ```ts
58
+ const user = await cache.computeIfAbsent(`get-user-${userId}`, findUserById(userId))
59
+ ```
@@ -0,0 +1,68 @@
1
+ # 配置
2
+
3
+ 配置模块的主要作用是将配置对象与环境变量映射,提供给其它的模块来使用,
4
+ 可以和校验组件相结合用于扩展新功能。
5
+
6
+ 提供了两个函数:
7
+
8
+ | 函数 | 功能说明 |
9
+ | :------------- | :--------------------------------------------------------------- |
10
+ | registerConfig | 注册配置信息,注册会立即匹配环境变量并返回映射了属性后的配置对象 |
11
+ | getConfig | 获取配置信息 |
12
+
13
+ 环境变量的映射需要有一个前缀,然后将对象的属性拼接前缀,再进行转换,去匹配环境变量。
14
+ 比如配置对象有个属性是 appId,设置的前缀是 cus ,那么匹配的环境变量就是 CUS_APP_ID。
15
+ 每次调用 registerConfig 函数会有日志输出,可以查看到匹配的情况,用于程序调试。
16
+
17
+ registerConfig 函数使用示例:
18
+
19
+ ```ts
20
+ /**
21
+ * 配置定义
22
+ */
23
+ interface CustomConfig {
24
+ appId: string
25
+ appSecret: string
26
+ ssl: boolean
27
+ timeout: number
28
+ }
29
+
30
+ // 调用 registerConfig 与环境变量映射
31
+ // 返回映射后的配置对象
32
+ const config = registerConfig<CustomConfig>(
33
+ // 第一个参数是默认的配置对象,必须要有默认,在匹配不成功的情况下可以使用
34
+ { appId: '', appSecret: '', ssl: true, timeout: 5000 },
35
+ // 第二个参数是配置前缀
36
+ 'custom',
37
+ // 第三个参数是校验规则,可选,详细可以参照校验组件
38
+ {
39
+ appId: [notBlank()],
40
+ appSecret: [notBlank()],
41
+ ssl: [notNull()],
42
+ timeout: [notNull(), min(1000), max(3600)]
43
+ }
44
+ )
45
+ ```
46
+
47
+ 也可以不定义配置对象,直接写默认配置对象,通过第一个参数的默认配置对象可以完成自动类型推断,
48
+ 更简洁一些。
49
+
50
+ ```ts
51
+ const config2 = registerConfig(
52
+ {
53
+ url: 'http://localhost/api',
54
+ account: 'Jack'
55
+ },
56
+ 'c2',
57
+ {
58
+ url: [notBlank()]
59
+ }
60
+ )
61
+ ```
62
+
63
+ getConfig 函数仅一个参数,传递前缀,可以获取到配置对象。
64
+ 一般很少需要使用,推荐调用 registerConfig 时将返回的配置对象导出以供其它程序模块使用。
65
+
66
+ ```ts
67
+ const config2 = getConfig('c2')
68
+ ```
@@ -0,0 +1,33 @@
1
+ # HTTP 客户端
2
+
3
+ HTTP 客户端是基于 Nodejs 内置的 http 和 https 模块封装的 http 请求发送工具,
4
+ 提供了三个函数。
5
+
6
+ | 函数 | 作用 |
7
+ | :-------- | :--------------------------------------- |
8
+ | doRequest | 通用的 http 请求,可以自定义各种选项 |
9
+ | postJson | 发送 post 请求,获取 json 格式的响应数据 |
10
+ | getJson | 发送 get 请求,获取 json 格式的响应数据 |
11
+
12
+ ## 使用示例
13
+
14
+ ```ts
15
+ // get 请求 json
16
+ const list = await getJson<User[]>({
17
+ url: '/users'
18
+ })
19
+
20
+ // post 请求 json
21
+ const res = await postJson<Result>({
22
+ url: '/data/save',
23
+ body: { name: 'jack', age: 33 }
24
+ })
25
+
26
+ // 使用 doRequest,自定义更多的选项
27
+ await doRequest({
28
+ url: '/users/001',
29
+ method: 'DELETE',
30
+ timeout: 5000,
31
+ followRedirect: true
32
+ })
33
+ ```
@@ -0,0 +1,154 @@
1
+ # 国际化
2
+
3
+ 国际化组件提供了对多语言环境的支持,可支持扩展新的国际化内容,并自动保持语言一致。
4
+ i18n 对象是全局的,在处理请求时如有异步操作,可通过绑定操作来保持一次请求的处理语言始终不变。
5
+
6
+ ## 无国际化处理
7
+
8
+ 默认情况下国际化组件会根据环境来自动更新语言,但是如果是在容器和虚拟中使用,
9
+ 那么很可能镜像默认使用的是英文。
10
+
11
+ 如果项目无做国际化的需要,并且要保证框架中的提示信息必须是中文,可以在程序中指定环境变量 LANG。
12
+
13
+ ```ts
14
+ // 通过 process 更改环境变量 LANG,指定简体中文
15
+ // 必须写在框架 import 之前
16
+ process.env.LANG = 'zh-CN'
17
+ // 前面变量改过了,再 import
18
+ import {...} from 'wok-server'
19
+ ```
20
+
21
+ 如果使用的是容器,可直接为容器设置环境变量,这样就不需要改代码了。
22
+
23
+ ## 使用示例
24
+
25
+ ```ts
26
+ // 通过 getI18n 函数获取 i18n 对象
27
+ const i18n = getI18n()
28
+ // getLang 方法可以获取当前使用的语言
29
+ const currentLang = i18n.getLang()
30
+ // setLang 方法可以切换语言,返回布尔类型,表示是否切换成功
31
+ // 只有支持的语言标签可以被支持才会切换成功
32
+ i18n.setLang('en')
33
+ // buildMsg 方法可以根据当前语言构建消息
34
+ // 第一个参数是 key (有类型约束),后面可以填写0到多个模板参数
35
+ // 更多的信息下面的配置新语言会介绍
36
+ const msg = i18n.buildMsg('validate-err-max', '7')
37
+ ```
38
+
39
+ ## 语言标签与匹配规则
40
+
41
+ 目前只实现对语言加地区的格式的支持,如 en-US,en 表示英语,US 表示美国。
42
+ 其中地区是可选的,在配置的时候也可以只有语言,如 en 。在匹配时,大小写不区分。
43
+
44
+ 如果只配置了“en-US”,但是将语言设置为 “en-GB”,也是可以成功的。
45
+ 这是因为匹配的时候,如果没有找到语言和地区完全一致的配置,就寻找语言的默认,
46
+ 也就是 "en",发现默认也没有,于是就从相同语言中寻找第一个配置,最终使用的是 "en-US"。
47
+
48
+ 在切换语言时如果匹配失败,则不进行切换,保持不变,**并不会使用默认语言**。
49
+ 默认语言统一是 en ,任何扩展的 i18n 对象都必须有一套英文作为默认,这是为了保持一致,保障程序的正常使用。
50
+ 但是程序初始化的时候会根据当前的环境变量来自动进行切换,如果设置了 LANG 或 LC_CTYPE 变量,
51
+ 则会根据环境变量的设置来完成切换。对于扩展的国际化内容则需要自行处理,详细请看下面关于扩展的内容。
52
+
53
+ ## 配置新的语言
54
+
55
+ 框架中已经内置了以下语言。
56
+
57
+ | 语言标签 | 对应语言 |
58
+ | :------- | :------------- |
59
+ | en | 英语,默认语言 |
60
+ | zh-CN | 简体中文 |
61
+ | zh-TW | 繁体中文 |
62
+ | zh-HK | 香港繁体中文 |
63
+ | ja | 日语 |
64
+ | ko | 韩语 |
65
+ | ru | 俄语 |
66
+ | es | 西班牙语 |
67
+ | de | 德语 |
68
+ | fr | 法语 |
69
+ | ar | 阿拉伯语 |
70
+ | pt | 葡萄牙语 |
71
+
72
+ 如果要使用的语言没有被内置,就需要自己进行配置,下面是示例代码。
73
+
74
+ ```ts
75
+ const i18n = getI18n()
76
+ // 调用 setMsgs 进行语言的设置,第一个参数是语言标签,第二个参数是消息模板
77
+ i18n.setMsgs('ja', {
78
+ 'validate-err-array': '値が配列ではありません',
79
+ 'validate-err-enum': '値は {} の中のいずれかでなければなりません',
80
+ 'validate-err-numer': '値が数字ではありません',
81
+ 'validate-err-max': '{} 以下である必要があります',
82
+ 'validate-err-min': '{} 以上である必要があります',
83
+ 'validate-err-empty': '空であってはいけません',
84
+ 'validate-err-string': '値が文字列のタイプではありません',
85
+ 'validate-err-incorrect-format': '形式が正しくありません',
86
+ 'validate-err-no-length': 'length属性が見当たりません',
87
+ 'validate-err-length-not-number': 'lengthプロパティは数値ではありません',
88
+ 'validate-err-min-length': '長さは {} 以上でなければりません',
89
+ 'validate-err-max-length': '長さは {} 以下でなければなりません'
90
+ })
91
+ // 设置后就可以成功切换到自定义的语言了
92
+ i18n.setLang('ja')
93
+ ```
94
+
95
+ ## 扩展新内容
96
+
97
+ 以上都是框架自带的国际化内容,实际项目开发中有很多业务相关的国际化,
98
+ 可以基于框架的 i18n 对象进行扩展新的内容。扩展得到的对象会与 i18n 全局对象
99
+ 的语言保持一致,在需要更改语言的时候,只需要调用全局对象 i18n 的 setLang 方法就可以了。
100
+
101
+ ```ts
102
+ // 获取 i18n 对象
103
+ const i18n = getI18n()
104
+ // 新的语言模板定义
105
+ interface ExtMsgs {
106
+ hello: string
107
+ world: string
108
+ }
109
+ // 扩展新的内容, 参数是英文模板,统一使用英文作为默认,文档前面已经有说明
110
+ // 返回的是一个 I18n 类型的对象,方法与全局的 i18n 对象基本一致,只是没有 extend 方法
111
+ const extI18n = i18n.extend<ExtMsgs>({ hello: 'hello', world: 'world' })
112
+ // 为扩展内容添加中文
113
+ extI18n.setMsgs('zh-cn', { hello: '你好', world: '世界' })
114
+
115
+ // i18n 全局对象更改语言后,extI18n 也会改变
116
+ // 在实际开发中,可根据情况在扩展完成后切换到合适的语言
117
+ i18n.setLang('zh')
118
+
119
+ i18n.getLang() // zh
120
+ extI18n.getLang() // zh
121
+ ```
122
+
123
+ 在实际开发中,可以将 extI18n 对象导出以供其它模块使用。
124
+
125
+ 需要注意的是,新的语言模板,value 必须都是 string 类型,否则会报错。
126
+ 模板内容支持 0 到多个占位,比如 `{accountNotExist:"帐号{}不存在"}`,调用 `buildMsg('accountNotExist','jack')`
127
+ 得到 `"帐号jack不存在"`。
128
+
129
+ ## 绑定语言
130
+
131
+ 由于 i18n 对象是全局的,是共享的,在处理请求时,如果请求有异步操作,
132
+ 那么很可能一个请求更改了语言后执行异步操作,又被别的请求更改了语言,待异步完成后,
133
+ 语言可能是不正确的。
134
+
135
+ 这种情况可以使用绑定语言的功能。
136
+
137
+ ```ts
138
+ // 处理请求,简单的演示,详细的可以看后面的 mvc 章节
139
+ async function handleReq(exchange: RouterExchange): Promise<void> {
140
+ // 消息头,类型是 IncomingHttpHeaders,nodejs 内置的 http 模块原生类型
141
+ const headers = exchange.headers
142
+ // 绑定得到一个语言固定的 i18n 对象,extI18n 是上面演示中扩展的业务国际化对象
143
+ // bindByRequest 会根据消息头 'accept-language' 的值生成固定语言的 i18n 对象
144
+ const boundI18n = extI18n.bindByRequest(headers)
145
+ await query1()
146
+ await query2()
147
+ await query3()
148
+ // 构建的消息始终是和请求接受的语言相关
149
+ const hello = boundI18n.buildMsg('hello')
150
+ }
151
+ ```
152
+
153
+ 此外还有 i18n 对象还有一个 switchByRequest 方法,参数也是 IncomingHttpHeaders 类型,
154
+ 作用是根据消息头切换语言。
@@ -0,0 +1,25 @@
1
+ # node-server
2
+
3
+ Nodejs 后端开发框架,简洁,易上手,功能够用。使用 Typescript 开发,有完整的类型定义,
4
+ 开发效率高。
5
+
6
+ ## 文档约定
7
+
8
+ 所有文档中出现的演示代码一律使用 Typescript,也只推荐在 Typescript 的项目中使用框架,因为框架很多功能都依赖类型推断。
9
+
10
+ 文档中不会列出每一个选项的信息,这样工作量太大了。但是,会尽可能的给出较为丰富的使用示例,具体的参数,
11
+ 在使用的时候,可以通过编辑器的文档预览和跳转功能查看定义文件。
12
+
13
+ ## 功能
14
+
15
+ - [国际化](./i18n.md)
16
+ - [校验](./validate.md)
17
+ - [配置](./config.md)
18
+ - [日志](./log.md)
19
+ - [缓存](./cache.md)
20
+ - [mysql](./mysql.md)
21
+ - [mongodb](./mongodb.md)
22
+ - [MVC](./mvc.md)
23
+ - [任务](./task.md)
24
+ - [Http 客户端](./http-client.md)
25
+ - [单元测试](./test.md)
@@ -0,0 +1,40 @@
1
+ # 日志
2
+
3
+ 日志用于记录信息,支持简单的级别控制,以及写入文件功能。
4
+
5
+ ## 环境变量
6
+
7
+ | 环境变量名称 | 默认值 | 说明 |
8
+ | :---------------- | :----- | :----------------------------------------------------------------------- |
9
+ | LOG_LEVEL | info | 日志级别,低于设定级别的日志将不会输出,取值:DEBUG,INFO,WARN,ERROR |
10
+ | LOG_FILE | false | 取值 true 或 false ,表示是否开启文件 |
11
+ | LOG_FILE_MAX_DAYS | 30 | 数文件的保留天数 |
12
+ | LOG_FILE_DIR | logs | 日志文件存储路径,支持相对路径和绝对路径,相对路径是相对于进程执行目录的 |
13
+
14
+ ## 使用
15
+
16
+ 通过 getLogger() 函数获取日志对象,然后调用日志对象的方法来输出日志。
17
+
18
+ ```ts
19
+ const logger = getLogger()
20
+
21
+ logger.info('普通日志信息')
22
+
23
+ const err = new Error('错误信息测试')
24
+ logger.error('错误日志输出信息', err)
25
+
26
+ if (logger.isDebugEnabled()) {
27
+ logger.debug('调试日志输出', JSON.stringify(args))
28
+ }
29
+ ```
30
+
31
+ ## 自定义日志存储
32
+
33
+ 通过函数 setLogStore 可以自定义日志的存储,一旦设置,将会覆盖掉文件存储,即使设置了开启文件,日志也不会输出到文件中。
34
+
35
+ ```ts
36
+ setLogStore(log => {
37
+ // 可以根据需要将日志内容放入消息队列或独立的文件存储系统中
38
+ messageQueue.push(log)
39
+ })
40
+ ```