wok-server 0.4.13 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 -29
- package/dist/log/date.js +21 -21
- package/dist/log/file.js +198 -72
- package/dist/log/index.js +135 -105
- package/dist/log/level.js +33 -33
- package/dist/log/log.js +56 -0
- package/dist/log/store.js +19 -16
- 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 -231
- 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 -130
- 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 -100
- 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/engineering.md +1 -1
- package/documentation/zh-cn/log.md +81 -8
- package/documentation/zh-cn/mvc.md +66 -24
- package/documentation/zh-cn/mysql.md +24 -23
- package/documentation/zh-cn/validate.md +2 -2
- 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 -27
- package/types/log/date.d.ts +2 -2
- package/types/log/file.d.ts +13 -5
- package/types/log/index.d.ts +53 -34
- package/types/log/level.d.ts +14 -14
- package/types/log/log.d.ts +40 -0
- package/types/log/store.d.ts +19 -12
- 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 -159
- 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 -70
- 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 -35
- 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,235 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wok-server-mongodb
|
|
3
|
+
description: wok-server MongoDB 组件使用指南,基于官方驱动封装,提供实体映射、CRUD、事务和版本管理。
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: Peak Tai
|
|
7
|
+
email: peaktai@qq.com
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# wok-server MongoDB 组件
|
|
11
|
+
|
|
12
|
+
## 概述
|
|
13
|
+
|
|
14
|
+
MongoDB 组件基于 [mongodb 官方驱动](https://www.npmjs.com/package/mongodb) 封装,提供实体映射和增删改查功能。支持多实例、事务、慢查询告警、版本管理。
|
|
15
|
+
|
|
16
|
+
## 源码与类型定义
|
|
17
|
+
|
|
18
|
+
安装 `wok-server` 后,可通过以下路径查看源码与类型定义:
|
|
19
|
+
|
|
20
|
+
- 源码目录:`node_modules/wok-server/src/mongodb/`
|
|
21
|
+
- 类型定义:`node_modules/wok-server/types/` (引用 mongodb 组件的 `.d.ts` 文件)
|
|
22
|
+
|
|
23
|
+
核心源码文件:
|
|
24
|
+
|
|
25
|
+
| 文件 | 说明 |
|
|
26
|
+
| :----------------- | :--------------------------------- |
|
|
27
|
+
| `index.ts` | 模块入口,`enableMongoDB`/`getMongoDBManager` |
|
|
28
|
+
| `config.ts` | 配置定义与默认值 |
|
|
29
|
+
| `collection.ts` | `MongoCollection<T>` 集合映射接口 |
|
|
30
|
+
| `doc.ts` | `MongoDocId`、`MongoDocWithId<T>` |
|
|
31
|
+
| `manager/base.ts` | `BaseMongoManager` 基类 |
|
|
32
|
+
| `manager/index.ts` | `MongoDBManager`,含 `tx` 方法 |
|
|
33
|
+
| `manager/tx.ts` | `MongoTxSession` 事务会话 |
|
|
34
|
+
| `manager/tx-strict.ts` | `MongoStrictTxSession` 严格事务 |
|
|
35
|
+
| `migration.ts` | 版本迁移 |
|
|
36
|
+
| `exception.ts` | `MongoDBException` 异常类 |
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## 环境变量
|
|
41
|
+
|
|
42
|
+
| 环境变量 | 说明 | 默认值 |
|
|
43
|
+
| :-------------------------- | :------------------- | :----- |
|
|
44
|
+
| `MONGO_URI` | 连接地址 | - |
|
|
45
|
+
| `MONGO_MAX_POOL_SIZE` | 连接池最大连接数 | 10 |
|
|
46
|
+
| `MONGO_MIN_POOL_SIZE` | 连接池最小连接数 | 1 |
|
|
47
|
+
| `MONGO_MAX_CONNECTING` | 最大并发连接数 | 10 |
|
|
48
|
+
| `MONGO_MAX_IDLE_TIME_MS` | 最大闲置时间(ms) | 60000 |
|
|
49
|
+
| `MONGO_WAIT_QUEUE_TIMEOUT_MS` | 等待连接超时(ms) | 60000 |
|
|
50
|
+
| `MONGO_SLOW_QUERY_WARN` | 慢查询警告 | true |
|
|
51
|
+
| `MONGO_SLOW_QUERY_MS` | 慢查询阈值(ms) | 200 |
|
|
52
|
+
| `MONGO_TRANSACTION_TIMEOUT` | 事务超时(ms) | 5000 |
|
|
53
|
+
| `MONGO_TRANSACTION_STRICT` | 事务严格模式 | true |
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 初始化
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { enableMongoDB, getMongoDBManager } from 'wok-server'
|
|
61
|
+
|
|
62
|
+
await enableMongoDB()
|
|
63
|
+
const manager = getMongoDBManager()
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 多实例
|
|
67
|
+
|
|
68
|
+
指定名称即可,环境变量前缀自动变更为该名称大写:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
await enableMongoDB() // 默认,前缀 MONGO_
|
|
72
|
+
await enableMongoDB({ name: 'md2' }) // 自定义,前缀 MD2_
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## 实体映射
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
import { MongoCollection } from 'wok-server'
|
|
81
|
+
|
|
82
|
+
export interface User {
|
|
83
|
+
nickname: string
|
|
84
|
+
skills: string[]
|
|
85
|
+
createAt?: Date // 可选,由组件自动管理
|
|
86
|
+
updateAt?: Date
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const collUser: MongoCollection<User> = {
|
|
90
|
+
collectionName: 'user',
|
|
91
|
+
createdDate: { type: 'date', field: 'createAt' },
|
|
92
|
+
updatedDate: { type: 'date', field: 'updateAt' }
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
- 主键固定为 `_id`(`string | ObjectId`),不可自定义映射
|
|
97
|
+
- 实体接口不要声明 `_id` 字段,插入时可传可省略(省略时数据库自动生成 ObjectId)
|
|
98
|
+
- `createdDate`/`updatedDate` 配置后由组件自动填充
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## CRUD 操作
|
|
103
|
+
|
|
104
|
+
所有操作以 `MongoCollection<T>` 为第一个参数。
|
|
105
|
+
|
|
106
|
+
### 插入
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
const result = await manager.insert(collUser, { _id: '007', nickname: 'Spark', skills: [] })
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 查询
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
const user = await manager.findById(collUser, '007') // 按 _id
|
|
116
|
+
const list = await manager.findByIdIn(collUser, ['007', '008']) // 批量 _id
|
|
117
|
+
const jack = await manager.findFirst(collUser, { nickname: 'jack' }) // 第一条
|
|
118
|
+
const all = await manager.findAll(collUser) // ⚠️ 全量,危险
|
|
119
|
+
|
|
120
|
+
// 条件查询
|
|
121
|
+
const results = await manager.find(collUser,
|
|
122
|
+
{ skills: { $exists: true } },
|
|
123
|
+
{ offset: 0, limit: 2 }
|
|
124
|
+
)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
查询条件使用 MongoDB 原生 Filter 语法(`{ nick: 'jack' }`, `{ $gt: ... }` 等)。
|
|
128
|
+
|
|
129
|
+
### 分页
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
const page = await manager.paginate(collUser,
|
|
133
|
+
{ skills: { $exists: true } },
|
|
134
|
+
{ pn: 2, pz: 20, orderBy: ['_id', 'asc'] }
|
|
135
|
+
)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 更新(四种方法)
|
|
139
|
+
|
|
140
|
+
| 方法 | 说明 | 需要完整文档 |
|
|
141
|
+
| :-------------- | :--------------------------------- | :----------- |
|
|
142
|
+
| `update` | 完整文档更新,失败抛异常 | 是 |
|
|
143
|
+
| `partialUpdate` | 局部更新,只需 id + 更新字段 | 否 |
|
|
144
|
+
| `updateMany` | 批量更新所有符合条件的 | 否 |
|
|
145
|
+
| `updateOne` | 只更新一条相等条件的 | 否 |
|
|
146
|
+
|
|
147
|
+
```ts
|
|
148
|
+
// 完整更新
|
|
149
|
+
const user = await manager.findById(collUser, '007')
|
|
150
|
+
user.nickname = 'ryan'
|
|
151
|
+
await manager.update(collUser, user)
|
|
152
|
+
|
|
153
|
+
// 局部更新(MongoDB 更新操作符语法)
|
|
154
|
+
await manager.partialUpdate(collUser, '001', { $set: { nickname: 'lily' } })
|
|
155
|
+
|
|
156
|
+
// 批量更新
|
|
157
|
+
await manager.updateMany(collUser, { credit: { $lte: 10 } }, { $inc: { credit: 1 } })
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### 其他
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
await manager.existsById(collUser, 'xyz')
|
|
164
|
+
await manager.existsBy(collUser, { nickname: 'smith' })
|
|
165
|
+
await manager.deleteById(collUser, '007')
|
|
166
|
+
await manager.deleteMany(collUser, { nickname: 'smith' }) // ⚠️ 危险
|
|
167
|
+
const count = await manager.count(collUser, { nickname: 'Steve' })
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## 事务
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
await manager.tx(async session => {
|
|
176
|
+
await session.partialUpdate(collOrder, orderId, { $set: { status: 'finished' } })
|
|
177
|
+
await session.partialUpdate(collAccount, accountId, { $inc: { balance: -amount } })
|
|
178
|
+
}, { timeout: 1000 })
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**⚠️ 事务中的所有操作必须通过 `session` 完成**,直接使用 `manager` 不会在事务中生效。
|
|
182
|
+
|
|
183
|
+
选项可覆盖全局超时时间,支持设置 `readConcern`、`writeConcern`、`readPreference`。
|
|
184
|
+
|
|
185
|
+
### 严格模式
|
|
186
|
+
|
|
187
|
+
`MONGO_TRANSACTION_STRICT=true`(默认),事务中禁止:
|
|
188
|
+
1. 批量 `insertMany`
|
|
189
|
+
2. 批量 `updateMany` / `deleteMany`
|
|
190
|
+
3. 大批量查询 `find` / `count` / `paginate`
|
|
191
|
+
4. `findByIdIn` 参数超过 100
|
|
192
|
+
5. 任何操作累计超过 10 次
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 版本管理
|
|
197
|
+
|
|
198
|
+
在 `enableMongoDB` 时传入 `migration.versionList`:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
await enableMongoDB({
|
|
202
|
+
migration: {
|
|
203
|
+
versionList: [
|
|
204
|
+
async db => { // 版本 0
|
|
205
|
+
await db.createCollection('user')
|
|
206
|
+
await db.collection('user').createIndex({ nickname: 1 }, { unique: true })
|
|
207
|
+
},
|
|
208
|
+
async db => { // 版本 1
|
|
209
|
+
await db.collection('user').insertOne({ nickname: 'jack', ... })
|
|
210
|
+
}
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
- 版本号 = 数组下标,从 0 开始
|
|
217
|
+
- **已有元素不可修改**,只能在末尾追加
|
|
218
|
+
- 启动时自动检测当前版本(存储在 `db_version` 集合),执行未应用的版本
|
|
219
|
+
- 迁移不能回滚,出错需手动在数据库中修复后重启
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## 内部实现要点
|
|
224
|
+
|
|
225
|
+
### 初始化
|
|
226
|
+
|
|
227
|
+
`registerConfig` 注册配置 → 创建 `MongoClient` → 可选迁移 → 存入 `managerMap` → 进程退出前自动 `close()`。
|
|
228
|
+
|
|
229
|
+
### 慢查询计时
|
|
230
|
+
|
|
231
|
+
所有操作通过 `timingQuery` 包装,记录耗时,超出 `MONGO_SLOW_QUERY_MS` 时输出 WARN 日志(含操作类型、集合名、ID 等)。
|
|
232
|
+
|
|
233
|
+
### 事务实现
|
|
234
|
+
|
|
235
|
+
创建 `ClientSession` → `startTransaction` → `Promise.race` 超时竞速 → 根据 `transactionStrict` 创建普通/严格 session → `exec(session)` → `commit` / `abort` / `finally endSession`。
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wok-server-mvc
|
|
3
|
+
description: wok-server MVC 组件使用指南,基于 Node.js http 模块,提供路由、拦截器、JSON/上传处理器等。
|
|
4
|
+
license: MIT
|
|
5
|
+
metadata:
|
|
6
|
+
author: Peak Tai
|
|
7
|
+
email: peaktai@qq.com
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# wok-server MVC 组件
|
|
11
|
+
|
|
12
|
+
## 概述
|
|
13
|
+
|
|
14
|
+
MVC 组件基于 Node.js 内置 `http` 模块封装,提供 HTTP 服务构建能力。核心概念:路由(Router)、拦截器(Interceptor)、处理器(Handler)。
|
|
15
|
+
|
|
16
|
+
## 源码与类型定义
|
|
17
|
+
|
|
18
|
+
安装 `wok-server` 后,可通过以下路径查看源码与类型定义:
|
|
19
|
+
|
|
20
|
+
- 源码目录:`node_modules/wok-server/src/mvc/`
|
|
21
|
+
- 类型定义:`node_modules/wok-server/types/` (引用 mvc 组件的 `.d.ts` 文件)
|
|
22
|
+
|
|
23
|
+
核心源码文件:
|
|
24
|
+
|
|
25
|
+
| 文件 | 说明 |
|
|
26
|
+
| :----------------- | :--------------------------------- |
|
|
27
|
+
| `index.ts` | 模块入口,`startWebServer`/`stopWebServer` |
|
|
28
|
+
| `server.ts` | `WokServer` 类,HTTP/HTTPS 服务实现 |
|
|
29
|
+
| `router.ts` | `RouterHandler` 类型与 `Routers` 定义 |
|
|
30
|
+
| `exchange.ts` | `ServerExchange` 数据交换对象 |
|
|
31
|
+
| `config.ts` | 服务配置(端口、超时、CORS、TLS 等)|
|
|
32
|
+
| `interceptor.ts` | `Interceptor` 拦截器接口 |
|
|
33
|
+
| `handler/json.ts` | `createJsonHandler` JSON 处理器 |
|
|
34
|
+
| `handler/upload.ts`| `createUploadHandler` 二进制上传 |
|
|
35
|
+
| `handler/sse.ts` | `createSseHandler` SSE 服务端推送 |
|
|
36
|
+
| `handler/restful.ts`| `restful` 方法分派函数 |
|
|
37
|
+
| `handler/index.ts` | 处理器模块聚合导出 |
|
|
38
|
+
| `query.ts` | `QueryString` 查询字符串解析 |
|
|
39
|
+
| `static/` | 静态文件服务 |
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 环境变量
|
|
44
|
+
|
|
45
|
+
| 环境变量 | 说明 | 默认值 |
|
|
46
|
+
| :------------------------- | :------------------ | :----- |
|
|
47
|
+
| `SERVER_PORT` | 端口号 | 8080 |
|
|
48
|
+
| `SERVER_TIMEOUT` | 超时时间(ms) | 30000 |
|
|
49
|
+
| `SERVER_ACCESS_LOG` | 是否启用访问日志 | false |
|
|
50
|
+
| `SERVER_CORS_ALLOW_ORIGIN` | CORS 允许的源域名 | * |
|
|
51
|
+
| `SERVER_CORS_ALLOW_HEADERS`| CORS 允许的消息头 | * |
|
|
52
|
+
| `SERVER_CORS_ALLOW_METHODS`| CORS 允许的请求方法 | * |
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 启动与停止
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
import { startWebServer, stopWebServer } from 'wok-server'
|
|
60
|
+
|
|
61
|
+
await startWebServer({
|
|
62
|
+
routers: { '/': async exchange => exchange.respondText('Hello') }
|
|
63
|
+
})
|
|
64
|
+
|
|
65
|
+
await stopWebServer()
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
服务全局单例,重复启动抛异常。进程退出前自动停止。
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 路由
|
|
73
|
+
|
|
74
|
+
路由是 `Record<string, RouterHandler>`,key 为路径,value 为异步处理函数。**仅支持明确地址,不支持动态路径(如 `/users/:id`)**。
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { RouterHandler } from 'wok-server'
|
|
78
|
+
|
|
79
|
+
const myHandler: RouterHandler = async exchange => {
|
|
80
|
+
const body = await exchange.bodyJson()
|
|
81
|
+
exchange.respondJson({ ok: true })
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
特殊路径 `'*'` 匹配所有未命中请求,用于自定义 404。
|
|
86
|
+
|
|
87
|
+
### ServerExchange
|
|
88
|
+
|
|
89
|
+
路由处理函数的参数,提供请求读取与响应方法:
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
// 读取请求
|
|
93
|
+
exchange.request.method // 请求方法
|
|
94
|
+
exchange.request.url // 请求 URL
|
|
95
|
+
exchange.request.headers // 消息头
|
|
96
|
+
exchange.parseQueryString() // 解析 QueryString → QueryString 对象
|
|
97
|
+
|
|
98
|
+
// 读取正文
|
|
99
|
+
const body = await exchange.bodyBuffer() // Buffer
|
|
100
|
+
const text = await exchange.bodyText() // string
|
|
101
|
+
const json = await exchange.bodyJson<T>() // T
|
|
102
|
+
|
|
103
|
+
// 响应
|
|
104
|
+
exchange.respondText('text', 200)
|
|
105
|
+
exchange.respondJson({ ok: true }, 200)
|
|
106
|
+
exchange.respondErrMsg('错误信息', 400) // JSON 格式: { message }
|
|
107
|
+
exchange.respondFile('/abs/path/to/file')
|
|
108
|
+
exchange.respondHtml('<h1>Hi</h1>', 200)
|
|
109
|
+
exchange.respond({ statusCode: 200, body: 'raw', headers: { ... } })
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## 拦截器
|
|
115
|
+
|
|
116
|
+
类型 `Interceptor: (exchange, next) => Promise<void>`。按数组中顺序执行,调用 `next()` 继续下一拦截器或路由。
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
const authInterceptor: Interceptor = async (exchange, next) => {
|
|
120
|
+
const token = exchange.request.headers.authorization
|
|
121
|
+
if (!token) {
|
|
122
|
+
exchange.respondErrMsg('Unauthorized', 401)
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
await next()
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
典型用途:授权校验、异常统一处理、CORS 预检等。服务选项中 `SERVER_ACCESS_LOG=true` 会自动注入访问日志拦截器(位于最前)。
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## JSON 请求处理器
|
|
134
|
+
|
|
135
|
+
`createJsonHandler<REQ, RES>` 封装了请求正文 JSON 解析、校验、i18n 语言切换、响应缓存等常见流程:
|
|
136
|
+
|
|
137
|
+
```ts
|
|
138
|
+
import { createJsonHandler, notBlank, length } from 'wok-server'
|
|
139
|
+
|
|
140
|
+
interface Form { code: string; nickname: string }
|
|
141
|
+
interface Resp { id: string }
|
|
142
|
+
|
|
143
|
+
const createUser = createJsonHandler<Form, Resp>({
|
|
144
|
+
validation: {
|
|
145
|
+
code: [notBlank(), length({ max: 64 })],
|
|
146
|
+
nickname: [notBlank(), length({ max: 64 })]
|
|
147
|
+
},
|
|
148
|
+
async handle(body, exchange) {
|
|
149
|
+
const newUser = await insertUser(body)
|
|
150
|
+
return { id: newUser.id }
|
|
151
|
+
}
|
|
152
|
+
})
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
- 仅处理 POST 请求,非 POST 返 405
|
|
156
|
+
- `validation` 可选,校验前自动通过 `accept-language` 切换校验器语言
|
|
157
|
+
- 支持 `validation` 为函数以动态生成规则
|
|
158
|
+
- `cache` 可选,设置后通过缓存组件缓存 `Buffer` 格式的响应(避免重复序列化)
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 文件上传
|
|
163
|
+
|
|
164
|
+
`createUploadHandler<RES>` 处理 `application/octet-stream` 格式的二进制文件上传,比 multipart/form-data 更简单高效。也支持通过第三方库(如 formidable)处理 multipart/form-data 格式。
|
|
165
|
+
|
|
166
|
+
详见:[文件上传](references/upload.md)
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Restful 方法分派
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
import { restful } from 'wok-server'
|
|
174
|
+
|
|
175
|
+
routers: {
|
|
176
|
+
'/users': restful({
|
|
177
|
+
get: async exchange => { /* 查列表 */ },
|
|
178
|
+
post: async exchange => { /* 创建 */ },
|
|
179
|
+
delete: async exchange => { /* 删除 */ }
|
|
180
|
+
})
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## 响应 HTML
|
|
187
|
+
|
|
188
|
+
`exchange.respondHtml()` 支持两种方式:内置 `HtmlStuct` 结构化构建(提供 `HtmlTag` 类型推断,支持动态渲染),或直接传入第三方模板引擎(Handlebars、Vue SSR 等)渲染后的 HTML 字符串。
|
|
189
|
+
|
|
190
|
+
详见:[响应 HTML](references/respond-html.md)
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## SSE 服务端推送
|
|
195
|
+
|
|
196
|
+
`createSseHandler` 封装了 Server-Sent Events 协议细节,通过 `ctx.send()` 即可推送数据,支持命名事件和断线重连。
|
|
197
|
+
|
|
198
|
+
详见:[Server-Sent Events](references/sse.md)
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## 静态文件
|
|
203
|
+
|
|
204
|
+
通过 `static` 参数设置静态文件目录映射,支持前缀匹配、主页自动映射和服务器端缓存。
|
|
205
|
+
|
|
206
|
+
详见:[静态文件](references/static-files.md)
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## TLS / HTTPS
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
SERVER_TLS_ENABLE=true
|
|
214
|
+
SERVER_TLS_KEY=/path/to/key.pem
|
|
215
|
+
SERVER_TLS_CERT=/path/to/cert.pem
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## 内部实现要点
|
|
221
|
+
|
|
222
|
+
### 请求处理流程
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
请求到达 → WokServer.handleRequest()
|
|
226
|
+
→ 依次执行拦截器链(含可选的 accessLogInterceptor、CORS 处理)
|
|
227
|
+
→ 路由匹配(精确匹配,未命中使用 '*' handler)
|
|
228
|
+
→ 未捕获异常统一响应 500
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### ServerExchange
|
|
232
|
+
|
|
233
|
+
封装 `IncomingMessage` 和 `ServerResponse`。`bodyBuffer()` 内部有缓存,多次调用只读一次流。`bodyJson` 空正文返回 `{}`。
|
|
234
|
+
|
|
235
|
+
### createJsonHandler 缓存
|
|
236
|
+
|
|
237
|
+
缓存值为 `Buffer`(序列化后的 JSON),直接 `response.end(buffer)` 避免重复 `JSON.stringify`。`cache` 函数返回 `{ key, expiresInSeconds }`,存入缓存组件。
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## 参考文档
|
|
242
|
+
|
|
243
|
+
以下为扩展功能的详细参考文档:
|
|
244
|
+
|
|
245
|
+
| 文档 | 说明 |
|
|
246
|
+
| :-------------------------------------------- | :----------------------- |
|
|
247
|
+
| [文件上传](references/upload.md) | 二进制上传与 multipart/form-data |
|
|
248
|
+
| [响应 HTML](references/respond-html.md) | 内置结构化构建与第三方模板引擎 |
|
|
249
|
+
| [静态文件](references/static-files.md) | 静态文件目录映射与缓存 |
|
|
250
|
+
| [WebSocket](references/websocket.md) | 通过 socket.io 集成 WebSocket |
|
|
251
|
+
| [Server-Sent Events](references/sse.md) | `createSseHandler` 服务端推送 |
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# 响应 HTML
|
|
2
|
+
|
|
3
|
+
MVC 组件提供了两种 HTML 响应方式:框架内置的结构化 HTML 构建和第三方模板引擎。
|
|
4
|
+
|
|
5
|
+
## 内置 HTML 构建
|
|
6
|
+
|
|
7
|
+
`ServerExchange.respondHtml()` 接收 `HtmlStuct` 对象或 HTML 字符串,自动渲染并设置 `Content-Type: text/html; charset=utf-8`。
|
|
8
|
+
|
|
9
|
+
### HtmlStuct 结构
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
interface HtmlStuct {
|
|
13
|
+
lang?: string // <html lang="zh">
|
|
14
|
+
head: SubElementsOpt // <head> 子元素
|
|
15
|
+
body: SubElementsOpt | { attrs?: HtmlAttrs; children: SubElementsOpt } // <body> 子元素及属性
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
type SubElementsOpt = Array<HtmlTag | string> | ((add: (...child) => void) => void)
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`SubElementsOpt` 既可以是静态数组,也可以是一个函数,通过回调参数 `add` 动态添加子元素,配合循环和分支语句实现动态渲染。
|
|
22
|
+
|
|
23
|
+
### HtmlTag 标签定义
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
interface HtmlTag {
|
|
27
|
+
tag: string // 标签名,如 'div'、'span'、'h1'
|
|
28
|
+
selfClosing?: boolean // 是否自闭合,如 <br/>、<img/>
|
|
29
|
+
attrs?: HtmlAttrs // 属性(有类型推断,支持 id、class、style 等全局属性)
|
|
30
|
+
children?: SubElementsOpt // 子元素
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 完整示例
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
await startWebServer({
|
|
38
|
+
routers: {
|
|
39
|
+
'/profile': async exchange => {
|
|
40
|
+
const user = await getUser(exchange.headers.authorization)
|
|
41
|
+
exchange.respondHtml({
|
|
42
|
+
lang: 'zh',
|
|
43
|
+
head: [
|
|
44
|
+
{ tag: 'title', children: ['个人中心'] },
|
|
45
|
+
{ tag: 'script', attrs: { type: 'module', src: 'main.js' } }
|
|
46
|
+
],
|
|
47
|
+
body: {
|
|
48
|
+
attrs: { style: { 'background-color': 'white' } },
|
|
49
|
+
children: add => {
|
|
50
|
+
add({ tag: 'h1', children: ['个人中心'] })
|
|
51
|
+
if (user) {
|
|
52
|
+
add({ tag: 'p', children: [`用户名:${user.account}`] })
|
|
53
|
+
} else {
|
|
54
|
+
add({
|
|
55
|
+
tag: 'p',
|
|
56
|
+
children: [
|
|
57
|
+
'请登录后查看',
|
|
58
|
+
{ tag: 'a', attrs: { href: '/login' }, children: ['点击进行登录'] }
|
|
59
|
+
]
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
add(footer())
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
})
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
})
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 提取可复用组件
|
|
72
|
+
|
|
73
|
+
常用的标签组合可封装为函数,返回 `HtmlTag` 类型:
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
function footer(): HtmlTag {
|
|
77
|
+
return {
|
|
78
|
+
tag: 'div',
|
|
79
|
+
attrs: { class: 'footer' },
|
|
80
|
+
children: [
|
|
81
|
+
{ tag: 'a', attrs: { href: '/about' }, children: ['关于我们'] },
|
|
82
|
+
{ tag: 'a', attrs: { href: '/call' }, children: ['联系我们'] },
|
|
83
|
+
{ tag: 'a', attrs: { href: '/privacy' }, children: ['隐私协议'] }
|
|
84
|
+
]
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### 快捷方法
|
|
90
|
+
|
|
91
|
+
除了 `respondHtml()`,也可直接传入 HTML 字符串:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
exchange.respondHtml('<h1>Hello World</h1>')
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
等价于设置 `Content-Type: text/html` 并输出给定字符串。
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## 第三方模板引擎
|
|
102
|
+
|
|
103
|
+
如果不喜欢内置的结构化构建方式,也可以使用第三方模板库,渲染后将 HTML 字符串传给 `respondHtml()`。
|
|
104
|
+
|
|
105
|
+
### Handlebars
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
import { compile } from 'handlebars'
|
|
109
|
+
|
|
110
|
+
await startWebServer({
|
|
111
|
+
routers: {
|
|
112
|
+
'/html': async exchange => {
|
|
113
|
+
const template = compile(`
|
|
114
|
+
<!DOCTYPE html>
|
|
115
|
+
<html>
|
|
116
|
+
<head><title>Handlebars Example</title></head>
|
|
117
|
+
<body>
|
|
118
|
+
<p>Hello, my name is {{name}}.</p>
|
|
119
|
+
<ul>{{#kids}}<li>{{name}} is {{age}}</li>{{/kids}}</ul>
|
|
120
|
+
</body>
|
|
121
|
+
</html>
|
|
122
|
+
`)
|
|
123
|
+
const data = {
|
|
124
|
+
name: 'Alan',
|
|
125
|
+
kids: [{ name: 'Jimmy', age: '12' }, { name: 'Sally', age: '4' }]
|
|
126
|
+
}
|
|
127
|
+
exchange.respondHtml(template(data))
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Vue 3.x SSR
|
|
134
|
+
|
|
135
|
+
```ts
|
|
136
|
+
import { createSSRApp } from 'vue'
|
|
137
|
+
import { renderToString } from 'vue/server-renderer'
|
|
138
|
+
|
|
139
|
+
await startWebServer({
|
|
140
|
+
routers: {
|
|
141
|
+
'/html': async exchange => {
|
|
142
|
+
const app = createSSRApp({
|
|
143
|
+
data: () => ({ count: 1 }),
|
|
144
|
+
template: `<button>{{ count }}</button>`
|
|
145
|
+
})
|
|
146
|
+
const html = await renderToString(app)
|
|
147
|
+
exchange.respondHtml(`<!DOCTYPE html>
|
|
148
|
+
<html>
|
|
149
|
+
<head><title>Vue SSR</title></head>
|
|
150
|
+
<body><div id="app">${html}</div></body>
|
|
151
|
+
</html>`)
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
})
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
> **提示:** 无论使用哪种方式,最终调用 `exchange.respondHtml()` 即可正确设置响应头与状态码。
|