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
package/src/i18n/tag.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface LangTag {
|
|
2
|
+
lang: string
|
|
3
|
+
region?: string
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* 解析语言标签,语言标签格式非常多,这里仅支持语言加地区的形式,如 zh-CN。
|
|
7
|
+
* 更多信息可以查看 https://www.rfc-editor.org/rfc/bcp/bcp47.txt 。
|
|
8
|
+
* @param tag
|
|
9
|
+
* @returns 语言和地区信息,为了方便匹配,全转小写
|
|
10
|
+
*/
|
|
11
|
+
export function parseLangTag(tag: string): LangTag {
|
|
12
|
+
const [lang, region] = tag.split('-')
|
|
13
|
+
// 解析失败,抛出错误
|
|
14
|
+
if (!lang) {
|
|
15
|
+
throw new Error(`Unable to parse lang tag:${tag}`)
|
|
16
|
+
}
|
|
17
|
+
return { lang: lang.toLowerCase(), region: region ? region.toLowerCase() : undefined }
|
|
18
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { I18nMsgs } from "./msg";
|
|
2
|
+
|
|
3
|
+
export const zhHK: I18nMsgs = {
|
|
4
|
+
'validate-err-array': '值不是陣列',
|
|
5
|
+
'validate-err-enum': '值必須是 {} 其中一個',
|
|
6
|
+
'validate-err-numer': '值不是數字',
|
|
7
|
+
'validate-err-max': '不得大於 {}',
|
|
8
|
+
'validate-err-min': '不得小於 {}',
|
|
9
|
+
'validate-err-empty': '不能為空',
|
|
10
|
+
'validate-err-string': '值不是字串型別',
|
|
11
|
+
'validate-err-incorrect-format': '格式不正確',
|
|
12
|
+
'validate-err-no-length': '找不到 length 屬性',
|
|
13
|
+
'validate-err-length-not-number': 'length 屬性不是數字',
|
|
14
|
+
'validate-err-min-length': '長度不得小於 {}',
|
|
15
|
+
'validate-err-max-length': '長度不得大於 {}'
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { I18nMsgs } from './msg'
|
|
2
|
+
|
|
3
|
+
export const zhTW: I18nMsgs = {
|
|
4
|
+
'validate-err-array': '值不是陣列',
|
|
5
|
+
'validate-err-enum': '值必須是 {} 其中一個',
|
|
6
|
+
'validate-err-numer': '值不是數字',
|
|
7
|
+
'validate-err-max': '不得大於 {}',
|
|
8
|
+
'validate-err-min': '不得小於 {}',
|
|
9
|
+
'validate-err-empty': '不能為空',
|
|
10
|
+
'validate-err-string': '值不是字串型別',
|
|
11
|
+
'validate-err-incorrect-format': '格式不正確',
|
|
12
|
+
'validate-err-no-length': '找不到 length 屬性',
|
|
13
|
+
'validate-err-length-not-number': 'length 屬性不是數字',
|
|
14
|
+
'validate-err-min-length': '長度不得小於 {}',
|
|
15
|
+
'validate-err-max-length': '長度不得大於 {}'
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { I18nMsgs } from './msg'
|
|
2
|
+
|
|
3
|
+
export const zhCN: I18nMsgs = {
|
|
4
|
+
'validate-err-array': '值不是数组',
|
|
5
|
+
'validate-err-enum': '值必须是 {} 其中一个',
|
|
6
|
+
'validate-err-numer': '值不是数字',
|
|
7
|
+
'validate-err-max': '不得大于 {}',
|
|
8
|
+
'validate-err-min': '不得小于 {}',
|
|
9
|
+
'validate-err-empty': '不能为空',
|
|
10
|
+
'validate-err-string': '值不是字符串类型',
|
|
11
|
+
'validate-err-incorrect-format': '格式不正确',
|
|
12
|
+
'validate-err-no-length': '找不到 length 属性',
|
|
13
|
+
'validate-err-length-not-number': 'length 属性不是数字',
|
|
14
|
+
'validate-err-min-length': '长度不得小于 {}',
|
|
15
|
+
'validate-err-max-length': '长度不得大于 {}'
|
|
16
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './log'
|
|
2
|
+
export * from './i18n'
|
|
3
|
+
export * from './validation'
|
|
4
|
+
export * from './config'
|
|
5
|
+
export * from './cache'
|
|
6
|
+
export * from './task'
|
|
7
|
+
export * from './mvc'
|
|
8
|
+
export * from './mysql'
|
|
9
|
+
export * from './http-client'
|
|
10
|
+
export * from './mongodb'
|
|
11
|
+
export * from './lock'
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto'
|
|
2
|
+
|
|
3
|
+
export interface LockInfo {
|
|
4
|
+
/**
|
|
5
|
+
* 一个随机值,用于验证锁是否为当前程序所拥有
|
|
6
|
+
*/
|
|
7
|
+
value: string
|
|
8
|
+
/**
|
|
9
|
+
* 锁过期的时间
|
|
10
|
+
*/
|
|
11
|
+
expiresAt: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* 锁管理器,主要用于将不确定的顺序且有冲突的异步操作顺序执行,
|
|
16
|
+
* 防止异步流程庞大穿插执行造成的数据混乱和错误,常见于请求的处理。
|
|
17
|
+
*/
|
|
18
|
+
class ServerLockManager {
|
|
19
|
+
/**
|
|
20
|
+
* 存储锁信息的表,值是一个随机值,用于验证锁是否为当前程序所拥有
|
|
21
|
+
*/
|
|
22
|
+
private lockMap = new Map<string, LockInfo>()
|
|
23
|
+
|
|
24
|
+
constructor() {
|
|
25
|
+
// 定期清理,将过期的信息移除,防止内存泄漏
|
|
26
|
+
setTimeout(() => {
|
|
27
|
+
const keysToBeDeleted: string[] = []
|
|
28
|
+
const now = Date.now()
|
|
29
|
+
for (const entry of this.lockMap.entries()) {
|
|
30
|
+
const [key, info] = entry
|
|
31
|
+
if (info.expiresAt < now) {
|
|
32
|
+
keysToBeDeleted.push(key)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (keysToBeDeleted.length) {
|
|
36
|
+
for (const key of keysToBeDeleted) {
|
|
37
|
+
this.lockMap.delete(key)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}, 10000)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* 尝试竞争锁,如果成功获取到锁,则执行 run 函数
|
|
45
|
+
* @param opts
|
|
46
|
+
* @returns 是否获取到锁
|
|
47
|
+
*/
|
|
48
|
+
async tryLock(opts: {
|
|
49
|
+
/**
|
|
50
|
+
* 竞争锁的标识,相同的 key 会处于竞争关系,从而按顺序执行
|
|
51
|
+
*/
|
|
52
|
+
key: string
|
|
53
|
+
/**
|
|
54
|
+
* 等待秒数,如果没有获取锁,要等待的时间,单位秒。
|
|
55
|
+
* 不设置的情况下则不会等待,获取不到锁就立即返回。
|
|
56
|
+
*/
|
|
57
|
+
waitSeconds?: number
|
|
58
|
+
/**
|
|
59
|
+
* 运行函数,成功获取锁就会执行
|
|
60
|
+
* @returns
|
|
61
|
+
*/
|
|
62
|
+
run: () => Promise<void>
|
|
63
|
+
/**
|
|
64
|
+
* 过期时间,单位秒。目的是防止一个程序长期占用锁,导致其它程序获取不到锁一直不能被执行
|
|
65
|
+
* 导致的死锁问题。锁一旦过期,当前程序就不再拥有锁,其它程序就可以获取到锁。默认 60 秒。
|
|
66
|
+
*/
|
|
67
|
+
expiresInSeconds?: number
|
|
68
|
+
}): Promise<boolean> {
|
|
69
|
+
const value = randomUUID().toString()
|
|
70
|
+
const expiresInSeconds =
|
|
71
|
+
typeof opts.expiresInSeconds === 'number' && opts.expiresInSeconds > 0
|
|
72
|
+
? opts.expiresInSeconds
|
|
73
|
+
: 60
|
|
74
|
+
const expiresAt = Date.now() + expiresInSeconds * 1000
|
|
75
|
+
const waitSeconds =
|
|
76
|
+
typeof opts.waitSeconds === 'number' && opts.waitSeconds > 0 ? opts.waitSeconds : 0
|
|
77
|
+
const res = await this.waitLock({
|
|
78
|
+
key: opts.key,
|
|
79
|
+
value,
|
|
80
|
+
expiresAt,
|
|
81
|
+
waitSeconds
|
|
82
|
+
})
|
|
83
|
+
if (!res) {
|
|
84
|
+
return false
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
await opts.run()
|
|
88
|
+
} finally {
|
|
89
|
+
// 解锁
|
|
90
|
+
const info = this.lockMap.get(opts.key)
|
|
91
|
+
if (info && info.value === value) {
|
|
92
|
+
this.lockMap.delete(opts.key)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return true
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* 等待锁
|
|
99
|
+
* @param opts
|
|
100
|
+
*/
|
|
101
|
+
private async waitLock(opts: {
|
|
102
|
+
/**
|
|
103
|
+
* 竞争锁的标识,相同的 key 会处于竞争关系,从而按顺序执行
|
|
104
|
+
*/
|
|
105
|
+
key: string
|
|
106
|
+
/**
|
|
107
|
+
* 值
|
|
108
|
+
*/
|
|
109
|
+
value: string
|
|
110
|
+
/**
|
|
111
|
+
* 等待秒数,如果没有获取锁,要等待的时间,单位秒。
|
|
112
|
+
*/
|
|
113
|
+
waitSeconds: number
|
|
114
|
+
/**
|
|
115
|
+
* 过期时间
|
|
116
|
+
*/
|
|
117
|
+
expiresAt: number
|
|
118
|
+
}): Promise<boolean> {
|
|
119
|
+
let start = Date.now()
|
|
120
|
+
while (true) {
|
|
121
|
+
const info = this.lockMap.get(opts.key)
|
|
122
|
+
// 锁不存在或已经过期
|
|
123
|
+
if (!info || info.expiresAt < Date.now()) {
|
|
124
|
+
// 成功获取到锁
|
|
125
|
+
this.lockMap.set(opts.key, {
|
|
126
|
+
value: opts.value,
|
|
127
|
+
expiresAt: opts.expiresAt
|
|
128
|
+
})
|
|
129
|
+
return true
|
|
130
|
+
}
|
|
131
|
+
if (info.value === opts.value) {
|
|
132
|
+
return true
|
|
133
|
+
}
|
|
134
|
+
if (Date.now() - start > opts.waitSeconds * 1000) {
|
|
135
|
+
break
|
|
136
|
+
}
|
|
137
|
+
await this.sleep()
|
|
138
|
+
}
|
|
139
|
+
return false
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* 沉睡
|
|
143
|
+
* @returns
|
|
144
|
+
*/
|
|
145
|
+
private sleep() {
|
|
146
|
+
return new Promise<void>((resolve, reject) => {
|
|
147
|
+
setTimeout(resolve, 0)
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
let lockManager: ServerLockManager | undefined
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* 获取锁管理器。锁管理器提供一个简单的异步并发控制,用于将不确定的顺序的有冲突的异步操作顺序执行,
|
|
156
|
+
* 防止异步流程庞大穿插执行造成的数据混乱和错误,常见于请求的处理。
|
|
157
|
+
* @returns
|
|
158
|
+
*/
|
|
159
|
+
export function getLockManager(): ServerLockManager {
|
|
160
|
+
if (!lockManager) {
|
|
161
|
+
lockManager = new ServerLockManager()
|
|
162
|
+
}
|
|
163
|
+
return lockManager
|
|
164
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { isAbsolute, resolve } from 'path'
|
|
2
|
+
import { registerConfig } from '../config'
|
|
3
|
+
import { min, notBlank, notNull } from '../validation'
|
|
4
|
+
import { LogLevel, parseLogLevel } from './level'
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* 日志配置的定义
|
|
8
|
+
*/
|
|
9
|
+
interface EnvConfig {
|
|
10
|
+
/**
|
|
11
|
+
* 是否输出日志到控制台
|
|
12
|
+
*/
|
|
13
|
+
console: boolean
|
|
14
|
+
/**
|
|
15
|
+
* 输出日志的格式
|
|
16
|
+
*/
|
|
17
|
+
format: 'text' | 'json'
|
|
18
|
+
/**
|
|
19
|
+
* 是否输出到文件,如果为 true ,则会在根目录下生成 logs 目录存放日志文件.
|
|
20
|
+
*/
|
|
21
|
+
file: boolean
|
|
22
|
+
/**
|
|
23
|
+
* 文件目录
|
|
24
|
+
*/
|
|
25
|
+
fileDir: string
|
|
26
|
+
/**
|
|
27
|
+
* 文件最大保存天数.需要开启文件才有效.
|
|
28
|
+
*/
|
|
29
|
+
fileMaxDays: number
|
|
30
|
+
/**
|
|
31
|
+
* 要输出的日志级别.
|
|
32
|
+
*/
|
|
33
|
+
level: string
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const envConfig = registerConfig<EnvConfig>(
|
|
37
|
+
{
|
|
38
|
+
console: true,
|
|
39
|
+
format: 'text',
|
|
40
|
+
file: false,
|
|
41
|
+
fileDir: 'logs',
|
|
42
|
+
fileMaxDays: 30,
|
|
43
|
+
level: 'INFO'
|
|
44
|
+
},
|
|
45
|
+
'LOG',
|
|
46
|
+
{
|
|
47
|
+
console: [notNull()],
|
|
48
|
+
format: [notNull()],
|
|
49
|
+
file: [notNull()],
|
|
50
|
+
fileDir: [notBlank()],
|
|
51
|
+
fileMaxDays: [min(1)],
|
|
52
|
+
level: [notBlank()]
|
|
53
|
+
}
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
export type LogConfig = Omit<EnvConfig, 'level'> & { level: LogLevel }
|
|
57
|
+
|
|
58
|
+
let { fileDir, level } = envConfig
|
|
59
|
+
// 目录处理
|
|
60
|
+
if (!isAbsolute(fileDir)) {
|
|
61
|
+
fileDir = resolve(process.cwd(), fileDir)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const config: LogConfig = Object.freeze({
|
|
65
|
+
file: envConfig.file,
|
|
66
|
+
fileDir,
|
|
67
|
+
fileMaxDays: envConfig.fileMaxDays,
|
|
68
|
+
level: parseLogLevel(level),
|
|
69
|
+
console: envConfig.console,
|
|
70
|
+
format: envConfig.format
|
|
71
|
+
})
|
package/src/log/date.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function currentDateTimeStr() {
|
|
2
|
+
return formatDateTime(new Date())
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function formatDateTime(date: Date) {
|
|
6
|
+
return (
|
|
7
|
+
date.toLocaleString('zh-CN', {
|
|
8
|
+
timeZone: 'Asia/Shanghai',
|
|
9
|
+
year: 'numeric',
|
|
10
|
+
month: '2-digit',
|
|
11
|
+
day: '2-digit',
|
|
12
|
+
hour: '2-digit',
|
|
13
|
+
minute: '2-digit',
|
|
14
|
+
second: '2-digit',
|
|
15
|
+
hour12: false,
|
|
16
|
+
hourCycle: 'h23'
|
|
17
|
+
}) + `.${date.getMilliseconds()}`
|
|
18
|
+
)
|
|
19
|
+
}
|
package/src/log/file.ts
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import { existsSync, statSync } from 'fs'
|
|
2
|
+
import { readdir, rm, appendFile, mkdir } from 'fs/promises'
|
|
3
|
+
import { EOL } from 'os'
|
|
4
|
+
import { dirname, resolve, isAbsolute } from 'path'
|
|
5
|
+
import { config, LogConfig } from './config'
|
|
6
|
+
import { formatLogJson, formatLogText, Log } from './log'
|
|
7
|
+
|
|
8
|
+
// 日志队列
|
|
9
|
+
let LOG_QUEUE: Log[] = []
|
|
10
|
+
// 最大缓冲数量
|
|
11
|
+
const MAX_QUEUE_SIZE = 1024
|
|
12
|
+
// 写入定时器
|
|
13
|
+
let WRITE_TIMER: NodeJS.Timeout | null = null
|
|
14
|
+
// 延迟写入时间(毫秒)
|
|
15
|
+
const WRITE_DELAY = 100
|
|
16
|
+
// 是否已经安排了清理任务
|
|
17
|
+
let CLEANUP_SCHEDULED = false
|
|
18
|
+
// 清理任务定时器
|
|
19
|
+
let CLEANUP_TIMER: NodeJS.Timeout | null = null
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* 文件存储.
|
|
23
|
+
* @param log 日志对象
|
|
24
|
+
* @param logConfig 日志配置
|
|
25
|
+
*/
|
|
26
|
+
export function fileStore(log: Log, logConfig: LogConfig): void {
|
|
27
|
+
// 将日志添加到队列
|
|
28
|
+
LOG_QUEUE.push(log)
|
|
29
|
+
|
|
30
|
+
// 如果队列超过最大缓冲数量,立即写入
|
|
31
|
+
if (LOG_QUEUE.length >= MAX_QUEUE_SIZE) {
|
|
32
|
+
writeLogs(logConfig).catch(e => console.error('Writing log file failed', e))
|
|
33
|
+
|
|
34
|
+
// 在写入前检查是否需要安排清理任务
|
|
35
|
+
if (!CLEANUP_SCHEDULED) {
|
|
36
|
+
scheduleCleanupTask(logConfig)
|
|
37
|
+
}
|
|
38
|
+
return
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// 安排延迟写入
|
|
42
|
+
if (!WRITE_TIMER) {
|
|
43
|
+
WRITE_TIMER = setTimeout(() => {
|
|
44
|
+
WRITE_TIMER = null
|
|
45
|
+
writeLogs(logConfig).catch(e => console.error('Writing log file failed', e))
|
|
46
|
+
}, WRITE_DELAY)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 如果启用了文件存储并且还没有安排清理任务,则安排清理任务
|
|
50
|
+
if (!CLEANUP_SCHEDULED) {
|
|
51
|
+
scheduleCleanupTask(logConfig)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* 根据日期构建日志文件路径
|
|
57
|
+
* @param logConfig 日志配置
|
|
58
|
+
* @param dateKey 数字键 (格式:年*10000 + 月*100 + 日)
|
|
59
|
+
* @returns 日志文件路径
|
|
60
|
+
*/
|
|
61
|
+
function buildFilePathByDate(logConfig: LogConfig, dateKey: number): string {
|
|
62
|
+
const fileName = `${dateKey}.log`
|
|
63
|
+
// 确保目录是绝对路径
|
|
64
|
+
let fileDir = logConfig.fileDir
|
|
65
|
+
if (!isAbsolute(fileDir)) {
|
|
66
|
+
fileDir = resolve(process.cwd(), fileDir)
|
|
67
|
+
}
|
|
68
|
+
return resolve(fileDir, fileName)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* 根据日期对象计算数字键
|
|
73
|
+
* @param date 日期对象
|
|
74
|
+
* @returns 数字键 (格式:年*10000 + 月*100 + 日)
|
|
75
|
+
*/
|
|
76
|
+
function calculateDateKey(date: Date): number {
|
|
77
|
+
const year = date.getFullYear()
|
|
78
|
+
const month = date.getMonth() + 1 // 转换为1-12
|
|
79
|
+
const day = date.getDate()
|
|
80
|
+
return year * 10000 + month * 100 + day
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* 写入日志到文件
|
|
85
|
+
* @param logConfig 日志配置
|
|
86
|
+
*/
|
|
87
|
+
async function writeLogs(logConfig: LogConfig): Promise<void> {
|
|
88
|
+
if (!LOG_QUEUE.length || !logConfig.file) {
|
|
89
|
+
return
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// 复制队列并清空原始队列
|
|
93
|
+
const logsToWrite = [...LOG_QUEUE]
|
|
94
|
+
LOG_QUEUE = []
|
|
95
|
+
|
|
96
|
+
// 按日期对日志进行分组 - 使用数字键提升性能
|
|
97
|
+
const logsByDate = new Map<number, Log[]>()
|
|
98
|
+
|
|
99
|
+
logsToWrite.forEach(log => {
|
|
100
|
+
const logDate = new Date(log.time)
|
|
101
|
+
// 直接使用日期对象计算数字键
|
|
102
|
+
const dateKey = calculateDateKey(logDate)
|
|
103
|
+
const dateLogs = logsByDate.get(dateKey)
|
|
104
|
+
if (dateLogs) {
|
|
105
|
+
dateLogs.push(log)
|
|
106
|
+
} else {
|
|
107
|
+
logsByDate.set(dateKey, [log])
|
|
108
|
+
}
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
// 为每个日期组写入对应的日志文件
|
|
112
|
+
for (const [dateKey, dateLogs] of logsByDate.entries()) {
|
|
113
|
+
// 直接使用数字键构建文件路径
|
|
114
|
+
const filePath = buildFilePathByDate(logConfig, dateKey)
|
|
115
|
+
const dir = dirname(filePath)
|
|
116
|
+
|
|
117
|
+
// 确保目录存在
|
|
118
|
+
if (!existsSync(dir)) {
|
|
119
|
+
await mkdir(dir, { recursive: true })
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// 格式化并写入该日期的所有日志
|
|
123
|
+
const lines = dateLogs
|
|
124
|
+
.map(log => (logConfig.format === 'json' ? formatLogJson(log) : formatLogText(log)))
|
|
125
|
+
.join(EOL)
|
|
126
|
+
|
|
127
|
+
try {
|
|
128
|
+
await appendFile(filePath, lines)
|
|
129
|
+
} catch (error) {
|
|
130
|
+
console.error(`Failed to write logs for date ${dateKey}:`, error)
|
|
131
|
+
// 继续处理下一个日期的日志,不中断整个写入过程
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* 执行日志清理任务
|
|
138
|
+
* @param logConfig 日志配置
|
|
139
|
+
*/
|
|
140
|
+
async function performCleanupTask(logConfig: LogConfig): Promise<void> {
|
|
141
|
+
try {
|
|
142
|
+
let dir = logConfig.fileDir
|
|
143
|
+
if (!isAbsolute(dir)) {
|
|
144
|
+
dir = resolve(process.cwd(), dir)
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// 确保目录存在
|
|
148
|
+
if (!existsSync(dir)) {
|
|
149
|
+
return
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const files = await readdir(dir)
|
|
153
|
+
const now = new Date().getTime()
|
|
154
|
+
const maxAge = logConfig.fileMaxDays * 24 * 3600 * 1000
|
|
155
|
+
|
|
156
|
+
for (const file of files) {
|
|
157
|
+
try {
|
|
158
|
+
// 获取文件的完整路径
|
|
159
|
+
const filePath = resolve(dir, file)
|
|
160
|
+
|
|
161
|
+
// 获取文件的最后修改时间
|
|
162
|
+
const fileStats = statSync(filePath)
|
|
163
|
+
const lastModifiedTime = fileStats.mtime.getTime()
|
|
164
|
+
|
|
165
|
+
// 检查文件是否过期(最后修改时间早于最大保留天数)
|
|
166
|
+
if (lastModifiedTime + maxAge < now) {
|
|
167
|
+
console.warn(`Remove log file: ${file}`)
|
|
168
|
+
await rm(filePath)
|
|
169
|
+
}
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.error(`Failed to process log file ${file}:`, error)
|
|
172
|
+
// 继续处理下一个文件,不中断清理过程
|
|
173
|
+
continue
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
} catch (error) {
|
|
177
|
+
console.error('Error during log cleanup:', error)
|
|
178
|
+
} finally {
|
|
179
|
+
// 清理完成后,重置清理任务安排状态
|
|
180
|
+
CLEANUP_SCHEDULED = false
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* 安排日志清理任务
|
|
186
|
+
* @param logConfig 日志配置
|
|
187
|
+
*/
|
|
188
|
+
function scheduleCleanupTask(logConfig: LogConfig): void {
|
|
189
|
+
CLEANUP_SCHEDULED = true
|
|
190
|
+
|
|
191
|
+
// 清除现有的清理定时器
|
|
192
|
+
if (CLEANUP_TIMER) {
|
|
193
|
+
clearTimeout(CLEANUP_TIMER)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// 设置清理任务在一天后执行
|
|
197
|
+
const delay = 24 * 60 * 60 * 1000
|
|
198
|
+
CLEANUP_TIMER = setTimeout(() => {
|
|
199
|
+
CLEANUP_TIMER = null
|
|
200
|
+
performCleanupTask(logConfig).catch(e => console.error('Cleanup task failed', e))
|
|
201
|
+
}, delay)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* 确保所有日志都被写入文件
|
|
206
|
+
* 可以在应用程序关闭时调用
|
|
207
|
+
*/
|
|
208
|
+
export async function flushLogsToFile(): Promise<void> {
|
|
209
|
+
if (WRITE_TIMER) {
|
|
210
|
+
clearTimeout(WRITE_TIMER)
|
|
211
|
+
WRITE_TIMER = null
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
await writeLogs(config)
|
|
215
|
+
}
|
package/src/log/index.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { config } from './config'
|
|
2
|
+
import { fileStore } from './file'
|
|
3
|
+
import { LogLevel } from './level'
|
|
4
|
+
import { formatLogJson, formatLogText, Log } from './log'
|
|
5
|
+
import { getLogStore, setLogStore } from './store'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* 文件存储
|
|
9
|
+
*/
|
|
10
|
+
if (config.file) {
|
|
11
|
+
setLogStore(fileStore)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class Logger {
|
|
15
|
+
constructor(private prefix?: string) {}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 输出日志
|
|
19
|
+
* @param level
|
|
20
|
+
* @param message
|
|
21
|
+
* @param error
|
|
22
|
+
*/
|
|
23
|
+
private log(level: LogLevel, message: string, error?: any) {
|
|
24
|
+
if (level < config.level) {
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
const log: Log = {
|
|
28
|
+
level,
|
|
29
|
+
content: message,
|
|
30
|
+
time: new Date(),
|
|
31
|
+
prefix: this.prefix,
|
|
32
|
+
error
|
|
33
|
+
}
|
|
34
|
+
// 控制台输出日志
|
|
35
|
+
if (config.console) {
|
|
36
|
+
// const msg = config.format === 'text' ? formatLogText(log, true) : formatLogJson(log, true)
|
|
37
|
+
// 控制台强制使用 text 格式,json 格式只在文件中输出
|
|
38
|
+
const msg = formatLogText(log, true)
|
|
39
|
+
switch (level) {
|
|
40
|
+
case LogLevel.DEBUG:
|
|
41
|
+
console.debug(msg)
|
|
42
|
+
break
|
|
43
|
+
case LogLevel.INFO:
|
|
44
|
+
console.info(msg)
|
|
45
|
+
break
|
|
46
|
+
case LogLevel.WARN:
|
|
47
|
+
console.warn(msg)
|
|
48
|
+
break
|
|
49
|
+
case LogLevel.ERROR:
|
|
50
|
+
console.error(msg)
|
|
51
|
+
break
|
|
52
|
+
}
|
|
53
|
+
if (error) {
|
|
54
|
+
console.error(error)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// 自定义存储中输出日志
|
|
58
|
+
const store = getLogStore()
|
|
59
|
+
if (store) {
|
|
60
|
+
store(log, config)
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* debug 日志
|
|
65
|
+
*/
|
|
66
|
+
debug(message: string) {
|
|
67
|
+
this.log(LogLevel.DEBUG, message)
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
isDebugEnabled() {
|
|
71
|
+
return LogLevel.DEBUG >= config.level
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* info 日志
|
|
75
|
+
* @param message
|
|
76
|
+
*/
|
|
77
|
+
info(message: string) {
|
|
78
|
+
this.log(LogLevel.INFO, message)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
isInfoEnabled() {
|
|
82
|
+
return LogLevel.INFO >= config.level
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* 警告日志
|
|
86
|
+
* @param message
|
|
87
|
+
* @param error
|
|
88
|
+
*/
|
|
89
|
+
warn(message: string, error?: any) {
|
|
90
|
+
this.log(LogLevel.WARN, message, error)
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* 等同于 warn
|
|
94
|
+
* @param message
|
|
95
|
+
* @param error
|
|
96
|
+
*/
|
|
97
|
+
warning(message: string, error?: any) {
|
|
98
|
+
this.log(LogLevel.WARN, message, error)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
isWarnEnabled() {
|
|
102
|
+
return LogLevel.WARN >= config.level
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* 错误日志
|
|
106
|
+
* @param message
|
|
107
|
+
* @param error
|
|
108
|
+
*/
|
|
109
|
+
error(message: string, error?: any) {
|
|
110
|
+
this.log(LogLevel.ERROR, message, error)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
isErrorEnabled() {
|
|
114
|
+
return LogLevel.ERROR >= config.level
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const defaultLogger = new Logger()
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* 获取日志对象.
|
|
122
|
+
*
|
|
123
|
+
* @param prefix 日志前缀,如果有值,每条日志前都会加上前缀信息
|
|
124
|
+
* @returns
|
|
125
|
+
*/
|
|
126
|
+
export function getLogger(prefix?: string) {
|
|
127
|
+
if (prefix) {
|
|
128
|
+
return new Logger(prefix)
|
|
129
|
+
}
|
|
130
|
+
return defaultLogger
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export * from './config'
|
|
134
|
+
export * from './level'
|
|
135
|
+
export * from './log'
|
|
136
|
+
export { setLogStore } from './store'
|