wok-server 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +61 -0
- package/README.md +44 -29
- package/dist/cache/cache.js +98 -98
- package/dist/cache/config.js +19 -19
- package/dist/cache/index.js +27 -27
- package/dist/cache/purge-task.js +46 -46
- package/dist/cache/stat.js +47 -47
- package/dist/config/convert.js +36 -36
- package/dist/config/exception.js +14 -14
- package/dist/config/index.js +81 -81
- package/dist/http-client/index.js +136 -136
- package/dist/i18n/ar.js +17 -17
- package/dist/i18n/de.js +17 -17
- package/dist/i18n/en-us.js +17 -17
- package/dist/i18n/es.js +17 -17
- package/dist/i18n/fr.js +17 -17
- package/dist/i18n/i18n.js +231 -231
- package/dist/i18n/index.js +52 -52
- package/dist/i18n/ja.js +17 -17
- package/dist/i18n/ko.js +17 -17
- package/dist/i18n/msg.js +2 -2
- package/dist/i18n/pt.js +17 -17
- package/dist/i18n/ru.js +17 -17
- package/dist/i18n/tag.js +18 -18
- package/dist/i18n/zh-HK.js +17 -17
- package/dist/i18n/zh-TW.js +17 -17
- package/dist/i18n/zh-cn.js +17 -17
- package/dist/index.js +14 -14
- package/dist/lock/index.js +114 -114
- package/dist/log/config.js +35 -35
- package/dist/log/date.js +21 -21
- package/dist/log/file.js +198 -198
- package/dist/log/index.js +135 -135
- package/dist/log/level.js +33 -33
- package/dist/log/log.js +56 -56
- package/dist/log/store.js +19 -19
- package/dist/mongodb/collection.js +2 -2
- package/dist/mongodb/config.js +34 -34
- package/dist/mongodb/doc.js +2 -2
- package/dist/mongodb/exception.js +14 -14
- package/dist/mongodb/index.js +58 -58
- package/dist/mongodb/manager/base.js +563 -563
- package/dist/mongodb/manager/index.js +63 -63
- package/dist/mongodb/manager/tx-strict.js +84 -84
- package/dist/mongodb/manager/tx.js +30 -30
- package/dist/mongodb/migration.js +52 -52
- package/dist/mvc/access-log.js +33 -33
- package/dist/mvc/config.js +27 -27
- package/dist/mvc/exchange.js +113 -113
- package/dist/mvc/handler/index.js +7 -6
- package/dist/mvc/handler/json.js +65 -65
- package/dist/mvc/handler/restful.js +35 -35
- package/dist/mvc/handler/sse.js +65 -0
- package/dist/mvc/handler/upload.js +31 -31
- package/dist/mvc/index.js +50 -50
- package/dist/mvc/interceptor.js +2 -2
- package/dist/mvc/query.js +43 -43
- package/dist/mvc/render/file.js +132 -132
- package/dist/mvc/render/html/html.js +90 -90
- package/dist/mvc/render/html/index.js +18 -18
- package/dist/mvc/render/html/style.js +2 -2
- package/dist/mvc/render/index.js +7 -7
- package/dist/mvc/render/json.js +26 -26
- package/dist/mvc/render/text.js +16 -16
- package/dist/mvc/router.js +2 -2
- package/dist/mvc/server.js +272 -272
- package/dist/mvc/static/header.js +67 -67
- package/dist/mvc/static/index.js +6 -6
- package/dist/mvc/static/mime-type.js +84 -84
- package/dist/mvc/static/server-cache-config.js +66 -66
- package/dist/mvc/static/server-cache.js +133 -133
- package/dist/mvc/static/static-handler.js +372 -372
- package/dist/mysql/config.js +51 -51
- package/dist/mysql/exception.js +14 -14
- package/dist/mysql/index.js +87 -87
- package/dist/mysql/manager/base.js +239 -239
- package/dist/mysql/manager/index.js +107 -107
- package/dist/mysql/manager/ops/count.js +20 -20
- package/dist/mysql/manager/ops/criteria.js +356 -356
- package/dist/mysql/manager/ops/delete.js +65 -65
- package/dist/mysql/manager/ops/exist.js +26 -26
- package/dist/mysql/manager/ops/find.js +169 -169
- package/dist/mysql/manager/ops/index.js +14 -14
- package/dist/mysql/manager/ops/insert.js +106 -106
- package/dist/mysql/manager/ops/modify.js +10 -10
- package/dist/mysql/manager/ops/paginate.js +23 -23
- package/dist/mysql/manager/ops/query.js +9 -9
- package/dist/mysql/manager/ops/update.js +216 -216
- package/dist/mysql/manager/ops/utils.js +24 -24
- package/dist/mysql/manager/tx-strict.js +103 -103
- package/dist/mysql/manager/tx.js +30 -30
- package/dist/mysql/manager/utils.js +56 -56
- package/dist/mysql/migration.js +136 -136
- package/dist/mysql/table-info.js +8 -8
- package/dist/task/daily.js +59 -59
- package/dist/task/fixed-delay.js +38 -38
- package/dist/task/fixed-rate.js +42 -42
- package/dist/task/index.js +9 -9
- package/dist/task/task.js +56 -56
- package/dist/validation/exception.js +36 -36
- package/dist/validation/index.js +40 -40
- package/dist/validation/validator/array.js +34 -34
- package/dist/validation/validator/enum.js +28 -28
- package/dist/validation/validator/index.js +14 -14
- package/dist/validation/validator/length.js +40 -40
- package/dist/validation/validator/max-length.js +35 -35
- package/dist/validation/validator/max.js +29 -29
- package/dist/validation/validator/min-length.js +33 -33
- package/dist/validation/validator/min.js +29 -29
- package/dist/validation/validator/not-blank.js +33 -33
- package/dist/validation/validator/not-null.js +21 -21
- package/dist/validation/validator/plain-obj.js +32 -32
- package/dist/validation/validator/regexp.js +34 -34
- package/documentation/en/cache.md +56 -0
- package/documentation/en/config.md +96 -0
- package/documentation/en/engineering.md +256 -0
- package/documentation/en/http-client.md +32 -0
- package/documentation/en/i18n.md +143 -0
- package/documentation/en/index.md +24 -0
- package/documentation/en/lock.md +51 -0
- package/documentation/en/log.md +109 -0
- package/documentation/en/mongodb.md +256 -0
- package/documentation/en/mvc.md +688 -0
- package/documentation/en/mysql.md +552 -0
- package/documentation/en/task.md +45 -0
- package/documentation/en/test.md +56 -0
- package/documentation/en/validate.md +130 -0
- package/documentation/zh-cn/mvc.md +66 -24
- package/package.json +3 -1
- package/skills/wok-server-api-rules/SKILL.md +350 -0
- package/skills/wok-server-cache/SKILL.md +216 -0
- package/skills/wok-server-config/SKILL.md +200 -0
- package/skills/wok-server-getting-started/SKILL.md +123 -0
- package/skills/wok-server-getting-started/references/engineering.md +169 -0
- package/skills/wok-server-http-client/SKILL.md +164 -0
- package/skills/wok-server-i18n/SKILL.md +214 -0
- package/skills/wok-server-lock/SKILL.md +144 -0
- package/skills/wok-server-log/SKILL.md +218 -0
- package/skills/wok-server-mongodb/SKILL.md +235 -0
- package/skills/wok-server-mvc/SKILL.md +251 -0
- package/skills/wok-server-mvc/references/respond-html.md +157 -0
- package/skills/wok-server-mvc/references/sse.md +121 -0
- package/skills/wok-server-mvc/references/static-files.md +47 -0
- package/skills/wok-server-mvc/references/upload.md +62 -0
- package/skills/wok-server-mvc/references/websocket.md +30 -0
- package/skills/wok-server-mysql/SKILL.md +315 -0
- package/skills/wok-server-mysql/references/multi-datasource.md +76 -0
- package/skills/wok-server-mysql/references/version-control.md +22 -0
- package/skills/wok-server-task/SKILL.md +158 -0
- package/skills/wok-server-validate/SKILL.md +167 -0
- package/src/cache/cache.ts +118 -0
- package/src/cache/config.ts +53 -0
- package/src/cache/index.ts +27 -0
- package/src/cache/purge-task.ts +53 -0
- package/src/cache/stat.ts +47 -0
- package/src/config/convert.ts +27 -0
- package/src/config/exception.ts +8 -0
- package/src/config/index.ts +92 -0
- package/src/http-client/index.ts +202 -0
- package/src/i18n/ar.ts +16 -0
- package/src/i18n/de.ts +16 -0
- package/src/i18n/en-us.ts +16 -0
- package/src/i18n/es.ts +16 -0
- package/src/i18n/fr.ts +16 -0
- package/src/i18n/i18n.ts +230 -0
- package/src/i18n/index.ts +50 -0
- package/src/i18n/ja.ts +16 -0
- package/src/i18n/ko.ts +16 -0
- package/src/i18n/msg.ts +50 -0
- package/src/i18n/pt.ts +16 -0
- package/src/i18n/ru.ts +16 -0
- package/src/i18n/tag.ts +18 -0
- package/src/i18n/zh-HK.ts +16 -0
- package/src/i18n/zh-TW.ts +16 -0
- package/src/i18n/zh-cn.ts +16 -0
- package/src/index.ts +11 -0
- package/src/lock/index.ts +164 -0
- package/src/log/config.ts +71 -0
- package/src/log/date.ts +19 -0
- package/src/log/file.ts +215 -0
- package/src/log/index.ts +136 -0
- package/src/log/level.ts +29 -0
- package/src/log/log.ts +77 -0
- package/src/log/store.ts +31 -0
- package/src/mongodb/collection.ts +25 -0
- package/src/mongodb/config.ts +69 -0
- package/src/mongodb/doc.ts +12 -0
- package/src/mongodb/exception.ts +8 -0
- package/src/mongodb/index.ts +71 -0
- package/src/mongodb/manager/base.ts +674 -0
- package/src/mongodb/manager/index.ts +80 -0
- package/src/mongodb/manager/tx-strict.ts +153 -0
- package/src/mongodb/manager/tx.ts +34 -0
- package/src/mongodb/migration.ts +66 -0
- package/src/mvc/access-log.ts +33 -0
- package/src/mvc/config.ts +70 -0
- package/src/mvc/exchange.ts +126 -0
- package/src/mvc/handler/index.ts +4 -0
- package/src/mvc/handler/json.ts +96 -0
- package/src/mvc/handler/restful.ts +39 -0
- package/src/mvc/handler/sse.ts +90 -0
- package/src/mvc/handler/upload.ts +54 -0
- package/src/mvc/index.ts +48 -0
- package/src/mvc/interceptor.ts +12 -0
- package/src/mvc/query.ts +36 -0
- package/src/mvc/render/file.ts +148 -0
- package/src/mvc/render/html/html.ts +187 -0
- package/src/mvc/render/html/index.ts +16 -0
- package/src/mvc/render/html/style.ts +1201 -0
- package/src/mvc/render/index.ts +4 -0
- package/src/mvc/render/json.ts +24 -0
- package/src/mvc/render/text.ts +14 -0
- package/src/mvc/router.ts +13 -0
- package/src/mvc/server.ts +315 -0
- package/src/mvc/static/header.ts +86 -0
- package/src/mvc/static/index.ts +3 -0
- package/src/mvc/static/mime-type.ts +81 -0
- package/src/mvc/static/server-cache-config.ts +92 -0
- package/src/mvc/static/server-cache.ts +171 -0
- package/src/mvc/static/static-handler.ts +445 -0
- package/src/mysql/config.ts +130 -0
- package/src/mysql/exception.ts +8 -0
- package/src/mysql/index.ts +88 -0
- package/src/mysql/manager/base.ts +285 -0
- package/src/mysql/manager/index.ts +112 -0
- package/src/mysql/manager/ops/count.ts +30 -0
- package/src/mysql/manager/ops/criteria.ts +412 -0
- package/src/mysql/manager/ops/delete.ts +96 -0
- package/src/mysql/manager/ops/exist.ts +41 -0
- package/src/mysql/manager/ops/find.ts +226 -0
- package/src/mysql/manager/ops/index.ts +11 -0
- package/src/mysql/manager/ops/insert.ts +120 -0
- package/src/mysql/manager/ops/modify.ts +14 -0
- package/src/mysql/manager/ops/paginate.ts +60 -0
- package/src/mysql/manager/ops/query.ts +13 -0
- package/src/mysql/manager/ops/update.ts +294 -0
- package/src/mysql/manager/ops/utils.ts +20 -0
- package/src/mysql/manager/tx-strict.ts +138 -0
- package/src/mysql/manager/tx.ts +31 -0
- package/src/mysql/manager/utils.ts +75 -0
- package/src/mysql/migration.ts +149 -0
- package/src/mysql/table-info.ts +41 -0
- package/src/task/daily.ts +70 -0
- package/src/task/fixed-delay.ts +45 -0
- package/src/task/fixed-rate.ts +49 -0
- package/src/task/index.ts +4 -0
- package/src/task/task.ts +70 -0
- package/src/validation/exception.ts +27 -0
- package/src/validation/index.ts +61 -0
- package/src/validation/validator/array.ts +32 -0
- package/src/validation/validator/enum.ts +25 -0
- package/src/validation/validator/index.ts +11 -0
- package/src/validation/validator/length.ts +42 -0
- package/src/validation/validator/max-length.ts +33 -0
- package/src/validation/validator/max.ts +26 -0
- package/src/validation/validator/min-length.ts +31 -0
- package/src/validation/validator/min.ts +26 -0
- package/src/validation/validator/not-blank.ts +31 -0
- package/src/validation/validator/not-null.ts +19 -0
- package/src/validation/validator/plain-obj.ts +30 -0
- package/src/validation/validator/regexp.ts +32 -0
- package/types/cache/cache.d.ts +52 -52
- package/types/cache/config.d.ts +32 -32
- package/types/cache/index.d.ts +2 -2
- package/types/cache/purge-task.d.ts +11 -11
- package/types/cache/stat.d.ts +26 -26
- package/types/config/convert.d.ts +6 -6
- package/types/config/exception.d.ts +7 -7
- package/types/config/index.d.ts +25 -25
- package/types/http-client/index.d.ts +71 -71
- package/types/i18n/ar.d.ts +2 -2
- package/types/i18n/de.d.ts +2 -2
- package/types/i18n/en-us.d.ts +2 -2
- package/types/i18n/es.d.ts +2 -2
- package/types/i18n/fr.d.ts +2 -2
- package/types/i18n/i18n.d.ts +102 -102
- package/types/i18n/index.d.ts +9 -9
- package/types/i18n/ja.d.ts +2 -2
- package/types/i18n/ko.d.ts +2 -2
- package/types/i18n/msg.d.ts +50 -50
- package/types/i18n/pt.d.ts +2 -2
- package/types/i18n/ru.d.ts +2 -2
- package/types/i18n/tag.d.ts +11 -11
- package/types/i18n/zh-HK.d.ts +2 -2
- package/types/i18n/zh-TW.d.ts +2 -2
- package/types/i18n/zh-cn.d.ts +2 -2
- package/types/index.d.ts +11 -11
- package/types/lock/index.d.ts +64 -64
- package/types/log/config.d.ts +35 -35
- package/types/log/date.d.ts +2 -2
- package/types/log/file.d.ts +13 -13
- package/types/log/index.d.ts +53 -53
- package/types/log/level.d.ts +14 -14
- package/types/log/log.d.ts +40 -40
- package/types/log/store.d.ts +19 -19
- package/types/mongodb/collection.d.ts +25 -25
- package/types/mongodb/config.d.ts +45 -45
- package/types/mongodb/doc.d.ts +11 -11
- package/types/mongodb/exception.d.ts +7 -7
- package/types/mongodb/index.d.ts +29 -29
- package/types/mongodb/manager/base.d.ts +188 -188
- package/types/mongodb/manager/index.d.ts +38 -38
- package/types/mongodb/manager/tx-strict.d.ts +41 -41
- package/types/mongodb/manager/tx.d.ts +21 -21
- package/types/mongodb/migration.d.ts +12 -12
- package/types/mvc/access-log.d.ts +7 -7
- package/types/mvc/config.d.ts +42 -42
- package/types/mvc/exchange.d.ts +72 -72
- package/types/mvc/handler/index.d.ts +4 -3
- package/types/mvc/handler/json.d.ts +44 -44
- package/types/mvc/handler/restful.d.ts +11 -11
- package/types/mvc/handler/sse.d.ts +34 -0
- package/types/mvc/handler/upload.d.ts +36 -36
- package/types/mvc/index.d.ts +22 -22
- package/types/mvc/interceptor.d.ts +11 -11
- package/types/mvc/query.d.ts +13 -13
- package/types/mvc/render/file.d.ts +10 -10
- package/types/mvc/render/html/html.d.ts +98 -98
- package/types/mvc/render/html/index.d.ts +11 -11
- package/types/mvc/render/html/style.d.ts +1201 -1201
- package/types/mvc/render/index.d.ts +4 -4
- package/types/mvc/render/json.d.ts +17 -17
- package/types/mvc/render/text.d.ts +10 -10
- package/types/mvc/router.d.ts +11 -11
- package/types/mvc/server.d.ts +90 -90
- package/types/mvc/static/header.d.ts +27 -27
- package/types/mvc/static/index.d.ts +3 -3
- package/types/mvc/static/mime-type.d.ts +2 -2
- package/types/mvc/static/server-cache-config.d.ts +30 -30
- package/types/mvc/static/server-cache.d.ts +76 -76
- package/types/mvc/static/static-handler.d.ts +77 -77
- package/types/mysql/config.d.ts +90 -90
- package/types/mysql/exception.d.ts +7 -7
- package/types/mysql/index.d.ts +16 -16
- package/types/mysql/manager/base.d.ts +165 -165
- package/types/mysql/manager/index.d.ts +36 -36
- package/types/mysql/manager/ops/count.d.ts +13 -13
- package/types/mysql/manager/ops/criteria.d.ts +134 -134
- package/types/mysql/manager/ops/delete.d.ts +46 -46
- package/types/mysql/manager/ops/exist.d.ts +6 -6
- package/types/mysql/manager/ops/find.d.ts +86 -86
- package/types/mysql/manager/ops/index.d.ts +10 -10
- package/types/mysql/manager/ops/insert.d.ts +18 -18
- package/types/mysql/manager/ops/modify.d.ts +3 -3
- package/types/mysql/manager/ops/paginate.d.ts +36 -36
- package/types/mysql/manager/ops/query.d.ts +3 -3
- package/types/mysql/manager/ops/update.d.ts +76 -76
- package/types/mysql/manager/ops/utils.d.ts +5 -5
- package/types/mysql/manager/tx-strict.d.ts +36 -36
- package/types/mysql/manager/tx.d.ts +15 -15
- package/types/mysql/manager/utils.d.ts +17 -17
- package/types/mysql/migration.d.ts +8 -8
- package/types/mysql/table-info.d.ts +36 -36
- package/types/task/daily.d.ts +16 -16
- package/types/task/fixed-delay.d.ts +9 -9
- package/types/task/fixed-rate.d.ts +9 -9
- package/types/task/index.d.ts +4 -4
- package/types/task/task.d.ts +34 -34
- package/types/validation/exception.d.ts +38 -38
- package/types/validation/index.d.ts +32 -32
- package/types/validation/validator/array.d.ts +5 -5
- package/types/validation/validator/enum.d.ts +8 -8
- package/types/validation/validator/index.d.ts +11 -11
- package/types/validation/validator/length.d.ts +10 -10
- package/types/validation/validator/max-length.d.ts +8 -8
- package/types/validation/validator/max.d.ts +7 -7
- package/types/validation/validator/min-length.d.ts +6 -6
- package/types/validation/validator/min.d.ts +7 -7
- package/types/validation/validator/not-blank.d.ts +7 -7
- package/types/validation/validator/not-null.d.ts +6 -6
- package/types/validation/validator/plain-obj.d.ts +7 -7
- package/types/validation/validator/regexp.d.ts +8 -8
|
@@ -1,34 +1,34 @@
|
|
|
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
|
-
// 跳过空串
|
|
21
|
-
if (!val) {
|
|
22
|
-
return { ok: true };
|
|
23
|
-
}
|
|
24
|
-
if (!pattern.test(val)) {
|
|
25
|
-
return {
|
|
26
|
-
ok: false,
|
|
27
|
-
validator,
|
|
28
|
-
message: msg || (0, i18n_1.getI18n)().buildMsg('validate-err-incorrect-format')
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
return { ok: true };
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
exports.regexp = regexp;
|
|
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
|
+
// 跳过空串
|
|
21
|
+
if (!val) {
|
|
22
|
+
return { ok: true };
|
|
23
|
+
}
|
|
24
|
+
if (!pattern.test(val)) {
|
|
25
|
+
return {
|
|
26
|
+
ok: false,
|
|
27
|
+
validator,
|
|
28
|
+
message: msg || (0, i18n_1.getI18n)().buildMsg('validate-err-incorrect-format')
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return { ok: true };
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
exports.regexp = regexp;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Cache
|
|
2
|
+
|
|
3
|
+
The cache component provides simple in-memory caching with a random eviction strategy and support for expiration times.
|
|
4
|
+
|
|
5
|
+
## Environment Variables
|
|
6
|
+
|
|
7
|
+
| Environment Variable | Description |
|
|
8
|
+
| :---------------------------- | :-------------------------------------------------------------------------- |
|
|
9
|
+
| CACHE_DEFAULT_EXPIRE_IN_SECONDS | Default expiration time in seconds. Value: 1-3600, default 60 |
|
|
10
|
+
| CACHE_STAT_TASK_ENABLED | Whether to enable statistics task. When enabled, cache statistics are printed at specified intervals for observation |
|
|
11
|
+
| CACHE_STAT_INTERVAL | Statistics task execution interval in seconds. Value: 1-86400 |
|
|
12
|
+
| CACHE_CLEANING_INTERVAL | Expired data cleaning interval in seconds. Value: 1-3600, default 60 |
|
|
13
|
+
| CACHE_MAX_ELEMENTS | Maximum number of elements. Value: 1-NUM.MAX_VALUE, default 1024 |
|
|
14
|
+
|
|
15
|
+
After enabling cache statistics, statistics will be output to the log at the specified interval.
|
|
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
|
+
The example above shows statistics including hit rate and capacity usage. In the example, capacity is exceeded, which is normal because the cleaning task hasn't run yet. Statistics are time-windowed and only count within the current cycle.
|
|
23
|
+
|
|
24
|
+
## Performance Considerations
|
|
25
|
+
|
|
26
|
+
CACHE_CLEANING_INTERVAL controls the cache cleaning task cycle. If the project has a lot of cached content, this should be set smaller to clean up invalid data promptly.
|
|
27
|
+
|
|
28
|
+
Excessive cached data affects GC because the garbage collector cannot reclaim cached objects, but the marking and memory compaction work is still costly. In addition to more frequent cleaning, cache records should also have shorter expiration times when possible.
|
|
29
|
+
|
|
30
|
+
To reduce overhead, the cache component uses a random eviction strategy and does not support configurable eviction strategies.
|
|
31
|
+
|
|
32
|
+
If large amounts of data need to be cached without affecting GC, consider alternative solutions such as off-heap memory (Buffer) or external cache services (Redis, etc.). In-memory caching is only suitable for caching small amounts of short-term data.
|
|
33
|
+
|
|
34
|
+
## Examples
|
|
35
|
+
|
|
36
|
+
You can get the global cache object through the getCache function and use its methods to work with the cache.
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
// Get cache object
|
|
40
|
+
const cache = getCache()
|
|
41
|
+
|
|
42
|
+
// Use default expiration time
|
|
43
|
+
cache.put('abc', 123)
|
|
44
|
+
let value = cache.get('abc') // 123
|
|
45
|
+
|
|
46
|
+
// Specify expiration time (third parameter, in seconds)
|
|
47
|
+
cache.put('d', 2233, 1)
|
|
48
|
+
// Remove cache entry
|
|
49
|
+
cache.remove('d')
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The cache object has a computeIfAbsent method that allows you to specify a function to generate cache content. If no cached data exists, it generates and caches it; otherwise, it returns the cached data directly.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
const user = await cache.computeIfAbsent(`get-user-${userId}`, findUserById(userId))
|
|
56
|
+
```
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Configuration
|
|
2
|
+
|
|
3
|
+
The configuration module maps configuration objects to environment variables and provides them to other modules. It can be combined with the validation component to extend new features.
|
|
4
|
+
|
|
5
|
+
Three functions are provided:
|
|
6
|
+
|
|
7
|
+
| Function | Description |
|
|
8
|
+
| :-------------- | :-------------------------------------------------------------------------- |
|
|
9
|
+
| registerConfig | Register configuration, which immediately matches environment variables and returns the mapped configuration object |
|
|
10
|
+
| getConfig | Get configuration |
|
|
11
|
+
| generateConfig | Generate configuration from environment variables without registering |
|
|
12
|
+
|
|
13
|
+
## Configuration Types and Instance Objects
|
|
14
|
+
|
|
15
|
+
To perform configuration mapping, you must first define a configuration type. Here is an example:
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
/**
|
|
19
|
+
* Configuration definition
|
|
20
|
+
*/
|
|
21
|
+
interface CustomConfig {
|
|
22
|
+
appId: string
|
|
23
|
+
appSecret: string
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**All properties of the configuration type must be non-nullable and must have values for mapping to work.**
|
|
28
|
+
|
|
29
|
+
You can also skip defining a type and directly declare an object, then call registerConfig to complete automatic type inference. See the registerConfig description below for details.
|
|
30
|
+
|
|
31
|
+
Currently, configuration objects only support the following types: string, number, boolean.
|
|
32
|
+
|
|
33
|
+
## registerConfig
|
|
34
|
+
|
|
35
|
+
Environment variable mapping requires a prefix. The object's properties are concatenated with the prefix and then converted to match environment variables. For example, if the configuration object has a property `appId` and the prefix is `cus`, the matching environment variable would be `CUS_APP_ID`.
|
|
36
|
+
|
|
37
|
+
Each call to registerConfig outputs logs showing the matching status for debugging purposes.
|
|
38
|
+
|
|
39
|
+
Example usage of registerConfig:
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
/**
|
|
43
|
+
* Configuration definition
|
|
44
|
+
*/
|
|
45
|
+
interface CustomConfig {
|
|
46
|
+
appId: string
|
|
47
|
+
appSecret: string
|
|
48
|
+
ssl: boolean
|
|
49
|
+
timeout: number
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Call registerConfig to map with environment variables
|
|
53
|
+
// Returns the mapped configuration object
|
|
54
|
+
const config = registerConfig<CustomConfig>(
|
|
55
|
+
// First parameter: default configuration object, must have defaults for fallback
|
|
56
|
+
{ appId: '', appSecret: '', ssl: true, timeout: 5000 },
|
|
57
|
+
// Second parameter: configuration prefix
|
|
58
|
+
'custom',
|
|
59
|
+
// Third parameter: validation rules, optional, see validation component for details
|
|
60
|
+
{
|
|
61
|
+
appId: [notBlank()],
|
|
62
|
+
appSecret: [notBlank()],
|
|
63
|
+
ssl: [notNull()],
|
|
64
|
+
timeout: [notNull(), min(1000), max(3600)]
|
|
65
|
+
}
|
|
66
|
+
)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
You can also skip defining the configuration object and directly write the default configuration object. Automatic type inference is done through the default configuration object in the first parameter, which is more concise.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
const config2 = registerConfig(
|
|
73
|
+
{
|
|
74
|
+
url: 'http://localhost/api',
|
|
75
|
+
account: 'Jack'
|
|
76
|
+
},
|
|
77
|
+
'c2',
|
|
78
|
+
{
|
|
79
|
+
url: [notBlank()]
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## getConfig
|
|
85
|
+
|
|
86
|
+
The getConfig function takes only one parameter, the prefix, and returns the configuration object.
|
|
87
|
+
|
|
88
|
+
This is rarely needed. It is recommended to export the configuration object returned by registerConfig for use by other modules.
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
const config2 = getConfig('c2')
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## generateConfig
|
|
95
|
+
|
|
96
|
+
Generates a configuration object from environment variables with the same parameters as registerConfig. Unlike registerConfig, generateConfig can be called multiple times, making it convenient to regenerate configuration after changing environment variables at runtime. registerConfig locks the configuration once registered and cannot be changed. This design facilitates program testing, simulating program execution in different environments, and other special requirements.
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# Engineering Practices
|
|
2
|
+
|
|
3
|
+
As the program grows in size, we need to split and better organize code files to manage large projects conveniently.
|
|
4
|
+
|
|
5
|
+
The following are recommended practices.
|
|
6
|
+
|
|
7
|
+
## Directory Structure
|
|
8
|
+
|
|
9
|
+
The recommended approach is to organize by feature rather than by traditional layers (service layer, controller layer). This keeps highly related files together, making them easier to find and better for encapsulation.
|
|
10
|
+
|
|
11
|
+
Suppose there are two business functions: user and tag. Here is the project structure:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Root Directory
|
|
15
|
+
├── db-migration Database migration files, only needed when using MySQL
|
|
16
|
+
├── src Source directory
|
|
17
|
+
│ ├── auth Authorization
|
|
18
|
+
│ │ ├── auth.ts Authorization entity configuration
|
|
19
|
+
│ │ ├── auth-interceptor.ts Authorization interceptor
|
|
20
|
+
│ │ ├── create-auth.ts Create authorization endpoint (/auth/create)
|
|
21
|
+
│ │ ├── ccu-task.ts Online user count task
|
|
22
|
+
│ │ └── index.ts Package entry file, exports needed modules
|
|
23
|
+
│ ├── user User business function directory
|
|
24
|
+
│ │ ├── user.ts User entity configuration
|
|
25
|
+
│ │ ├── create-user.ts Create user endpoint (/user/create)
|
|
26
|
+
│ │ ├── delete-user.ts Delete user endpoint (/user/delete)
|
|
27
|
+
│ │ ├── update-user.ts Update user endpoint (/user/update)
|
|
28
|
+
│ │ └── index.ts Package entry file, exports needed modules
|
|
29
|
+
│ ├── tag Tag business function directory
|
|
30
|
+
│ │ ├── tag.ts Tag entity configuration
|
|
31
|
+
│ │ ├── create-tag.ts Create tag endpoint (/tag/create)
|
|
32
|
+
│ │ ├── delete-tag.ts Delete tag endpoint (/tag/delete)
|
|
33
|
+
│ │ └── index.ts Package entry file, exports needed modules
|
|
34
|
+
│ ├── exception.ts Global exceptions
|
|
35
|
+
│ └── main.ts Entry file, starts server, configures routes
|
|
36
|
+
├── .env Development environment variable configuration
|
|
37
|
+
├── package.json
|
|
38
|
+
├── tsconfig.json
|
|
39
|
+
└── .gitignore
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## File Description
|
|
43
|
+
|
|
44
|
+
The exception.ts file contains custom business exceptions and exception handling interceptors.
|
|
45
|
+
|
|
46
|
+
```ts
|
|
47
|
+
/**
|
|
48
|
+
* Custom business exception.
|
|
49
|
+
*/
|
|
50
|
+
export class BusinessException {
|
|
51
|
+
constructor(
|
|
52
|
+
/**
|
|
53
|
+
* Message.
|
|
54
|
+
*/
|
|
55
|
+
readonly message: string,
|
|
56
|
+
/**
|
|
57
|
+
* Custom status code, default 400
|
|
58
|
+
*/
|
|
59
|
+
readonly status?: number
|
|
60
|
+
) {}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Global exception interceptor that handles specific exceptions and provides appropriate response messages.
|
|
65
|
+
* @param exchange
|
|
66
|
+
* @param next
|
|
67
|
+
*/
|
|
68
|
+
export async function globalErrorInterceptor(
|
|
69
|
+
exchange: ServerExchange,
|
|
70
|
+
next: () => Promise<void>
|
|
71
|
+
): Promise<void> {
|
|
72
|
+
try {
|
|
73
|
+
await next()
|
|
74
|
+
} catch (e) {
|
|
75
|
+
// Handle custom business exceptions
|
|
76
|
+
if (e instanceof BusinessException) {
|
|
77
|
+
const status = typeof e.status === 'number' ? e.status : 400
|
|
78
|
+
const message = e.message || ''
|
|
79
|
+
exchange.respondErrMsg(message, status)
|
|
80
|
+
return
|
|
81
|
+
}
|
|
82
|
+
// Handle validation exceptions
|
|
83
|
+
if (e instanceof ValidationException) {
|
|
84
|
+
exchange.respondErrMsg(`${e.propertyPath}: ${e.errMsg}`, 400)
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
// Other exceptions are thrown directly, framework responds with 500 status code by default
|
|
88
|
+
throw e
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Using custom business exceptions to abort request processing when business logic cannot proceed. Transactions will also rollback when exceptions occur during processing. This is the recommended approach.
|
|
94
|
+
|
|
95
|
+
main.ts example:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import { createAuth, authInterceptor, ccuTask } from './auth'
|
|
99
|
+
import { createUser, updateUser, deleteUser } from './user'
|
|
100
|
+
import { createTag, deleteTag } from './tag'
|
|
101
|
+
import { globalErrorInterceptor } from './exception'
|
|
102
|
+
|
|
103
|
+
async function main() {
|
|
104
|
+
// Override Date prototype to serialize dates as numbers
|
|
105
|
+
// Optional, typically done for internationalization
|
|
106
|
+
Date.prototype.toJSON = function () {
|
|
107
|
+
return this.getTime() as any
|
|
108
|
+
}
|
|
109
|
+
// Activate MySQL
|
|
110
|
+
await enableMysql()
|
|
111
|
+
// Start server
|
|
112
|
+
await startWebServer({
|
|
113
|
+
// Static file configuration
|
|
114
|
+
static: {
|
|
115
|
+
// Frontend files
|
|
116
|
+
'/': { dir: 'fe', cacheAge: 600 }
|
|
117
|
+
},
|
|
118
|
+
// If there are many endpoints, it's recommended to write this configuration separately
|
|
119
|
+
// or split further into a separate router directory
|
|
120
|
+
// However, route configuration must be centralized and cannot be placed in individual business function directories
|
|
121
|
+
// Centralization makes it easier to find
|
|
122
|
+
routers: {
|
|
123
|
+
'/auth/create': createAuth,
|
|
124
|
+
'/user/create': createUser,
|
|
125
|
+
'/user/update': updateUser,
|
|
126
|
+
'/user/delete': deleteUser,
|
|
127
|
+
'/tag/create': createTag,
|
|
128
|
+
'/tag/delete': deleteTag
|
|
129
|
+
},
|
|
130
|
+
// Interceptors
|
|
131
|
+
interceptors: [globalErrorInterceptor, authInterceptor]
|
|
132
|
+
})
|
|
133
|
+
// Periodic task
|
|
134
|
+
// Count online users every 60 seconds
|
|
135
|
+
scheduleWithFixedDelay(60, 60, ccuTask)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
main().catch(console.error)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Taking the user function as an example, let's explain entity configuration and endpoint writing.
|
|
142
|
+
|
|
143
|
+
user/user.ts file example:
|
|
144
|
+
|
|
145
|
+
```ts
|
|
146
|
+
import { Table } from 'wok-server'
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* User
|
|
150
|
+
*/
|
|
151
|
+
export interface User {
|
|
152
|
+
id: string
|
|
153
|
+
/**
|
|
154
|
+
* Code.
|
|
155
|
+
*/
|
|
156
|
+
code: string
|
|
157
|
+
/**
|
|
158
|
+
* Nickname
|
|
159
|
+
*/
|
|
160
|
+
nickname: string
|
|
161
|
+
/**
|
|
162
|
+
* Password
|
|
163
|
+
*/
|
|
164
|
+
pwd: string
|
|
165
|
+
/**
|
|
166
|
+
* Status.
|
|
167
|
+
*/
|
|
168
|
+
status: 'ACTIVATED' | 'DISABLED'
|
|
169
|
+
/**
|
|
170
|
+
* Create time.
|
|
171
|
+
*/
|
|
172
|
+
create_at?: Date
|
|
173
|
+
/**
|
|
174
|
+
* Update time.
|
|
175
|
+
*/
|
|
176
|
+
update_at?: Date
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* User table
|
|
181
|
+
*/
|
|
182
|
+
export const tableUser: Table<User> = {
|
|
183
|
+
tableName: 'user',
|
|
184
|
+
id: 'id',
|
|
185
|
+
columns: ['code', 'nickname', 'pwd', 'status'],
|
|
186
|
+
createdDate: {
|
|
187
|
+
type: 'date',
|
|
188
|
+
column: 'create_at'
|
|
189
|
+
},
|
|
190
|
+
updatedDate: {
|
|
191
|
+
type: 'date',
|
|
192
|
+
column: 'update_at'
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
The user.ts file contains the entity type declaration and table configuration information. The example above is for MySQL; MongoDB is slightly different.
|
|
198
|
+
|
|
199
|
+
Our recommendation is to write each endpoint in a separate file, putting all request and response information related to the endpoint in the file, and only exporting the endpoint handler function.
|
|
200
|
+
|
|
201
|
+
user/create-user.ts example:
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
import { createJsonHandler, getMysqlManager, notBlank, length } from 'wok-server'
|
|
205
|
+
import { User, tableUser } from './user'
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Request form information
|
|
209
|
+
*/
|
|
210
|
+
interface Form {
|
|
211
|
+
/**
|
|
212
|
+
* Code.
|
|
213
|
+
*/
|
|
214
|
+
code: string
|
|
215
|
+
/**
|
|
216
|
+
* Nickname
|
|
217
|
+
*/
|
|
218
|
+
nickname: string
|
|
219
|
+
/**
|
|
220
|
+
* Password
|
|
221
|
+
*/
|
|
222
|
+
pwd: string
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Response information
|
|
226
|
+
*/
|
|
227
|
+
interface Resp {
|
|
228
|
+
/**
|
|
229
|
+
* User id
|
|
230
|
+
*/
|
|
231
|
+
id: string
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Create user endpoint /user/create
|
|
236
|
+
*/
|
|
237
|
+
export const createUser = createJsonHandler<Form, Resp>({
|
|
238
|
+
// Validation
|
|
239
|
+
validation: {
|
|
240
|
+
code: [notBlank(), length({ max: 64 })],
|
|
241
|
+
nickname: [notBlank(), length({ max: 64 })],
|
|
242
|
+
pwd: [notBlank(), length({ max: 20 })]
|
|
243
|
+
},
|
|
244
|
+
// Business handling
|
|
245
|
+
async handle(body, exchange) {
|
|
246
|
+
const manager = getMysqlManager()
|
|
247
|
+
if (await manager.existsBy(tableUser, { code: body.code })) {
|
|
248
|
+
// Throw exception to abort processing
|
|
249
|
+
// Exception will be handled by interceptor and responded
|
|
250
|
+
throw new BusinessException('Code already exists')
|
|
251
|
+
}
|
|
252
|
+
const newUser = await manager.insert(tableUser, body)
|
|
253
|
+
return { id: newUser.id }
|
|
254
|
+
}
|
|
255
|
+
})
|
|
256
|
+
```
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# HTTP Client
|
|
2
|
+
|
|
3
|
+
The HTTP client is an HTTP request tool built on top of Node.js's built-in http and https modules, providing three functions.
|
|
4
|
+
|
|
5
|
+
| Function | Description |
|
|
6
|
+
| :--------- | :---------------------------------------------- |
|
|
7
|
+
| doRequest | Generic HTTP request with customizable options |
|
|
8
|
+
| postJson | Send POST request and get JSON response |
|
|
9
|
+
| getJson | Send GET request and get JSON response |
|
|
10
|
+
|
|
11
|
+
## Usage Examples
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
// GET request for JSON
|
|
15
|
+
const list = await getJson<User[]>({
|
|
16
|
+
url: '/users'
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
// POST request for JSON
|
|
20
|
+
const res = await postJson<Result>({
|
|
21
|
+
url: '/data/save',
|
|
22
|
+
body: { name: 'jack', age: 33 }
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
// Use doRequest with more custom options
|
|
26
|
+
await doRequest({
|
|
27
|
+
url: '/users/001',
|
|
28
|
+
method: 'DELETE',
|
|
29
|
+
timeout: 5000,
|
|
30
|
+
followRedirect: true
|
|
31
|
+
})
|
|
32
|
+
```
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Internationalization
|
|
2
|
+
|
|
3
|
+
The internationalization component provides support for multilingual environments, allows extending new internationalization content, and automatically maintains language consistency.
|
|
4
|
+
|
|
5
|
+
The i18n object is global. During request processing with asynchronous operations, you can use binding to maintain consistent language throughout a single request.
|
|
6
|
+
|
|
7
|
+
## No Internationalization Handling
|
|
8
|
+
|
|
9
|
+
By default, the internationalization component automatically updates the language based on the environment. However, when using containers or virtual machines, the image may default to English.
|
|
10
|
+
|
|
11
|
+
If the project doesn't need internationalization and must ensure the framework's prompt messages are in Chinese, you can set the environment variable LANG in the program.
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
// Change environment variable LANG via process to specify Simplified Chinese
|
|
15
|
+
// Must be written before framework import
|
|
16
|
+
process.env.LANG = 'zh-CN'
|
|
17
|
+
// After changing the variable, then import
|
|
18
|
+
import {...} from 'wok-server'
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
If using containers, you can directly set the environment variable for the container, eliminating the need to modify code.
|
|
22
|
+
|
|
23
|
+
## Usage Examples
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
// Get i18n object through getI18n function
|
|
27
|
+
const i18n = getI18n()
|
|
28
|
+
// getLang method gets current language
|
|
29
|
+
const currentLang = i18n.getLang()
|
|
30
|
+
// setLang method switches language, returns boolean indicating success
|
|
31
|
+
// Only supported language tags can be switched successfully
|
|
32
|
+
i18n.setLang('en')
|
|
33
|
+
// buildMsg method builds message based on current language
|
|
34
|
+
// First parameter is key (with type constraints), followed by 0 to multiple template parameters
|
|
35
|
+
// More details in the configuration section below
|
|
36
|
+
const msg = i18n.buildMsg('validate-err-max', '7')
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Language Tags and Matching Rules
|
|
40
|
+
|
|
41
|
+
Currently only language + region format is supported, e.g., en-US, where en represents English and US represents the United States. The region is optional, and you can configure just the language, such as en. Matching is case-insensitive.
|
|
42
|
+
|
|
43
|
+
If only "en-US" is configured but the language is set to "en-GB", it will still succeed. This is because during matching, if no exact language and region match is found, it looks for the language default (i.e., "en"). If the default is also not found, it finds the first configuration from the same language, ultimately using "en-US".
|
|
44
|
+
|
|
45
|
+
If matching fails when switching languages, the switch is not performed and the language remains unchanged. **The default language is not used**. The default language is always en, and any extended i18n object must have English as the default for consistency and to ensure proper program operation.
|
|
46
|
+
|
|
47
|
+
However, during program initialization, the language is automatically switched based on the current environment variables. If LANG or LC_CTYPE variables are set, the switch is performed accordingly. Extended internationalization content needs to be handled separately. See the extension section below for details.
|
|
48
|
+
|
|
49
|
+
## Configure New Languages
|
|
50
|
+
|
|
51
|
+
The following languages are built into the framework:
|
|
52
|
+
|
|
53
|
+
| Language Tag | Language |
|
|
54
|
+
| :----------- | :--------------- |
|
|
55
|
+
| en | English (default)|
|
|
56
|
+
| zh-CN | Simplified Chinese|
|
|
57
|
+
| zh-TW | Traditional Chinese (Taiwan)|
|
|
58
|
+
| zh-HK | Traditional Chinese (Hong Kong)|
|
|
59
|
+
| ja | Japanese |
|
|
60
|
+
| ko | Korean |
|
|
61
|
+
| ru | Russian |
|
|
62
|
+
| es | Spanish |
|
|
63
|
+
| de | German |
|
|
64
|
+
| fr | French |
|
|
65
|
+
| ar | Arabic |
|
|
66
|
+
| pt | Portuguese |
|
|
67
|
+
|
|
68
|
+
If the language you need is not built-in, you need to configure it yourself. Here is example code:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
const i18n = getI18n()
|
|
72
|
+
// Call setMsgs to configure language. First parameter is language tag, second is message templates
|
|
73
|
+
i18n.setMsgs('ja', {
|
|
74
|
+
'validate-err-array': '値が配列ではありません',
|
|
75
|
+
'validate-err-enum': '値は {} の中のいずれかでなければなりません',
|
|
76
|
+
'validate-err-numer': '値が数字ではありません',
|
|
77
|
+
'validate-err-max': '{} 以下である必要があります',
|
|
78
|
+
'validate-err-min': '{} 以上である必要があります',
|
|
79
|
+
'validate-err-empty': '空であってはいけません',
|
|
80
|
+
'validate-err-string': '値が文字列のタイプではありません',
|
|
81
|
+
'validate-err-incorrect-format': '形式が正しくありません',
|
|
82
|
+
'validate-err-no-length': 'length属性が見当たりません',
|
|
83
|
+
'validate-err-length-not-number': 'lengthプロパティは数値ではありません',
|
|
84
|
+
'validate-err-min-length': '長さは {} 以上でなければりません',
|
|
85
|
+
'validate-err-max-length': '長さは {} 以下でなければなりません'
|
|
86
|
+
})
|
|
87
|
+
// After setting, you can successfully switch to the custom language
|
|
88
|
+
i18n.setLang('ja')
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Extend New Content
|
|
92
|
+
|
|
93
|
+
The above are the framework's built-in internationalization contents. In actual project development, there are many business-related internationalization requirements. You can extend new content based on the framework's i18n object. The extended object will maintain the same language as the global i18n object. When you need to change the language, simply call the global i18n object's setLang method.
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
// Get i18n object
|
|
97
|
+
const i18n = getI18n()
|
|
98
|
+
// New language template definition
|
|
99
|
+
interface ExtMsgs {
|
|
100
|
+
hello: string
|
|
101
|
+
world: string
|
|
102
|
+
}
|
|
103
|
+
// Extend new content. Parameter is English template, always use English as default (explained earlier)
|
|
104
|
+
// Returns an I18n type object with methods basically the same as the global i18n object, except without the extend method
|
|
105
|
+
const extI18n = i18n.extend<ExtMsgs>({ hello: 'hello', world: 'world' })
|
|
106
|
+
// Add Chinese to extended content
|
|
107
|
+
extI18n.setMsgs('zh-cn', { hello: '你好', world: '世界' })
|
|
108
|
+
|
|
109
|
+
// When the global i18n object changes language, extI18n also changes
|
|
110
|
+
// In actual development, you can switch to the appropriate language after extension
|
|
111
|
+
i18n.setLang('zh')
|
|
112
|
+
|
|
113
|
+
i18n.getLang() // zh
|
|
114
|
+
extI18n.getLang() // zh
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
In actual development, you can export the extI18n object for use by other modules.
|
|
118
|
+
|
|
119
|
+
Note that for new language templates, values must all be string type, otherwise an error will be thrown. Template content supports 0 to multiple placeholders. For example, `{accountNotExist:"Account {} does not exist"}`, calling `buildMsg('accountNotExist','jack')` returns `"Account jack does not exist"`.
|
|
120
|
+
|
|
121
|
+
## Bind Language
|
|
122
|
+
|
|
123
|
+
Since the i18n object is global and shared, during request processing with asynchronous operations, it's possible that one request changes the language, executes an async operation, then another request changes the language again. When the async operation completes, the language may be incorrect.
|
|
124
|
+
|
|
125
|
+
You can use the language binding feature in this case.
|
|
126
|
+
|
|
127
|
+
```ts
|
|
128
|
+
// Handle request, simplified demonstration, see MVC chapter for details
|
|
129
|
+
async function handleReq(exchange: RouterExchange): Promise<void> {
|
|
130
|
+
// Headers, type is IncomingHttpHeaders, native type from Node.js http module
|
|
131
|
+
const headers = exchange.headers
|
|
132
|
+
// Bind to get a language-fixed i18n object. extI18n is the business internationalization object extended in the above demonstration
|
|
133
|
+
// bindByRequest generates a fixed-language i18n object based on the 'accept-language' header value
|
|
134
|
+
const boundI18n = extI18n.bindByRequest(headers)
|
|
135
|
+
await query1()
|
|
136
|
+
await query2()
|
|
137
|
+
await query3()
|
|
138
|
+
// Built messages are always related to the request's accepted language
|
|
139
|
+
const hello = boundI18n.buildMsg('hello')
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
In addition, the i18n object has a switchByRequest method, which also takes IncomingHttpHeaders as a parameter and switches the language based on the headers.
|
|
@@ -1 +1,25 @@
|
|
|
1
1
|
# node-server
|
|
2
|
+
|
|
3
|
+
A Node.js backend development framework that is simple, easy to use, and has sufficient functionality. Developed with TypeScript, it has complete type definitions and high development efficiency.
|
|
4
|
+
|
|
5
|
+
## Documentation Conventions
|
|
6
|
+
|
|
7
|
+
All demonstration code in the documentation uses TypeScript. It is also recommended to use the framework only in TypeScript projects, as many features depend on type inference.
|
|
8
|
+
|
|
9
|
+
The documentation does not list every option's details, as this would be too much work. However, it will provide as many usage examples as possible. For specific parameters, you can use your editor's documentation preview and jump functions to view the definition files.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- [Internationalization](./i18n.md)
|
|
14
|
+
- [Validation](./validate.md)
|
|
15
|
+
- [Configuration](./config.md)
|
|
16
|
+
- [Logging](./log.md)
|
|
17
|
+
- [Cache](./cache.md)
|
|
18
|
+
- [MySQL](./mysql.md)
|
|
19
|
+
- [MongoDB](./mongodb.md)
|
|
20
|
+
- [MVC](./mvc.md)
|
|
21
|
+
- [Task Scheduling](./task.md)
|
|
22
|
+
- [Lock](./lock.md)
|
|
23
|
+
- [HTTP Client](./http-client.md)
|
|
24
|
+
- [Unit Testing](./test.md)
|
|
25
|
+
- [Engineering Practices](./engineering.md)
|