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
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Validation
|
|
2
|
+
|
|
3
|
+
The validation component provides a validate function to validate objects with many built-in validation rules. The component supports internationalization, and error messages depend on the current language. See the internationalization section for details.
|
|
4
|
+
|
|
5
|
+
Here is a simple usage example:
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
validate(
|
|
9
|
+
// Object to validate
|
|
10
|
+
{ name: 'tom' },
|
|
11
|
+
// Validation rules, multiple rules per property
|
|
12
|
+
{
|
|
13
|
+
name: [notNull(), length({ min: 2, max: 16 })]
|
|
14
|
+
}
|
|
15
|
+
)
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Built-in validation rule functions:
|
|
19
|
+
|
|
20
|
+
| Function | Description |
|
|
21
|
+
| :------------ | :----------------------------------------------------------------------- |
|
|
22
|
+
| notNull | Not null validation, cannot be null or undefined |
|
|
23
|
+
| notBlank | Not blank validation, cannot be null, undefined, or blank string |
|
|
24
|
+
| min | Validate minimum number value |
|
|
25
|
+
| max | Validate maximum number value |
|
|
26
|
+
| length | Validate length, applicable to strings and arrays |
|
|
27
|
+
| maxLength | Check maximum length, applicable to strings and arrays |
|
|
28
|
+
| minLength | Check minimum length, applicable to strings and arrays |
|
|
29
|
+
| regexp | Regular expression validation |
|
|
30
|
+
| enumerate | Enumeration validation, value must be one of the specified list |
|
|
31
|
+
| array | Array validation, set element validation rules to validate each element |
|
|
32
|
+
| plainObject | Object validation, validate nested object properties |
|
|
33
|
+
|
|
34
|
+
Here is an example of nested object and array validation:
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
interface Tag {
|
|
38
|
+
id: string
|
|
39
|
+
name: string
|
|
40
|
+
permissinos: { edit?: boolean; read?: boolean }
|
|
41
|
+
}
|
|
42
|
+
interface User {
|
|
43
|
+
profile: {
|
|
44
|
+
theme: string
|
|
45
|
+
}
|
|
46
|
+
tags: Tag[]
|
|
47
|
+
}
|
|
48
|
+
validate<User>(
|
|
49
|
+
{
|
|
50
|
+
profile: {
|
|
51
|
+
theme: 'light'
|
|
52
|
+
},
|
|
53
|
+
tags: [
|
|
54
|
+
{ id: '001', name: 'basketball', permissinos: { edit: true, read: true } },
|
|
55
|
+
{ id: '002', name: 'soccer', permissinos: { edit: true } }
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
profile: [
|
|
60
|
+
notNull(),
|
|
61
|
+
plainObject({
|
|
62
|
+
theme: [notBlank()]
|
|
63
|
+
})
|
|
64
|
+
],
|
|
65
|
+
tags: [
|
|
66
|
+
// Maximum 5 tags
|
|
67
|
+
maxLength(5),
|
|
68
|
+
// Tags list cannot be null
|
|
69
|
+
notNull(),
|
|
70
|
+
// Validate tag array elements
|
|
71
|
+
array([
|
|
72
|
+
// Element cannot be null
|
|
73
|
+
notNull(),
|
|
74
|
+
// Element property validation
|
|
75
|
+
plainObject({
|
|
76
|
+
id: [notBlank()],
|
|
77
|
+
name: [notBlank()],
|
|
78
|
+
permissinos: [
|
|
79
|
+
notNull(),
|
|
80
|
+
plainObject({
|
|
81
|
+
edit: [notNull()],
|
|
82
|
+
read: [notNull()]
|
|
83
|
+
})
|
|
84
|
+
]
|
|
85
|
+
})
|
|
86
|
+
])
|
|
87
|
+
]
|
|
88
|
+
}
|
|
89
|
+
)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
In actual development, it's recommended to keep validation at most one level deep, without nesting, otherwise the program will be difficult to maintain.
|
|
93
|
+
|
|
94
|
+
## Custom Validation Rules
|
|
95
|
+
|
|
96
|
+
If the built-in validation rules cannot meet your needs, you can write custom validation rules.
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
/**
|
|
100
|
+
* Custom validation
|
|
101
|
+
* @returns Property validator
|
|
102
|
+
*/
|
|
103
|
+
function customValidate(): PropValidator {
|
|
104
|
+
// Validator name for tracking
|
|
105
|
+
const validator = 'custom'
|
|
106
|
+
const message = 'Cannot start with t'
|
|
107
|
+
return val => {
|
|
108
|
+
// Skip null validation
|
|
109
|
+
if (!val) {
|
|
110
|
+
return { ok: true }
|
|
111
|
+
}
|
|
112
|
+
if (typeof val !== 'string') {
|
|
113
|
+
return { ok: false, validator, message: 'Value is not a string' }
|
|
114
|
+
}
|
|
115
|
+
if (val.startsWith('t')) {
|
|
116
|
+
return { ok: false, validator, message }
|
|
117
|
+
}
|
|
118
|
+
return { ok: true }
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
validate(
|
|
123
|
+
{ name: 'tim' },
|
|
124
|
+
{
|
|
125
|
+
name: [customValidate()]
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
Built-in validation rules have internationalization support. If you need internationalization for custom validation rules, you need to handle it yourself. See the internationalization chapter for details.
|
|
@@ -632,36 +632,78 @@ await startWebServer({
|
|
|
632
632
|
|
|
633
633
|
### Server-Sent Events
|
|
634
634
|
|
|
635
|
-
|
|
635
|
+
从 0.6.0 版本开始,MVC 组件内置了 `createSseHandler`,封装了 SSE 协议细节,大幅简化服务端推送实现。
|
|
636
636
|
|
|
637
637
|
```ts
|
|
638
|
-
|
|
638
|
+
import { createSseHandler } from 'wok-server'
|
|
639
|
+
|
|
639
640
|
await startWebServer({
|
|
640
|
-
// 路由配置
|
|
641
641
|
routers: {
|
|
642
|
-
'/sse':
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
await new Promise<void>((resolve, reject) => {
|
|
653
|
-
setTimeout(resolve, 1000)
|
|
654
|
-
})
|
|
655
|
-
counter++
|
|
656
|
-
// 写数据到响应信息中,前端在 EventSource 的 message 事件中处理
|
|
657
|
-
response.write(`data: ${JSON.stringify({ message: '实时更新', count: counter })}\n\n`)
|
|
658
|
-
if (counter >= 10) {
|
|
659
|
-
break
|
|
642
|
+
'/sse': createSseHandler({
|
|
643
|
+
async handle(ctx) {
|
|
644
|
+
let counter = 0
|
|
645
|
+
for (let i = 0; i < 10; i++) {
|
|
646
|
+
await new Promise<void>(resolve => setTimeout(resolve, 1000))
|
|
647
|
+
counter++
|
|
648
|
+
ctx.send({ message: '实时更新', count: counter })
|
|
649
|
+
if (counter >= 10) {
|
|
650
|
+
break
|
|
651
|
+
}
|
|
660
652
|
}
|
|
653
|
+
ctx.close()
|
|
661
654
|
}
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
655
|
+
})
|
|
656
|
+
}
|
|
657
|
+
})
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
`handle` 函数接收一个 `SseContext` 对象,提供以下能力:
|
|
661
|
+
|
|
662
|
+
| 方法/属性 | 说明 |
|
|
663
|
+
| :---------------------------------------- | :----------------------------------------------------------- |
|
|
664
|
+
| `ctx.send(data, event?, id?)` | 发送 SSE 事件,`data` 会被 JSON 序列化。`event` 指定事件名(前端用 `addEventListener` 监听),`id` 设置事件 ID(用于断线重连的 `Last-Event-ID`) |
|
|
665
|
+
| `ctx.close()` | 显式结束 SSE 连接。`handle` 返回或抛异常时连接也会自动关闭 |
|
|
666
|
+
| `ctx.request` | 原始 `IncomingMessage`,可读取请求头等信息 |
|
|
667
|
+
| `ctx.response` | 原始 `ServerResponse`,高级场景下使用 |
|
|
668
|
+
|
|
669
|
+
#### 命名事件
|
|
670
|
+
|
|
671
|
+
通过 `event` 参数发送命名事件,前端可按事件类型分别处理:
|
|
672
|
+
|
|
673
|
+
```ts
|
|
674
|
+
createSseHandler({
|
|
675
|
+
async handle(ctx) {
|
|
676
|
+
ctx.send({ title: '新消息' }, 'notification')
|
|
677
|
+
ctx.send({ progress: 50 }, 'progress')
|
|
665
678
|
}
|
|
666
679
|
})
|
|
667
680
|
```
|
|
681
|
+
|
|
682
|
+
前端:
|
|
683
|
+
|
|
684
|
+
```ts
|
|
685
|
+
const es = new EventSource('/sse')
|
|
686
|
+
es.addEventListener('notification', e => {
|
|
687
|
+
const data = JSON.parse(e.data)
|
|
688
|
+
console.log('收到通知:', data.title)
|
|
689
|
+
})
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
#### 断线重连
|
|
693
|
+
|
|
694
|
+
通过 `id` 参数设置事件 ID,前端断线重连时浏览器会自动发送 `Last-Event-ID` 请求头:
|
|
695
|
+
|
|
696
|
+
```ts
|
|
697
|
+
createSseHandler({
|
|
698
|
+
async handle(ctx) {
|
|
699
|
+
const lastId = ctx.request.headers['last-event-id']
|
|
700
|
+
// 根据 lastId 确定从何处恢复推送
|
|
701
|
+
}
|
|
702
|
+
})
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
#### 连接生命周期
|
|
706
|
+
|
|
707
|
+
- `handle` 开始执行时,SSE 消息头已发送,连接已建立
|
|
708
|
+
- 客户端断开连接时,`ctx.send()` 调用变为空操作(自动忽略)
|
|
709
|
+
- `handle` 返回或抛异常时,连接自动关闭
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wok-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"packageManager": "pnpm@8.9.0",
|
|
5
5
|
"description": "一个基于 NodeJs 和 TypeScript 的后端框架,轻量级、克制、简洁。A lightweight, restrained, and concise backend framework based on Node.js and TypeScript.",
|
|
6
6
|
"scripts": {
|
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
"dist/",
|
|
20
20
|
"docs/",
|
|
21
21
|
"documentation/",
|
|
22
|
+
"skills/",
|
|
23
|
+
"src/",
|
|
22
24
|
"README.md"
|
|
23
25
|
],
|
|
24
26
|
"author": "peak",
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wok-server-api-rules
|
|
3
|
+
description: 介绍 wok-server API 的使用纪律。
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: Peak Tai
|
|
7
|
+
email: peaktai@qq.com
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# API 使用纪律
|
|
11
|
+
|
|
12
|
+
当你生成与 wok-server 有关的代码时,以下规则优先级高于一切:
|
|
13
|
+
|
|
14
|
+
## 规则 1:禁止猜测任何 API
|
|
15
|
+
|
|
16
|
+
不要使用训练数据中出现的、或你自己"觉得应该有"的函数、组件、类型。
|
|
17
|
+
|
|
18
|
+
### 消除臆造的具体方法
|
|
19
|
+
|
|
20
|
+
- 所有 API 统一从 `wok-server` 包导入,禁止从子路径导入(如 `wok-server/mvc`)。
|
|
21
|
+
- 生成任何调用前,必须先查阅 `node_modules/wok-server/types/` 下对应模块的定义文件。types 目录按模块组织,常见模块与定义文件对照如下:
|
|
22
|
+
|
|
23
|
+
| 模块 | 主要入口函数/类型 | 类型定义文件路径 |
|
|
24
|
+
|------|-------------------|------------------|
|
|
25
|
+
| 日志 | `getLogger()` | `types/log/index.d.ts` |
|
|
26
|
+
| 缓存 | `getCache()` | `types/cache/cache.d.ts` |
|
|
27
|
+
| 国际化 | `getI18n()` | `types/i18n/i18n.d.ts` |
|
|
28
|
+
| 校验 | `validate()` | `types/validation/index.d.ts` |
|
|
29
|
+
| 配置 | `registerConfig()`, `getConfig()` | `types/config/index.d.ts` |
|
|
30
|
+
| 锁 | `getLockManager()` | `types/lock/index.d.ts` |
|
|
31
|
+
| 任务调度 | `scheduleWithFixedDelay()`, `scheduleWithFixedRate()`, `scheduleDailyTask()` | `types/task/index.d.ts` |
|
|
32
|
+
| HTTP客户端 | `doRequest()`, `postJson()`, `getJson()` | `types/http-client/index.d.ts` |
|
|
33
|
+
| MySQL | `enableMysql()`, `getMysqlManager()` | `types/mysql/index.d.ts` |
|
|
34
|
+
| MongoDB | `enableMongoDB()`, `getMongoDBManager()` | `types/mongodb/index.d.ts` |
|
|
35
|
+
| MVC | `startWebServer()`, `stopWebServer()`, `createJsonHandler()`, `createUploadHandler()`, `createSseHandler()`, `restful()`, `removeServerStaticCache()` | `types/mvc/index.d.ts` |
|
|
36
|
+
|
|
37
|
+
- 代码必须严格匹配签名——函数参数名称、顺序、类型完全一致,返回值类型正确处理(如 `Promise` 需 `await`)。
|
|
38
|
+
|
|
39
|
+
### 示例
|
|
40
|
+
|
|
41
|
+
❌ 错误:`getCache().add('key', data)` —— cache 没有 `add` 方法,属于臆造。
|
|
42
|
+
|
|
43
|
+
✅ 正确:查阅 `node_modules/wok-server/types/cache/cache.d.ts` 后,使用 `getCache().put('key', data)` 并严格按签名调用。
|
|
44
|
+
|
|
45
|
+
❌ 错误:`exchange.send(data)` 或 `exchange.json(data)` —— `ServerExchange` 没有这些方法。
|
|
46
|
+
|
|
47
|
+
✅ 正确:使用 `exchange.respondJson(data)` 或 `exchange.respondText(text)` 等,详见下方 ServerExchange 速查表。
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 规则 2:每个拦截器和每个路由 handler 都应该有单独的文件
|
|
52
|
+
|
|
53
|
+
禁止多个拦截器写在一个文件里,禁止多个接口的处理逻辑在一个文件里。
|
|
54
|
+
即使内容再少,也不允许写在一起。
|
|
55
|
+
|
|
56
|
+
路由的配置(`routers` 对象)必须在入口文件(如 `main.ts`)或独立的 router 目录中**集中管理**,不允许在业务目录中分散配置路由映射。集中配置是为了方便查找所有路由。
|
|
57
|
+
|
|
58
|
+
### 拦截器标准签名
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
import { ServerExchange } from 'wok-server'
|
|
62
|
+
|
|
63
|
+
// 每个拦截器单独一个文件,export 一个函数
|
|
64
|
+
export async function authInterceptor(
|
|
65
|
+
exchange: ServerExchange,
|
|
66
|
+
next: () => Promise<void>
|
|
67
|
+
): Promise<void> {
|
|
68
|
+
// 前置处理...
|
|
69
|
+
await next()
|
|
70
|
+
// 后置处理...
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
类型定义为:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
interface Interceptor {
|
|
78
|
+
(exchange: ServerExchange, next: () => Promise<void>): Promise<void>
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 规则 3:每个路由 handler 文件的参数和响应定义都应该保持在内部
|
|
85
|
+
|
|
86
|
+
每个路由的处理逻辑是独立的,不向外导出除 handler 以外的函数、组件、类型,不和别的路由共享数据。
|
|
87
|
+
|
|
88
|
+
### 可用的 Handler 工厂函数
|
|
89
|
+
|
|
90
|
+
wok-server 提供了以下 4 种 handler 工厂函数,禁止使用除此之外任何臆造的工厂函数:
|
|
91
|
+
|
|
92
|
+
| 工厂函数 | 用途 | 请求格式 | 响应格式 |
|
|
93
|
+
|----------|------|----------|----------|
|
|
94
|
+
| `createJsonHandler` | JSON 请求/响应 | POST,JSON body | JSON |
|
|
95
|
+
| `createUploadHandler` | 二进制文件上传 | POST,binary body | JSON |
|
|
96
|
+
| `createSseHandler` | Server-Sent Events 推送 | GET | SSE 事件流 |
|
|
97
|
+
| `restful` | 按 HTTP 方法分发 | 任意 | 由内层 handler 决定 |
|
|
98
|
+
|
|
99
|
+
#### createJsonHandler 示例
|
|
100
|
+
|
|
101
|
+
```ts
|
|
102
|
+
// create-user.ts
|
|
103
|
+
import { createJsonHandler, notBlank, length, min, max, notNull } from 'wok-server'
|
|
104
|
+
|
|
105
|
+
interface Form {
|
|
106
|
+
name: string
|
|
107
|
+
age: number
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
interface Resp {
|
|
111
|
+
id: string
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export const createUserHandler = createJsonHandler<Form, Resp>({
|
|
115
|
+
validation: {
|
|
116
|
+
name: [notBlank(), length({ min: 2, max: 16 })],
|
|
117
|
+
age: [notNull(), min(1), max(150)]
|
|
118
|
+
},
|
|
119
|
+
// 可选:缓存支持
|
|
120
|
+
async cache(body) {
|
|
121
|
+
return { key: `user-${body.name}`, expiresInSeconds: 60 }
|
|
122
|
+
},
|
|
123
|
+
async handle(body) {
|
|
124
|
+
const newUser = await createUser(body)
|
|
125
|
+
return { id: newUser.id }
|
|
126
|
+
}
|
|
127
|
+
})
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
命名约定:请求数据类型推荐命名为 `Form`,响应数据类型推荐命名为 `Resp`。
|
|
131
|
+
由于这两个数据类型是保持在文件内部的,所以不同的 handler 文件可以使用这两个名称,不会冲突,
|
|
132
|
+
这也是推荐的方式。如果每个具体的业务,根据场景命名也是可以的,如 CreateUserForm、CreateUserResp,
|
|
133
|
+
这样更严谨,查询可能更方便,但是开发效率会稍低。
|
|
134
|
+
|
|
135
|
+
#### createUploadHandler 示例
|
|
136
|
+
|
|
137
|
+
上传请求正文是文件二进制内容,额外参数通过 QueryString 传递。请求体类型是 `Buffer`,不需要定义 Form。
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
// upload-avatar.ts
|
|
141
|
+
import { createUploadHandler, validate, notBlank } from 'wok-server'
|
|
142
|
+
|
|
143
|
+
interface Resp {
|
|
144
|
+
url: string
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export const uploadAvatarHandler = createUploadHandler<Resp>({
|
|
148
|
+
async handle(body, exchange) {
|
|
149
|
+
const userId = exchange.query.getStr('userId')
|
|
150
|
+
validate({ userId }, { userId: [notBlank()] })
|
|
151
|
+
// body 就是文件的 Buffer,可直接使用
|
|
152
|
+
const key = `avatars/${userId}`
|
|
153
|
+
await oss.putObject(key, body)
|
|
154
|
+
return { url: oss.getUrl(key) }
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### createSseHandler 示例
|
|
160
|
+
|
|
161
|
+
SSE handler 没有请求/响应数据类型,只有 `SseContext`。
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
// sse-notify.ts
|
|
165
|
+
import { createSseHandler } from 'wok-server'
|
|
166
|
+
|
|
167
|
+
export const notifyHandler = createSseHandler({
|
|
168
|
+
async handle(ctx) {
|
|
169
|
+
// ctx.send(data, event?, id?) 发送事件
|
|
170
|
+
// ctx.close() 关闭连接
|
|
171
|
+
ctx.send({ message: '连接成功' }, 'connected')
|
|
172
|
+
// ... 业务逻辑
|
|
173
|
+
ctx.close()
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
#### restful 示例
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
// user-router.ts
|
|
182
|
+
import { restful } from 'wok-server'
|
|
183
|
+
import { createUserHandler } from './create-user'
|
|
184
|
+
import { getUserHandler } from './get-user'
|
|
185
|
+
|
|
186
|
+
export const userRouter = restful({
|
|
187
|
+
get: getUserHandler,
|
|
188
|
+
post: createUserHandler
|
|
189
|
+
})
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## 规则 4:业务错误应抛出异常,由全局异常拦截器统一处理
|
|
195
|
+
|
|
196
|
+
推荐的处理模式:
|
|
197
|
+
1. 定义 `BusinessException` 自定义业务异常类
|
|
198
|
+
2. 创建 `globalErrorInterceptor` 放在拦截器链**第一位**
|
|
199
|
+
3. Handler 中遇到业务错误,抛出异常来中止处理流程
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
// exception.ts —— 全局异常定义文件
|
|
203
|
+
import { ServerExchange, ValidationException } from 'wok-server'
|
|
204
|
+
|
|
205
|
+
export class BusinessException {
|
|
206
|
+
constructor(
|
|
207
|
+
readonly message: string,
|
|
208
|
+
readonly status?: number
|
|
209
|
+
) {}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export async function globalErrorInterceptor(
|
|
213
|
+
exchange: ServerExchange,
|
|
214
|
+
next: () => Promise<void>
|
|
215
|
+
): Promise<void> {
|
|
216
|
+
try {
|
|
217
|
+
await next()
|
|
218
|
+
} catch (e) {
|
|
219
|
+
if (e instanceof BusinessException) {
|
|
220
|
+
exchange.respondErrMsg(e.message, e.status ?? 400)
|
|
221
|
+
return
|
|
222
|
+
}
|
|
223
|
+
if (e instanceof ValidationException) {
|
|
224
|
+
exchange.respondErrMsg(`${e.propertyPath}:${e.errMsg}`, 400)
|
|
225
|
+
return
|
|
226
|
+
}
|
|
227
|
+
throw e
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
// main.ts 入口文件,将错误拦截器放在第一位
|
|
234
|
+
import { startWebServer } from 'wok-server'
|
|
235
|
+
import { globalErrorInterceptor } from './exception'
|
|
236
|
+
|
|
237
|
+
await startWebServer({
|
|
238
|
+
interceptors: [globalErrorInterceptor /* , 其他拦截器 */],
|
|
239
|
+
routers: { /* ... */ }
|
|
240
|
+
})
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## 附录 A:ServerExchange 速查表
|
|
246
|
+
|
|
247
|
+
所有路由 handler 和拦截器都通过 `ServerExchange` 与请求/响应交互。以下是其完整方法列表,禁止使用表中未列出的方法。
|
|
248
|
+
|
|
249
|
+
### 读取请求
|
|
250
|
+
|
|
251
|
+
| 方法/属性 | 返回类型 | 说明 |
|
|
252
|
+
|-----------|----------|------|
|
|
253
|
+
| `exchange.request` | `IncomingMessage` | Node.js 原生请求对象 |
|
|
254
|
+
| `exchange.response` | `ServerResponse` | Node.js 原生响应对象 |
|
|
255
|
+
| `await exchange.bodyJson<T>()` | `Promise<T>` | 读取 JSON 请求体(空体返回 `{}`) |
|
|
256
|
+
| `await exchange.bodyBuffer()` | `Promise<Buffer>` | 读取二进制请求体 |
|
|
257
|
+
| `await exchange.bodyText()` | `Promise<string>` | 读取文本请求体 |
|
|
258
|
+
| `exchange.parseQueryString()` | `QueryString` | 解析 URL 查询字符串 |
|
|
259
|
+
|
|
260
|
+
> **注意**:如果使用了第三方库读取 request 内容,则不能再调用 `bodyXxx` 系列方法,反之亦然。但 `bodyXxx` 系列方法之间可以重复调用。
|
|
261
|
+
|
|
262
|
+
### 响应
|
|
263
|
+
|
|
264
|
+
| 方法 | 说明 |
|
|
265
|
+
|------|------|
|
|
266
|
+
| `exchange.respondJson(json, status?)` | 响应 JSON,默认 status 200 |
|
|
267
|
+
| `exchange.respondErrMsg(message, status?)` | 响应统一错误格式 `{ message: "..." }`,默认 status 400 |
|
|
268
|
+
| `exchange.respondText(text, status?)` | 响应纯文本,默认 status 200 |
|
|
269
|
+
| `exchange.respondFile(filePath, download?)` | 响应文件,`download=true` 触发下载 |
|
|
270
|
+
| `exchange.respondHtml(html, status?)` | 响应 HTML |
|
|
271
|
+
| `exchange.respond({ statusCode, body?, headers? })` | 底层通用响应 |
|
|
272
|
+
|
|
273
|
+
---
|
|
274
|
+
|
|
275
|
+
## 附录 B:startWebServer 完整配置
|
|
276
|
+
|
|
277
|
+
```ts
|
|
278
|
+
import { startWebServer } from 'wok-server'
|
|
279
|
+
|
|
280
|
+
await startWebServer({
|
|
281
|
+
// 必填:路由配置,键为路径,值为 RouterHandler
|
|
282
|
+
// 路径仅支持明确地址,不支持动态参数(如 /users/:id)和通配符
|
|
283
|
+
// '*' 为特殊路径,用于兜底处理 404
|
|
284
|
+
routers: {
|
|
285
|
+
'/user/create': createUserHandler,
|
|
286
|
+
'/user/delete': deleteUserHandler,
|
|
287
|
+
'/sse/notify': notifyHandler,
|
|
288
|
+
'*': notFoundHandler
|
|
289
|
+
},
|
|
290
|
+
// 可选:拦截器链,按数组顺序执行
|
|
291
|
+
interceptors: [globalErrorInterceptor, authInterceptor],
|
|
292
|
+
// 可选:前置处理,可整合 socket.io 等原生 http 组件
|
|
293
|
+
preHandler: async (server) => {
|
|
294
|
+
// const io = new Server(server)
|
|
295
|
+
},
|
|
296
|
+
// 可选:静态文件服务配置
|
|
297
|
+
static: {
|
|
298
|
+
'/': { dir: 'fe', cacheAge: 600 }
|
|
299
|
+
}
|
|
300
|
+
})
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## 附录 C:内置校验器列表
|
|
306
|
+
|
|
307
|
+
以下校验器从 `wok-server` 导入,禁止臆造不存在的校验器:
|
|
308
|
+
|
|
309
|
+
| 函数 | 作用 |
|
|
310
|
+
|------|------|
|
|
311
|
+
| `notNull()` | 非空校验(不能是 null/undefined) |
|
|
312
|
+
| `notBlank()` | 字符串非空校验(不能是 null/undefined/空白字符串) |
|
|
313
|
+
| `min(n)` | 数字最小值 |
|
|
314
|
+
| `max(n)` | 数字最大值 |
|
|
315
|
+
| `length({ min?, max? })` | 字符串/数组长度范围 |
|
|
316
|
+
| `maxLength(n)` | 字符串/数组最大长度 |
|
|
317
|
+
| `minLength(n)` | 字符串/数组最小长度 |
|
|
318
|
+
| `regexp(re)` | 正则校验 |
|
|
319
|
+
| `enumerate(list)` | 枚举校验,值必须在指定列表中 |
|
|
320
|
+
| `array(validators)` | 数组元素校验 |
|
|
321
|
+
| `plainObject(opts)` | 嵌套对象校验 |
|
|
322
|
+
|
|
323
|
+
所有内置校验器已支持国际化,自动根据请求头 `accept-language` 切换提示语言。
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## 附录 D:目录结构参考
|
|
328
|
+
|
|
329
|
+
```
|
|
330
|
+
src/
|
|
331
|
+
├── exception.ts # 全局异常定义 + 错误拦截器
|
|
332
|
+
├── main.ts # 入口:启动服务、集中配置路由
|
|
333
|
+
├── auth/ # 授权模块
|
|
334
|
+
│ ├── auth-interceptor.ts
|
|
335
|
+
│ ├── create-auth.ts
|
|
336
|
+
│ └── index.ts
|
|
337
|
+
├── user/ # 用户模块
|
|
338
|
+
│ ├── user.ts # 实体配置(mysql/mongo 等)
|
|
339
|
+
│ ├── create-user.ts # POST /user/create
|
|
340
|
+
│ ├── update-user.ts # POST /user/update
|
|
341
|
+
│ └── index.ts
|
|
342
|
+
└── tag/ # 标签模块
|
|
343
|
+
├── tag.ts
|
|
344
|
+
├── create-tag.ts
|
|
345
|
+
└── index.ts
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
- 目录按业务功能划分,而非按技术层(service/controller)划分。
|
|
349
|
+
- 路由配置集中在 `main.ts` 或独立 `router/` 目录中。
|
|
350
|
+
- 每个 handler 和 interceptor 都是单独文件。
|