wok-server 0.5.0 → 0.7.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 +278 -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 +381 -356
- package/dist/mysql/manager/ops/delete.js +59 -65
- package/dist/mysql/manager/ops/exist.js +26 -26
- package/dist/mysql/manager/ops/find.js +149 -169
- package/dist/mysql/manager/ops/index.js +16 -14
- package/dist/mysql/manager/ops/insert.js +132 -106
- package/dist/mysql/manager/ops/modify.js +10 -10
- package/dist/mysql/manager/ops/order-by.js +28 -0
- package/dist/mysql/manager/ops/paginate.js +48 -23
- package/dist/mysql/manager/ops/query.js +9 -9
- package/dist/mysql/manager/ops/update.js +222 -216
- package/dist/mysql/manager/ops/upsert.js +178 -0
- package/dist/mysql/manager/ops/utils.js +28 -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 +682 -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/documentation/zh-cn/mysql.md +146 -17
- package/package.json +4 -1
- package/skills/wok-server-api-rules/SKILL.md +350 -0
- package/skills/wok-server-cache/SKILL.md +216 -0
- package/skills/wok-server-code-navigation/SKILL.md +153 -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 +388 -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 +332 -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 +446 -0
- package/src/mysql/manager/ops/delete.ts +91 -0
- package/src/mysql/manager/ops/exist.ts +41 -0
- package/src/mysql/manager/ops/find.ts +209 -0
- package/src/mysql/manager/ops/index.ts +13 -0
- package/src/mysql/manager/ops/insert.ts +158 -0
- package/src/mysql/manager/ops/modify.ts +14 -0
- package/src/mysql/manager/ops/order-by.ts +58 -0
- package/src/mysql/manager/ops/paginate.ts +100 -0
- package/src/mysql/manager/ops/query.ts +13 -0
- package/src/mysql/manager/ops/update.ts +318 -0
- package/src/mysql/manager/ops/upsert.ts +224 -0
- package/src/mysql/manager/ops/utils.ts +24 -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 +196 -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 +144 -134
- package/types/mysql/manager/ops/delete.d.ts +47 -46
- package/types/mysql/manager/ops/exist.d.ts +6 -6
- package/types/mysql/manager/ops/find.d.ts +87 -86
- package/types/mysql/manager/ops/index.d.ts +12 -10
- package/types/mysql/manager/ops/insert.d.ts +32 -18
- package/types/mysql/manager/ops/modify.d.ts +3 -3
- package/types/mysql/manager/ops/order-by.d.ts +38 -0
- package/types/mysql/manager/ops/paginate.d.ts +53 -36
- package/types/mysql/manager/ops/query.d.ts +3 -3
- package/types/mysql/manager/ops/update.d.ts +99 -76
- package/types/mysql/manager/ops/upsert.d.ts +36 -0
- 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,682 @@
|
|
|
1
|
+
# MySQL
|
|
2
|
+
|
|
3
|
+
The MySQL component is built on top of [mysql2](https://www.npmjs.com/package/mysql2), providing convenient single-table operations with support for multiple data sources and version management.
|
|
4
|
+
|
|
5
|
+
Use the enableMysql function to enable MySQL. The configuration name parameter is optional, defaulting to MYSQL.
|
|
6
|
+
|
|
7
|
+
## Environment Variables
|
|
8
|
+
|
|
9
|
+
Below are all environment variable configurations using the default name MYSQL. If using multiple data sources, replace the MYSQL prefix with a custom name. See initialization section for details.
|
|
10
|
+
|
|
11
|
+
| Environment Variable | Description |
|
|
12
|
+
| :-------------------------------- | :-------------------------------------------------------------------------- |
|
|
13
|
+
| MYSQL_HOST | Hostname |
|
|
14
|
+
| MYSQL_PORT | Port number |
|
|
15
|
+
| MYSQL_USER | Username |
|
|
16
|
+
| MYSQL_PASSWORD | Password |
|
|
17
|
+
| MYSQL_CHARSET | Character set, default utf8mb4 |
|
|
18
|
+
| MYSQL_DATABASE | Database name |
|
|
19
|
+
| MYSQL_VERSION_CONTROL_ENABLED | Enable version control |
|
|
20
|
+
| MYSQL_VERSION_CONTROL_DIR | Version control directory, default db_migration |
|
|
21
|
+
| MYSQL_TIMEZONE | Timezone, default +08:00 |
|
|
22
|
+
| MYSQL_CONNECT_TIMEOUT | Connection timeout in milliseconds, default 10000 |
|
|
23
|
+
| MYSQL_DEBUG | Debug mode. Set to true to output executed SQL |
|
|
24
|
+
| MYSQL_CONNECTION_LIMIT | Maximum connections |
|
|
25
|
+
| MYSQL_MAX_IDLE | Maximum idle connections |
|
|
26
|
+
| MYSQL_IDLE_TIMEOUT | Idle timeout in milliseconds (when a connection becomes idle) |
|
|
27
|
+
| MYSQL_SLOW_SQL_WARN | Slow SQL warning. When enabled, warning logs are output for slow queries |
|
|
28
|
+
| MYSQL_SLOW_SQL_MS | Slow SQL threshold in milliseconds, default 200 |
|
|
29
|
+
| MYSQL_TRANSACTION_TIMEOUT | Transaction timeout in milliseconds, default 5000 |
|
|
30
|
+
| MYSQL_TRANSACTION_STRICT | Transaction strict mode, default true. Set to false to disable |
|
|
31
|
+
| MYSQL_MAX_OPS_IN_STRICT_TX | Maximum operations allowed in strict transaction, default 10 |
|
|
32
|
+
|
|
33
|
+
## Initialization
|
|
34
|
+
|
|
35
|
+
First use the enableMysql function to enable the MySQL component, then use related features.
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
await enableMysql()
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The above call to enableMysql passes no parameters, using the default name "mysql" and searching for environment variables prefixed with `MYSQL_`.
|
|
42
|
+
|
|
43
|
+
If multiple databases need to be connected, call enableMysql multiple times with different names.
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// Custom configuration name d2
|
|
47
|
+
await enableMysql('d2')
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
After executing the above, environment variables prefixed with `D2_` will be mapped automatically.
|
|
51
|
+
|
|
52
|
+
Here is an example of environment variables for multiple data sources:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# enableMysql() default, prefixed with MYSQL_
|
|
56
|
+
MYSQL_HOST=localhost
|
|
57
|
+
MYSQL_PORT=3306
|
|
58
|
+
MYSQL_USER=test
|
|
59
|
+
MYSQL_PASSWORD=abc123
|
|
60
|
+
MYSQL_DATABASE=test1
|
|
61
|
+
# enableMysql('d2') custom D2, prefixed with D2_
|
|
62
|
+
D2_HOST=localhost
|
|
63
|
+
D2_PORT=3306
|
|
64
|
+
D2_USER=test2
|
|
65
|
+
D2_PASSWORD=abcdefg
|
|
66
|
+
D2_DATABASE=test2
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Use the getMysqlManager function to get a MysqlManager for entity operations. It takes one optional parameter, the name configured in the previous step.
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
// Default, name is mysql
|
|
73
|
+
const mysqlManager = getMysqlManager()
|
|
74
|
+
// Specify name d2, corresponds to enableMysql('d2')
|
|
75
|
+
const d2Manager = getMysqlManager('d2')
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Entity Configuration
|
|
79
|
+
|
|
80
|
+
Entity mapping configuration must be done before operations. Each entity class must have corresponding table information. Here is an example configuration for a user table:
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
/**
|
|
84
|
+
* User, maps to user table. All field names must match column names. Custom field name mapping is not supported.
|
|
85
|
+
*/
|
|
86
|
+
export interface User {
|
|
87
|
+
/**
|
|
88
|
+
* id, maps to column id.
|
|
89
|
+
*/
|
|
90
|
+
id: string
|
|
91
|
+
nickname: string
|
|
92
|
+
/**
|
|
93
|
+
* Entry date, maps to column entry_date.
|
|
94
|
+
*/
|
|
95
|
+
entry_date?: Date
|
|
96
|
+
hobby?: string
|
|
97
|
+
/**
|
|
98
|
+
* Create and update times are managed automatically by the component,
|
|
99
|
+
* so they are defined as optional in the type definition.
|
|
100
|
+
* These fields don't need to be filled when calling component methods.
|
|
101
|
+
*/
|
|
102
|
+
createAt?: Date
|
|
103
|
+
updateAt?: Date
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* User table configuration, used to automatically generate SQL statements.
|
|
108
|
+
*/
|
|
109
|
+
export const tableUser: Table<User> = {
|
|
110
|
+
/**
|
|
111
|
+
* Table name
|
|
112
|
+
*/
|
|
113
|
+
tableName: 'user',
|
|
114
|
+
/**
|
|
115
|
+
* Primary key name. Only single-column primary keys are supported, composite keys are not.
|
|
116
|
+
*/
|
|
117
|
+
id: 'id',
|
|
118
|
+
/**
|
|
119
|
+
* Column names, excluding automatically managed time columns and primary key.
|
|
120
|
+
*/
|
|
121
|
+
columns: ['nickname', 'hobby'],
|
|
122
|
+
/**
|
|
123
|
+
* Creation time. If set, it will be managed automatically during component operations.
|
|
124
|
+
*/
|
|
125
|
+
createdDate: {
|
|
126
|
+
/**
|
|
127
|
+
* Column name
|
|
128
|
+
*/
|
|
129
|
+
column: 'createAt',
|
|
130
|
+
/**
|
|
131
|
+
* Type, supports date and number
|
|
132
|
+
*/
|
|
133
|
+
type: 'date'
|
|
134
|
+
},
|
|
135
|
+
/**
|
|
136
|
+
* Update time. If set, it will be managed automatically during component operations.
|
|
137
|
+
*/
|
|
138
|
+
updatedDate: {
|
|
139
|
+
column: 'updateAt',
|
|
140
|
+
type: 'date'
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
It is recommended that all table configurations start with "table" for better editor autocompletion. When table configuration is needed, just type "table" and the editor will show all table configurations.
|
|
146
|
+
|
|
147
|
+
Entity configuration is not bound to the database configuration initialized earlier, meaning one entity configuration can be used by multiple databases. In read-write separation scenarios, primary and read-only databases can share entities.
|
|
148
|
+
|
|
149
|
+
### Type Mapping
|
|
150
|
+
|
|
151
|
+
Entity field types and query method return object field types follow a type mapping rule that must be followed: **the database type must match the corresponding JavaScript native type**.
|
|
152
|
+
|
|
153
|
+
The type mapping logic cannot be modified. Here is the mapping table:
|
|
154
|
+
|
|
155
|
+
| JavaScript Type | MySQL Field Type |
|
|
156
|
+
| :---------------- | :------------------------------------------------------------------------ |
|
|
157
|
+
| Boolean | TINYINT |
|
|
158
|
+
| Number | TINYINT, SMALLINT, INT, MEDIUMINT, YEAR, FLOAT, DOUBLE, BIGINT |
|
|
159
|
+
| Date | TIMESTAMP, DATE, DATETIME |
|
|
160
|
+
| Buffer | TINYBLOB, MEDIUMBLOB, LONGBLOB, BLOB, BINARY, VARBINARY, BIT |
|
|
161
|
+
| String | CHAR, VARCHAR, TINYTEXT, MEDIUMTEXT, LONGTEXT, TEXT, ENUM, SET, DECIMAL, TIME |
|
|
162
|
+
| Object or Array | JSON |
|
|
163
|
+
|
|
164
|
+
For nullable fields, define them as nullable in TypeScript:
|
|
165
|
+
|
|
166
|
+
```ts
|
|
167
|
+
export interface User {
|
|
168
|
+
/**
|
|
169
|
+
* Avatar file key in object storage, nullable
|
|
170
|
+
*/
|
|
171
|
+
avatar_oss_key?: string
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Enum types can also be mapped, but note that it's value mapping. For example:
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
enum Type {
|
|
179
|
+
COURSE,
|
|
180
|
+
EXAM
|
|
181
|
+
}
|
|
182
|
+
// Entity class
|
|
183
|
+
class Entity {
|
|
184
|
+
type: Type
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
In the above enum, Type.COURSE maps to 0 and Type.EXAM maps to 1. If you need Type.COURSE to map to the string "COURSE", handle it like this:
|
|
189
|
+
|
|
190
|
+
```ts
|
|
191
|
+
enum Type {
|
|
192
|
+
COURSE = 'COURSE',
|
|
193
|
+
EXAM = 'EXAM'
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
For convenience, union types are generally recommended:
|
|
198
|
+
|
|
199
|
+
```ts
|
|
200
|
+
class Entity {
|
|
201
|
+
type: 'course' | 'exam'
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## CRUD Operations
|
|
206
|
+
|
|
207
|
+
Now you can perform CRUD operations through the MysqlManager instance. All methods take table information as the first parameter.
|
|
208
|
+
|
|
209
|
+
Below are some CRUD operation examples. For more method details, refer to the MysqlManager type definition. All methods and parameters have comments.
|
|
210
|
+
|
|
211
|
+
```ts
|
|
212
|
+
// Get MysqlManager instance
|
|
213
|
+
const manager = getMysqlManager()
|
|
214
|
+
// Query by id
|
|
215
|
+
const admin = await manager.findById(tableUser, 'admin001')
|
|
216
|
+
// Query multiple records by id list
|
|
217
|
+
const users = await manager.findByIdIn(tableUser, ['admin001', 't001', 't002'])
|
|
218
|
+
// Check if id exists
|
|
219
|
+
const res = await manager.existsById(tableUser, 'admin001')
|
|
220
|
+
// Delete record with id d0001
|
|
221
|
+
await manager.deleteById(tableUser, 'd0001')
|
|
222
|
+
// Query all records in table, dangerous operation, use with caution
|
|
223
|
+
const list = await manager.findAll(tableUser)
|
|
224
|
+
// Insert record
|
|
225
|
+
await manager.insert(tableUser, {
|
|
226
|
+
id: 'in001',
|
|
227
|
+
nickname: '小明',
|
|
228
|
+
balance: 1
|
|
229
|
+
})
|
|
230
|
+
// Insert with expressions
|
|
231
|
+
await manager.insert(tableUser, {
|
|
232
|
+
id: 'in002',
|
|
233
|
+
nickname: '小红',
|
|
234
|
+
balance: ['expr', '?? * ?', ['score', 2]],
|
|
235
|
+
createAt: ['now']
|
|
236
|
+
})
|
|
237
|
+
// Batch insert
|
|
238
|
+
await manager.insertMany(tableUser, [
|
|
239
|
+
{ id: 'im001', nickname: '张飞', balance: 0 },
|
|
240
|
+
{ id: 'im002', nickname: '关羽', balance: 2 },
|
|
241
|
+
{ id: 'im003', nickname: '刘备', balance: 5 }
|
|
242
|
+
])
|
|
243
|
+
// Upsert single record, update on conflict
|
|
244
|
+
await manager.upsert(tableUser, { id: 'us001', nickname: '赵云', balance: 10 })
|
|
245
|
+
// Batch upsert
|
|
246
|
+
await manager.upsertMany(tableUser, [
|
|
247
|
+
{ id: 'us002', nickname: '马超', balance: 20 },
|
|
248
|
+
{ id: 'us003', nickname: '黄忠', balance: 30 }
|
|
249
|
+
])
|
|
250
|
+
// Upsert with custom updater (e.g., increment balance on conflict)
|
|
251
|
+
await manager.upsertWithUpdater(
|
|
252
|
+
tableUser,
|
|
253
|
+
{ id: 'us001', nickname: '赵云', balance: 10 },
|
|
254
|
+
{ balance: ['inc', 5], nickname: '赵云-updated' }
|
|
255
|
+
)
|
|
256
|
+
// Query first matching record by condition
|
|
257
|
+
const user = await manager.findFirst(tableUser, c =>
|
|
258
|
+
c.like('nickname', 'ff0%').gt('balance', 75).lt('balance', 77)
|
|
259
|
+
)
|
|
260
|
+
// Update record, full update
|
|
261
|
+
await manager.update(tableUser, { id: 'xxxxxxx', nickname: '王五', balance: 44 })
|
|
262
|
+
// Partial update, supports nulling and increment operations
|
|
263
|
+
await manager.partialUpdate(tableUser, { id: 'pu000', balance: ['inc', 22] })
|
|
264
|
+
// Batch update, partial update all matching records
|
|
265
|
+
await manager.updateMany(tableUser, c => c.like('nickname', 'um%').between('balance', 23, 24), {
|
|
266
|
+
balance: ['inc', 2]
|
|
267
|
+
})
|
|
268
|
+
// Find all matching records
|
|
269
|
+
await manager.find({
|
|
270
|
+
table: tableUser,
|
|
271
|
+
criteria: c => c.between('balance', 700, 800).like('id', 'find%'),
|
|
272
|
+
offset: 1,
|
|
273
|
+
limit: 10,
|
|
274
|
+
orderBy: [['balance', 'asc']]
|
|
275
|
+
})
|
|
276
|
+
// Custom order by expression: balance * 2 desc
|
|
277
|
+
await manager.find({
|
|
278
|
+
table: tableUser,
|
|
279
|
+
criteria: c => c.like('nickname', 'ff0%'),
|
|
280
|
+
orderBy: [['expr', '?? * ?', ['balance', 2], 'desc']]
|
|
281
|
+
})
|
|
282
|
+
// Custom criteria expression: balance * 2 > 50
|
|
283
|
+
await manager.find({
|
|
284
|
+
table: tableUser,
|
|
285
|
+
criteria: c => c.like('id', 'critex%').expr('?? * ? > ?', ['balance', 2, 50]),
|
|
286
|
+
orderBy: [['balance', 'asc']]
|
|
287
|
+
})
|
|
288
|
+
// Count matching records
|
|
289
|
+
const count = await manager.count(tableUser, c => c.like('id', 'c00%').like('nickname', '李%'))
|
|
290
|
+
// Paginated query
|
|
291
|
+
await manager.paginate({
|
|
292
|
+
table: tableUser,
|
|
293
|
+
criteria: c => c.like('id', 'pg0%'),
|
|
294
|
+
pn: 2,
|
|
295
|
+
pz: 5,
|
|
296
|
+
orderBy: [
|
|
297
|
+
['balance', 'asc'],
|
|
298
|
+
['id', 'asc']
|
|
299
|
+
]
|
|
300
|
+
})
|
|
301
|
+
// Custom query, write SQL manually
|
|
302
|
+
interface QueryResult {
|
|
303
|
+
author: string
|
|
304
|
+
book: string
|
|
305
|
+
}
|
|
306
|
+
const list = await manager.query<QueryResult>(
|
|
307
|
+
'select u.nickname as author,b.name as book ' +
|
|
308
|
+
' from ?? u left join ?? b on u.id=b.author_id ' +
|
|
309
|
+
' where b.id is not null',
|
|
310
|
+
['user', 'book']
|
|
311
|
+
)
|
|
312
|
+
// Custom modification, write SQL manually
|
|
313
|
+
await manager.modify(`update user set nickname='无名' where nickname='佚名'`)
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### All Operation Methods
|
|
317
|
+
|
|
318
|
+
| Method | Description |
|
|
319
|
+
| :-------------- | :-------------------------------------------------------------------------- |
|
|
320
|
+
| findById | Query by id |
|
|
321
|
+
| findByIdIn | Query multiple records by id list |
|
|
322
|
+
| existsBy | Check if records exist by condition |
|
|
323
|
+
| existsById | Check if id exists |
|
|
324
|
+
| deleteById | Delete by id |
|
|
325
|
+
| deleteMany | Delete by condition. Dangerous operation, recommend setting limit parameter |
|
|
326
|
+
| findAll | Query all records in table. Dangerous operation, only for small tables |
|
|
327
|
+
| findFirst | Query first matching record |
|
|
328
|
+
| insert | Insert record |
|
|
329
|
+
| insertMany | Insert multiple records at once |
|
|
330
|
+
| upsert | Insert record, update on duplicate key |
|
|
331
|
+
| upsertMany | Batch upsert |
|
|
332
|
+
| upsertWithUpdater | Upsert single record with custom updater for conflicts |
|
|
333
|
+
| update | Update record, requires complete information |
|
|
334
|
+
| partialUpdate | Partial update, only provide id and fields to update |
|
|
335
|
+
| updateOne | Update only first matching record, only supports equality conditions |
|
|
336
|
+
| updateMany | Update all matching records. Dangerous operation, restrict conditions |
|
|
337
|
+
| find | Query all matching records. Dangerous operation, recommend limit parameter |
|
|
338
|
+
| findSelect | Conditional query with specified fields. Same as find but with select param |
|
|
339
|
+
| count | Count matching records. Dangerous operation, use strict conditions |
|
|
340
|
+
| paginate | Paginated query. Dangerous operation, based on find and count |
|
|
341
|
+
| paginateSelect | Paginated query with specified fields, based on findSelect and count |
|
|
342
|
+
| query | Custom SQL query, returns record list, supports prepared statements |
|
|
343
|
+
| modify | Execute custom SQL, returns affected rows, supports prepared statements |
|
|
344
|
+
|
|
345
|
+
### Insert Expressions
|
|
346
|
+
|
|
347
|
+
Starting from version 0.7.0, `insert`, `insertMany`, `upsert` and other insert methods accept `InsertValue` type,
|
|
348
|
+
allowing expressions in the VALUES clause:
|
|
349
|
+
|
|
350
|
+
```ts
|
|
351
|
+
await manager.insert(tableUser, {
|
|
352
|
+
id: 'in001',
|
|
353
|
+
nickname: '小明',
|
|
354
|
+
// Set to NOW()
|
|
355
|
+
createAt: ['now'],
|
|
356
|
+
// Resolve conflict: set field to the array ['setNull'] (not the setNull operation)
|
|
357
|
+
extra: ['set', ['setNull']],
|
|
358
|
+
// Custom expression: balance = score * 2
|
|
359
|
+
balance: ['expr', '?? * ?', ['score', 2]],
|
|
360
|
+
// Expression without parameters
|
|
361
|
+
balance2: ['expr', 'RAND() * 100']
|
|
362
|
+
})
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Order By Expressions
|
|
366
|
+
|
|
367
|
+
Starting from version 0.7.0, the `orderBy` parameter is upgraded to `OrderBy<T>` type, supporting custom
|
|
368
|
+
expression-based ordering in addition to regular column ordering. This type is backward-compatible.
|
|
369
|
+
|
|
370
|
+
```ts
|
|
371
|
+
await manager.find({
|
|
372
|
+
table: tableUser,
|
|
373
|
+
criteria: c => c.like('nickname', 'ob%'),
|
|
374
|
+
// Regular column ordering (backward-compatible)
|
|
375
|
+
orderBy: [['balance', 'asc']]
|
|
376
|
+
})
|
|
377
|
+
|
|
378
|
+
// Custom expression ordering: balance * 2 desc
|
|
379
|
+
// SQL: ORDER BY `balance` * 2 desc
|
|
380
|
+
await manager.find({
|
|
381
|
+
table: tableUser,
|
|
382
|
+
criteria: c => c.like('nickname', 'ob%'),
|
|
383
|
+
orderBy: [['expr', '?? * ?', ['balance', 2], 'desc']]
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
// Order by name length: CHAR_LENGTH(name) desc
|
|
387
|
+
// SQL: ORDER BY CHAR_LENGTH(`name`) desc
|
|
388
|
+
await manager.find({
|
|
389
|
+
table: tableBook,
|
|
390
|
+
criteria: c => c.like('name', 'ob%'),
|
|
391
|
+
orderBy: [['expr', 'CHAR_LENGTH(??)', ['name'], 'desc']]
|
|
392
|
+
})
|
|
393
|
+
|
|
394
|
+
// Mixed: regular column + expression
|
|
395
|
+
orderBy: [
|
|
396
|
+
['active', 'asc'],
|
|
397
|
+
['expr', '?? * ?', ['balance', 2], 'desc']
|
|
398
|
+
]
|
|
399
|
+
// SQL: ORDER BY `active` asc , `balance` * 2 desc
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
### Criteria Expressions
|
|
403
|
+
|
|
404
|
+
Starting from version 0.7.0, `MysqlCriteria` adds an `expr()` method for inserting custom SQL expressions
|
|
405
|
+
in the WHERE clause:
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
// balance * 2 > 50
|
|
409
|
+
// SQL: where ... and `balance` * 2 > 50
|
|
410
|
+
await manager.find({
|
|
411
|
+
table: tableUser,
|
|
412
|
+
criteria: c => c.like('id', 'critex%').expr('?? * ? > ?', ['balance', 2, 50])
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
// Full-text search
|
|
416
|
+
// SQL: where ... and MATCH(`title`, `content`) AGAINST (? IN BOOLEAN MODE)
|
|
417
|
+
await manager.find({
|
|
418
|
+
table: tableBook,
|
|
419
|
+
criteria: c => c.expr('MATCH(??, ??) AGAINST(? IN BOOLEAN MODE)', ['title', 'content', keyword])
|
|
420
|
+
})
|
|
421
|
+
```
|
|
422
|
+
|
|
423
|
+
### JSON Type
|
|
424
|
+
|
|
425
|
+
Version 0.2.0 adds limited support for JSON types. You can insert and query normally, and filtering conditions partially support MySQL's JSON-related functions.
|
|
426
|
+
|
|
427
|
+
Compared to storing JSON as strings and deserializing in the program, using JSON format is much more convenient and efficient for development. Here is a complete example.
|
|
428
|
+
|
|
429
|
+
Database table creation statement with JSON type field:
|
|
430
|
+
|
|
431
|
+
```sql
|
|
432
|
+
CREATE TABLE
|
|
433
|
+
question (
|
|
434
|
+
id VARCHAR(32) PRIMARY KEY,
|
|
435
|
+
title VARCHAR(256) NOT NULL COMMENT '标题',
|
|
436
|
+
options json NOT NULL COMMENT '选项列表,json 数组',
|
|
437
|
+
question_setter json NOT NULL COMMENT '出题人信息,json 对象',
|
|
438
|
+
create_at BIGINT UNSIGNED NOT NULL COMMENT '创建时间',
|
|
439
|
+
update_at BIGINT UNSIGNED NOT NULL COMMENT '更新时间'
|
|
440
|
+
) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '试题';
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
Table mapping configuration. JSON type fields can be declared as custom types:
|
|
444
|
+
|
|
445
|
+
```ts
|
|
446
|
+
// Option
|
|
447
|
+
export interface QuesOption {
|
|
448
|
+
title: string
|
|
449
|
+
correct?: boolean
|
|
450
|
+
}
|
|
451
|
+
// Question setter
|
|
452
|
+
export interface QuestionSetter {
|
|
453
|
+
id: string
|
|
454
|
+
name: string
|
|
455
|
+
}
|
|
456
|
+
// Question
|
|
457
|
+
export interface Question {
|
|
458
|
+
id: string
|
|
459
|
+
title: string
|
|
460
|
+
// Options
|
|
461
|
+
options: QuesOption[]
|
|
462
|
+
// Question setter
|
|
463
|
+
question_setter: QuestionSetter
|
|
464
|
+
create_at?: number
|
|
465
|
+
update_at?: number
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export const tableQuestion: Table<Question> = {
|
|
469
|
+
tableName: 'question',
|
|
470
|
+
id: 'id',
|
|
471
|
+
columns: ['title', 'options', 'question_setter'],
|
|
472
|
+
createdDate: {
|
|
473
|
+
type: 'number',
|
|
474
|
+
column: 'create_at'
|
|
475
|
+
},
|
|
476
|
+
updatedDate: {
|
|
477
|
+
type: 'number',
|
|
478
|
+
column: 'update_at'
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
Common methods work the same way. JSON data is passed according to the field definition format:
|
|
484
|
+
|
|
485
|
+
```ts
|
|
486
|
+
await getMysqlManager().insert(tableQuestion, {
|
|
487
|
+
id: '003',
|
|
488
|
+
title: '下面哪个类型是 Mysql 不支持的',
|
|
489
|
+
options: [
|
|
490
|
+
{ title: 'TINYINT' },
|
|
491
|
+
{ title: 'BOOLEAN', correct: true },
|
|
492
|
+
{ title: 'CHAR' },
|
|
493
|
+
{ title: 'TEXT' }
|
|
494
|
+
],
|
|
495
|
+
question_setter: { id: 'x333', name: '小李老师' }
|
|
496
|
+
})
|
|
497
|
+
// Queried data is complete, no further processing needed. JSON fields are typed correctly
|
|
498
|
+
const q1 = await getMysqlManager().findById(tableQuestion, '003')
|
|
499
|
+
q1.question_setter.name // 小李老师
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
Query conditions support json_extract and json_length, which can be used wherever query conditions are supported. Instead of passing column names, pass a tuple:
|
|
503
|
+
|
|
504
|
+
```ts
|
|
505
|
+
await manager.findFirst(tableQuestion, c =>
|
|
506
|
+
// Query records where question_setter.id = 'x333'
|
|
507
|
+
c.eq(['json_extract', 'question_setter', '$.id'], 'x333')
|
|
508
|
+
)
|
|
509
|
+
await manager.findFirst(tableQuestion, c =>
|
|
510
|
+
// Query records where options[0].title = '地球'
|
|
511
|
+
c.eq(['json_extract', 'options', '$[0].title'], '地球')
|
|
512
|
+
)
|
|
513
|
+
await manager.find({
|
|
514
|
+
table: tableQuestion,
|
|
515
|
+
// Query records where options array has >= 5 elements
|
|
516
|
+
criteria: c => c.gte(['json_length', 'options'], 5)
|
|
517
|
+
})
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
Both json_extract and json_length queries require passing a tuple. The first parameter is the query type, the second is the field name, and json_extract has a third parameter for the property path. The property path format is the same as JavaScript property access syntax, using $ to refer to the field's value.
|
|
521
|
+
|
|
522
|
+
```ts
|
|
523
|
+
// Batch update records where question_setter.id = 'x333'
|
|
524
|
+
await manager.updateMany({
|
|
525
|
+
table: tableQuestion,
|
|
526
|
+
query: c => c.eq(['json_extract', 'question_setter', '$.id'], 'x333'),
|
|
527
|
+
updater: {
|
|
528
|
+
// Update question_setter info
|
|
529
|
+
question_setter: { id: 'x333', name: '李帅' }
|
|
530
|
+
}
|
|
531
|
+
})
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
Updates do not currently support json_set and other functions. You cannot update only part of a JSON field; you must update the entire field. This type of operation is rarely used and may be considered in future versions.
|
|
535
|
+
|
|
536
|
+
### Special Modification Operations
|
|
537
|
+
|
|
538
|
+
The partialUpdate and updateMany methods support partial field modifications and special operations like increment and nulling.
|
|
539
|
+
|
|
540
|
+
```ts
|
|
541
|
+
await manager.updateMany(tableUser, c => c.between('balance', 23, 24), {
|
|
542
|
+
// Increase balance by 2
|
|
543
|
+
balance: ['inc', 2],
|
|
544
|
+
// Increase visits by 1 (default increment)
|
|
545
|
+
visits: ['inc'],
|
|
546
|
+
// Set consume_type to null
|
|
547
|
+
consume_type: ['setNull'],
|
|
548
|
+
// Set to NOW()
|
|
549
|
+
last_login_at: ['now'],
|
|
550
|
+
// NULL-safe string concatenation: col = CONCAT(IFNULL(col, ''), ?)
|
|
551
|
+
nickname: ['concat', '-suffix'],
|
|
552
|
+
// Custom expression: score = score * 2
|
|
553
|
+
score: ['expr', '?? * ?', ['score', 2]]
|
|
554
|
+
})
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
> **Note**: `['func']` has been removed in 0.7.0. Use `['expr']` instead.
|
|
558
|
+
> E.g., `['func', 'NOW()']` → `['expr', 'NOW()']`.
|
|
559
|
+
|
|
560
|
+
**Starting from version 0.7.0**, `null` is treated the same as `undefined` and will be ignored during updates. **To set a field to NULL, you must use `['setNull']`**.
|
|
561
|
+
|
|
562
|
+
```ts
|
|
563
|
+
interface User {
|
|
564
|
+
id: string
|
|
565
|
+
role: string | null
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
// Correct: Use ['setNull'] to set field to NULL
|
|
569
|
+
await manager.partialUpdate(tableUser, {
|
|
570
|
+
id: '001',
|
|
571
|
+
role: ['setNull']
|
|
572
|
+
})
|
|
573
|
+
|
|
574
|
+
// Wrong: Starting from 0.7.0, null is ignored and won't update the field
|
|
575
|
+
await manager.partialUpdate(tableUser, {
|
|
576
|
+
id: '001',
|
|
577
|
+
role: null // This operation will not take effect
|
|
578
|
+
})
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
The special array syntax is used for convenience, avoiding the need to introduce new types. **However, after introducing JSON types, if a JSON field is an array, it may conflict with special modification operations**. For example, setting a JSON field to `['setNull']` would be interpreted as a nulling operation.
|
|
582
|
+
|
|
583
|
+
```ts
|
|
584
|
+
// Record entity definition
|
|
585
|
+
interface Record {
|
|
586
|
+
id: string
|
|
587
|
+
// extra field is a JSON array
|
|
588
|
+
extra: string[]
|
|
589
|
+
}
|
|
590
|
+
await manager.partialUpdate(tableRecord, {
|
|
591
|
+
id: '001',
|
|
592
|
+
// This would be interpreted as nulling extra
|
|
593
|
+
extra: ['setNull']
|
|
594
|
+
})
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
The component provides a set operation to resolve conflicts. It's also a special array where the first element is 'set' and the second is the value to set:
|
|
598
|
+
|
|
599
|
+
```ts
|
|
600
|
+
await manager.partialUpdate(tableRecord, {
|
|
601
|
+
id: '001',
|
|
602
|
+
// This correctly sets extra to ['setNull']
|
|
603
|
+
extra: ['set', ['setNull']]
|
|
604
|
+
})
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
### Prepared SQL
|
|
608
|
+
|
|
609
|
+
When using query or modify methods with custom SQL, prepared statements are supported. Use ? (question mark) for parameter values and ?? (double question mark) for table and column names.
|
|
610
|
+
|
|
611
|
+
```sql
|
|
612
|
+
update ?? set ?? = ? where ?? = ?
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
Parameters for the above prepared SQL:
|
|
616
|
+
|
|
617
|
+
```ts
|
|
618
|
+
const values = ['user', 'name', 'tom', 'id', '001']
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
Final compiled SQL:
|
|
622
|
+
|
|
623
|
+
```sql
|
|
624
|
+
update `user` set `name` = 'tom' where `id` = '001'
|
|
625
|
+
```
|
|
626
|
+
|
|
627
|
+
In actual development, table and column names don't necessarily need to be parameterized, as it may reduce code readability. However, for special or dynamic names, prepared statements are recommended for security compared to string concatenation.
|
|
628
|
+
|
|
629
|
+
## Version Control
|
|
630
|
+
|
|
631
|
+
As introduced in environment variables, MYSQL_VERSION_CONTROL_ENABLED enables version management, and MYSQL_VERSION_CONTROL_DIR sets the version directory. Currently, absolute paths or relative paths from the process working directory are supported.
|
|
632
|
+
|
|
633
|
+
In the version directory, all files follow the format "numeric version number.sql".
|
|
634
|
+
|
|
635
|
+
Example version directory file listing:
|
|
636
|
+
|
|
637
|
+
```
|
|
638
|
+
1.sql
|
|
639
|
+
2.sql
|
|
640
|
+
3.sql
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
Version numbers start from 1 and increment sequentially. **For program iterations, new versions must add new files, not modify existing ones.** The component does not have file validation to prevent modification of old files, nor does it support version comments. These need to be handled through project code version control.
|
|
644
|
+
|
|
645
|
+
**Note: Do not execute time-consuming SQL in version management. Each version's SQL should be as short as possible.** This is mainly because version management executes within a transaction. Too long execution times may cause transaction timeout and failure, and program startup time will be very long. For time-consuming operations like creating indexes on large tables, manual database operations are required and cannot be completed through version management.
|
|
646
|
+
|
|
647
|
+
## Transactions
|
|
648
|
+
|
|
649
|
+
Use the MysqlManager object's tx method to execute transaction operations. The method accepts a function parameter whose parameter is a session object. **All operations in the transaction must call session methods, which are the same as manager methods**.
|
|
650
|
+
|
|
651
|
+
```ts
|
|
652
|
+
mysqlManager.tx(
|
|
653
|
+
async session => {
|
|
654
|
+
// Update order and account balance in transaction
|
|
655
|
+
// orderId Order ID
|
|
656
|
+
// accountId Account ID
|
|
657
|
+
// amount Order amount
|
|
658
|
+
await session.partialUpdate(tableOrder, { id: orderId, status: 'finished' })
|
|
659
|
+
await session.partialUpdate(tableAccount, { id: accountId, balance: ['inc', -amount] })
|
|
660
|
+
},
|
|
661
|
+
// Set isolation level and timeout, optional
|
|
662
|
+
{ isolationLevel: 'READ UNCOMMITTED', timeout: 1000 }
|
|
663
|
+
)
|
|
664
|
+
```
|
|
665
|
+
|
|
666
|
+
**Note: Don't forget to await asynchronous calls in transactions. They must complete before the transaction commits, otherwise the operations won't participate in the transaction.**
|
|
667
|
+
|
|
668
|
+
### Strict Mode
|
|
669
|
+
|
|
670
|
+
Transactions have strict mode enabled by default. Many operations are prohibited in strict mode. Set the environment variable MYSQL_TRANSACTION_STRICT (default variable name, use corresponding name for multiple instances) to false to disable it.
|
|
671
|
+
|
|
672
|
+
In strict mode, the following operations are prohibited in transactions:
|
|
673
|
+
|
|
674
|
+
1. Bulk insert insertMany
|
|
675
|
+
2. Bulk update updateMany
|
|
676
|
+
3. Bulk delete deleteMany
|
|
677
|
+
4. Bulk query and count find, count, paginate
|
|
678
|
+
5. findByIdIn with more than 100 parameters
|
|
679
|
+
6. Execute custom SQL with query and modify
|
|
680
|
+
7. Any operation called via session exceeding 10 times. The MYSQL_MAX_OPS_IN_STRICT_TX variable can modify this limit
|
|
681
|
+
|
|
682
|
+
Long transactions are risky. In production environments, strict transactions are recommended with the shortest possible timeout.
|