wok-server 0.1.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/LICENSE +21 -0
- package/README.md +47 -0
- package/dist/cache/cache.js +94 -0
- package/dist/cache/config.js +19 -0
- package/dist/cache/index.js +27 -0
- package/dist/cache/purge-task.js +56 -0
- package/dist/cache/stat.js +47 -0
- package/dist/config/convert.js +36 -0
- package/dist/config/exception.js +14 -0
- package/dist/config/index.js +67 -0
- package/dist/http-client/index.js +132 -0
- package/dist/i18n/ar.js +17 -0
- package/dist/i18n/de.js +17 -0
- package/dist/i18n/en-us.js +17 -0
- package/dist/i18n/es.js +17 -0
- package/dist/i18n/fr.js +17 -0
- package/dist/i18n/i18n.js +231 -0
- package/dist/i18n/index.js +52 -0
- package/dist/i18n/ja.js +17 -0
- package/dist/i18n/ko.js +17 -0
- package/dist/i18n/msg.js +2 -0
- package/dist/i18n/pt.js +17 -0
- package/dist/i18n/ru.js +17 -0
- package/dist/i18n/tag.js +18 -0
- package/dist/i18n/zh-HK.js +17 -0
- package/dist/i18n/zh-TW.js +17 -0
- package/dist/i18n/zh-cn.js +17 -0
- package/dist/index.js +13 -0
- package/dist/log/config.js +28 -0
- package/dist/log/date.js +21 -0
- package/dist/log/file.js +79 -0
- package/dist/log/index.js +109 -0
- package/dist/log/level.js +39 -0
- package/dist/log/store.js +16 -0
- package/dist/mongodb/collection.js +2 -0
- package/dist/mongodb/config.js +34 -0
- package/dist/mongodb/doc.js +2 -0
- package/dist/mongodb/exception.js +14 -0
- package/dist/mongodb/index.js +58 -0
- package/dist/mongodb/manager/base.js +563 -0
- package/dist/mongodb/manager/index.js +63 -0
- package/dist/mongodb/manager/tx-strict.js +84 -0
- package/dist/mongodb/manager/tx.js +30 -0
- package/dist/mongodb/migration.js +52 -0
- package/dist/mvc/access-log.js +31 -0
- package/dist/mvc/config.js +20 -0
- package/dist/mvc/exchange.js +113 -0
- package/dist/mvc/handler/index.js +6 -0
- package/dist/mvc/handler/json.js +33 -0
- package/dist/mvc/handler/restful.js +35 -0
- package/dist/mvc/handler/upload.js +33 -0
- package/dist/mvc/index.js +316 -0
- package/dist/mvc/interceptor.js +2 -0
- package/dist/mvc/query.js +43 -0
- package/dist/mvc/render/file.js +177 -0
- package/dist/mvc/render/html/html.js +90 -0
- package/dist/mvc/render/html/index.js +18 -0
- package/dist/mvc/render/html/style.js +2 -0
- package/dist/mvc/render/index.js +7 -0
- package/dist/mvc/render/json.js +26 -0
- package/dist/mvc/render/text.js +16 -0
- package/dist/mvc/router.js +2 -0
- package/dist/mysql/config.js +49 -0
- package/dist/mysql/exception.js +14 -0
- package/dist/mysql/index.js +85 -0
- package/dist/mysql/manager/base.js +233 -0
- package/dist/mysql/manager/index.js +107 -0
- package/dist/mysql/manager/ops/count.js +20 -0
- package/dist/mysql/manager/ops/criteria.js +326 -0
- package/dist/mysql/manager/ops/delete.js +65 -0
- package/dist/mysql/manager/ops/exist.js +26 -0
- package/dist/mysql/manager/ops/find.js +111 -0
- package/dist/mysql/manager/ops/index.js +14 -0
- package/dist/mysql/manager/ops/insert.js +101 -0
- package/dist/mysql/manager/ops/modify.js +10 -0
- package/dist/mysql/manager/ops/paginate.js +23 -0
- package/dist/mysql/manager/ops/query.js +9 -0
- package/dist/mysql/manager/ops/update.js +201 -0
- package/dist/mysql/manager/tx-strict.js +98 -0
- package/dist/mysql/manager/tx.js +30 -0
- package/dist/mysql/manager/utils.js +56 -0
- package/dist/mysql/migration.js +136 -0
- package/dist/mysql/table-info.js +8 -0
- package/dist/task/daily.js +58 -0
- package/dist/task/fixed-delay.js +33 -0
- package/dist/task/fixed-rate.js +37 -0
- package/dist/task/index.js +9 -0
- package/dist/task/task.js +39 -0
- package/dist/validation/exception.js +44 -0
- package/dist/validation/index.js +29 -0
- package/dist/validation/validator/array.js +38 -0
- package/dist/validation/validator/enum.js +28 -0
- package/dist/validation/validator/index.js +14 -0
- package/dist/validation/validator/length.js +40 -0
- package/dist/validation/validator/max-length.js +35 -0
- package/dist/validation/validator/max.js +29 -0
- package/dist/validation/validator/min-length.js +33 -0
- package/dist/validation/validator/min.js +29 -0
- package/dist/validation/validator/not-blank.js +33 -0
- package/dist/validation/validator/not-null.js +21 -0
- package/dist/validation/validator/plain-obj.js +32 -0
- package/dist/validation/validator/regexp.js +30 -0
- package/documentation/en/index.md +1 -0
- package/documentation/zh-cn/cache.md +59 -0
- package/documentation/zh-cn/config.md +68 -0
- package/documentation/zh-cn/http-client.md +33 -0
- package/documentation/zh-cn/i18n.md +154 -0
- package/documentation/zh-cn/index.md +25 -0
- package/documentation/zh-cn/log.md +40 -0
- package/documentation/zh-cn/mongodb.md +262 -0
- package/documentation/zh-cn/mvc.md +430 -0
- package/documentation/zh-cn/mysql.md +389 -0
- package/documentation/zh-cn/task.md +50 -0
- package/documentation/zh-cn/test.md +57 -0
- package/documentation/zh-cn/validate.md +125 -0
- package/package.json +46 -0
- package/types/cache/cache.d.ts +52 -0
- package/types/cache/config.d.ts +32 -0
- package/types/cache/index.d.ts +2 -0
- package/types/cache/purge-task.d.ts +11 -0
- package/types/cache/stat.d.ts +26 -0
- package/types/config/convert.d.ts +6 -0
- package/types/config/exception.d.ts +7 -0
- package/types/config/index.d.ts +15 -0
- package/types/http-client/index.d.ts +71 -0
- package/types/i18n/ar.d.ts +2 -0
- package/types/i18n/de.d.ts +2 -0
- package/types/i18n/en-us.d.ts +2 -0
- package/types/i18n/es.d.ts +2 -0
- package/types/i18n/fr.d.ts +2 -0
- package/types/i18n/i18n.d.ts +102 -0
- package/types/i18n/index.d.ts +9 -0
- package/types/i18n/ja.d.ts +2 -0
- package/types/i18n/ko.d.ts +2 -0
- package/types/i18n/msg.d.ts +50 -0
- package/types/i18n/pt.d.ts +2 -0
- package/types/i18n/ru.d.ts +2 -0
- package/types/i18n/tag.d.ts +11 -0
- package/types/i18n/zh-HK.d.ts +2 -0
- package/types/i18n/zh-TW.d.ts +2 -0
- package/types/i18n/zh-cn.d.ts +2 -0
- package/types/index.d.ts +10 -0
- package/types/log/config.d.ts +27 -0
- package/types/log/date.d.ts +2 -0
- package/types/log/file.d.ts +5 -0
- package/types/log/index.d.ts +34 -0
- package/types/log/level.d.ts +15 -0
- package/types/log/store.d.ts +12 -0
- package/types/mongodb/collection.d.ts +25 -0
- package/types/mongodb/config.d.ts +45 -0
- package/types/mongodb/doc.d.ts +11 -0
- package/types/mongodb/exception.d.ts +7 -0
- package/types/mongodb/index.d.ts +29 -0
- package/types/mongodb/manager/base.d.ts +188 -0
- package/types/mongodb/manager/index.d.ts +38 -0
- package/types/mongodb/manager/tx-strict.d.ts +41 -0
- package/types/mongodb/manager/tx.d.ts +21 -0
- package/types/mongodb/migration.d.ts +12 -0
- package/types/mvc/access-log.d.ts +7 -0
- package/types/mvc/config.d.ts +30 -0
- package/types/mvc/exchange.d.ts +72 -0
- package/types/mvc/handler/index.d.ts +3 -0
- package/types/mvc/handler/json.d.ts +23 -0
- package/types/mvc/handler/restful.d.ts +11 -0
- package/types/mvc/handler/upload.d.ts +40 -0
- package/types/mvc/index.d.ts +49 -0
- package/types/mvc/interceptor.d.ts +11 -0
- package/types/mvc/query.d.ts +13 -0
- package/types/mvc/render/file.d.ts +10 -0
- package/types/mvc/render/html/html.d.ts +98 -0
- package/types/mvc/render/html/index.d.ts +11 -0
- package/types/mvc/render/html/style.d.ts +1201 -0
- package/types/mvc/render/index.d.ts +4 -0
- package/types/mvc/render/json.d.ts +17 -0
- package/types/mvc/render/text.d.ts +10 -0
- package/types/mvc/router.d.ts +11 -0
- package/types/mysql/config.d.ts +86 -0
- package/types/mysql/exception.d.ts +7 -0
- package/types/mysql/index.d.ts +16 -0
- package/types/mysql/manager/base.d.ts +158 -0
- package/types/mysql/manager/index.d.ts +36 -0
- package/types/mysql/manager/ops/count.d.ts +13 -0
- package/types/mysql/manager/ops/criteria.d.ts +120 -0
- package/types/mysql/manager/ops/delete.d.ts +46 -0
- package/types/mysql/manager/ops/exist.d.ts +6 -0
- package/types/mysql/manager/ops/find.d.ts +66 -0
- package/types/mysql/manager/ops/index.d.ts +10 -0
- package/types/mysql/manager/ops/insert.d.ts +18 -0
- package/types/mysql/manager/ops/modify.d.ts +3 -0
- package/types/mysql/manager/ops/paginate.d.ts +36 -0
- package/types/mysql/manager/ops/query.d.ts +3 -0
- package/types/mysql/manager/ops/update.d.ts +70 -0
- package/types/mysql/manager/tx-strict.d.ts +34 -0
- package/types/mysql/manager/tx.d.ts +15 -0
- package/types/mysql/manager/utils.d.ts +17 -0
- package/types/mysql/migration.d.ts +8 -0
- package/types/mysql/table-info.d.ts +36 -0
- package/types/task/daily.d.ts +15 -0
- package/types/task/fixed-delay.d.ts +8 -0
- package/types/task/fixed-rate.d.ts +8 -0
- package/types/task/index.d.ts +4 -0
- package/types/task/task.d.ts +33 -0
- package/types/validation/exception.d.ts +43 -0
- package/types/validation/index.d.ts +32 -0
- package/types/validation/validator/array.d.ts +5 -0
- package/types/validation/validator/enum.d.ts +8 -0
- package/types/validation/validator/index.d.ts +11 -0
- package/types/validation/validator/length.d.ts +10 -0
- package/types/validation/validator/max-length.d.ts +8 -0
- package/types/validation/validator/max.d.ts +7 -0
- package/types/validation/validator/min-length.d.ts +6 -0
- package/types/validation/validator/min.d.ts +7 -0
- package/types/validation/validator/not-blank.d.ts +7 -0
- package/types/validation/validator/not-null.d.ts +6 -0
- package/types/validation/validator/plain-obj.d.ts +7 -0
- package/types/validation/validator/regexp.d.ts +8 -0
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
# mysql
|
|
2
|
+
|
|
3
|
+
mysql 组件基于 [mysql2](https://www.npmjs.com/package/mysql2) 封装,提供了便捷的单表操作方法,
|
|
4
|
+
支持多数据源和版本管理功能。
|
|
5
|
+
|
|
6
|
+
使用 enableMysql 函数来启用 mysql,参数配置名称可选,默认为 MYSQL
|
|
7
|
+
|
|
8
|
+
## 环境变量
|
|
9
|
+
|
|
10
|
+
下面是所有环境变量配置说明,使用默认名称 MYSQL,如果使用多套数据源,将 MYSQL 前缀替换成自定义名称,详细见初始化部分。
|
|
11
|
+
|
|
12
|
+
| 环境变量 | 说明 |
|
|
13
|
+
| :---------------------------- | :---------------------------------------------------- |
|
|
14
|
+
| MYSQL_HOST | 主机名 |
|
|
15
|
+
| MYSQL_PORT | 端口号 |
|
|
16
|
+
| MYSQL_USER | 用户名 |
|
|
17
|
+
| MYSQL_PASSWORD | 密码 |
|
|
18
|
+
| MYSQL_CHARSET | 字符集,默认 utf8mb4 |
|
|
19
|
+
| MYSQL_DATABASE | 库 |
|
|
20
|
+
| MYSQL_VERSION_CONTROL_ENABLED | 版本控制开启 |
|
|
21
|
+
| MYSQL_VERSION_CONTROL_DIR | 版本控制的文件目录,默认 db_migration |
|
|
22
|
+
| MYSQL_TIMEZONE | 时区,默认 +08:00 |
|
|
23
|
+
| MYSQL_CONNECT_TIMEOUT | 超时时间,单位毫秒,默认 10000 |
|
|
24
|
+
| MYSQL_DEBUG | 调试模式,设置为 true 时会输出执行的 sql |
|
|
25
|
+
| MYSQL_CONNECTION_LIMIT | 最大连接数 |
|
|
26
|
+
| MYSQL_MAX_IDLE | 最大闲置数 |
|
|
27
|
+
| MYSQL_IDLE_TIMEOUT | 闲置的超时时间,也即多久不用算闲置,单位毫秒 |
|
|
28
|
+
| MYSQL_SLOW_SQL_WARN | 慢 sql 警告,启用后如果一个查询过慢,就会输出警告日志 |
|
|
29
|
+
| MYSQL_SLOW_SQL_MS | 慢 sql 毫秒数,默认 200 |
|
|
30
|
+
| MYSQL_TRANSACTION_TIMEOUT | 事务超时时间,单位毫秒,默认 5000 |
|
|
31
|
+
| MYSQL_TRANSACTION_STRICT | 事务严格模式,默认 true,设置为 false 可关闭严格模式 |
|
|
32
|
+
|
|
33
|
+
## 初始化
|
|
34
|
+
|
|
35
|
+
先使用函数 enableMysql 来启用 mysql 组件,然后才能使用相关功能。
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
await enableMysql()
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
上面调用 enableMysql 函数未传递任何参数,默认使用名称 "mysql",搜索以 `MYSQL_` 为前缀的环境变量。
|
|
42
|
+
|
|
43
|
+
如果有连接多个库的需要,可以多次调用 enableMysql ,传递不同的名称。
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// 自定义新的配置名称 d2
|
|
47
|
+
await enableMysql('d2')
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
上传的操作要激活 mysql 时,会自动映射以 `D2_` 为前缀的环境变量。
|
|
51
|
+
|
|
52
|
+
下面是多数据源的环境变量示例:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
# enableMysql() 默认,以 MYSQL_ 为前缀
|
|
56
|
+
MYSQL_HOST=localhost
|
|
57
|
+
MYSQL_PORT=3306
|
|
58
|
+
MYSQL_USER=test
|
|
59
|
+
MYSQL_PASSWORD=abc123
|
|
60
|
+
MYSQL_DATABASE=test1
|
|
61
|
+
# enableMysql('d2') 自定义 D2,以 D2_ 为前缀
|
|
62
|
+
D2_HOST=localhost
|
|
63
|
+
D2_PORT=3306
|
|
64
|
+
D2_USER=test2
|
|
65
|
+
D2_PASSWORD=abcdefg
|
|
66
|
+
D2_DATABASE=test2
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
使用 getMysqlManager 函数来获取 MysqlManager 来完成实体类的相关操作,仅有一个参数,也即是上一步配置的名称,可选。
|
|
70
|
+
|
|
71
|
+
```ts
|
|
72
|
+
// 默认不填,名称是 mysql
|
|
73
|
+
const mysqlManager = getMysqlManager()
|
|
74
|
+
// 指定名称为 d2,对应 enableMysql('d2')
|
|
75
|
+
const d2Manager = getMysqlManager('d2')
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 实体类设置
|
|
79
|
+
|
|
80
|
+
在进行操作之前必须先做好实体类的映射配置, 每个实体类都必须有对应的表信息,下面是用户表的配置示例。
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
/**
|
|
84
|
+
* 用户,映射用户表,所有的字段名称都必须和列名称一致,不支持字段名称映射自定义.
|
|
85
|
+
*/
|
|
86
|
+
export interface User {
|
|
87
|
+
/**
|
|
88
|
+
* id,映射列 id.
|
|
89
|
+
*/
|
|
90
|
+
id: string
|
|
91
|
+
nickname: string
|
|
92
|
+
/**
|
|
93
|
+
* 入职日期,映射列 entry_date.
|
|
94
|
+
*/
|
|
95
|
+
entry_date?: Date
|
|
96
|
+
hobby?: string
|
|
97
|
+
/**
|
|
98
|
+
* 创建和更新时间由于是自动管理的,类型定义为非必填,由组件自动处理,
|
|
99
|
+
* 在调用组件方法时,不用填写这两个字段的信息.
|
|
100
|
+
*/
|
|
101
|
+
createAt?: Date
|
|
102
|
+
updateAt?: Date
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* 用户表信息配置,其作用是自动生成 sql 语句.
|
|
107
|
+
*/
|
|
108
|
+
export const tableUser: Table<User> = {
|
|
109
|
+
/**
|
|
110
|
+
* 表名
|
|
111
|
+
*/
|
|
112
|
+
tableName: 'user',
|
|
113
|
+
/**
|
|
114
|
+
* 主键名称,仅支持单列主键,不支持复合主键.
|
|
115
|
+
*/
|
|
116
|
+
id: 'id',
|
|
117
|
+
/**
|
|
118
|
+
* 列名称,不包含下面自动管理的时间列和主键.
|
|
119
|
+
*/
|
|
120
|
+
columns: ['nickname', 'hobby'],
|
|
121
|
+
/**
|
|
122
|
+
* 创建时间,如果有设置在使用组件操作时会自动管理
|
|
123
|
+
*/
|
|
124
|
+
createdDate: {
|
|
125
|
+
/**
|
|
126
|
+
* 列名称
|
|
127
|
+
*/
|
|
128
|
+
column: 'createAt',
|
|
129
|
+
/**
|
|
130
|
+
* 类型,支持 date 和 number
|
|
131
|
+
*/
|
|
132
|
+
type: 'date'
|
|
133
|
+
},
|
|
134
|
+
/**
|
|
135
|
+
* 更新时间,如果有设置在使用组件操作时会自动管理
|
|
136
|
+
*/
|
|
137
|
+
updatedDate: {
|
|
138
|
+
column: 'updateAt',
|
|
139
|
+
type: 'date'
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
建议所有的表配置都以 table 开头,这样有利于编辑器提示,需要填入表配置信息的时候就输入 table ,编辑器会提示出所有的表配置信息。
|
|
145
|
+
|
|
146
|
+
实体类的配置与前面初始化的库配置是没有强制绑定的,也就是说一个实体类的配置可以给多个库使用。
|
|
147
|
+
在需要做读写分离的场景,可以让主库和只读库共用实体类。
|
|
148
|
+
|
|
149
|
+
### 类型映射
|
|
150
|
+
|
|
151
|
+
实体类字段和查询方法的返回对象的字段有一套类型映射规则,这个需要写的时间注意,**数据库里是什么类型,就必须写对应的 js 原生类型**。
|
|
152
|
+
类型映射逻辑不支持修改,下面是对照表:
|
|
153
|
+
|
|
154
|
+
| js 原生类型 | mysql 字段类型 |
|
|
155
|
+
| :---------- | :------------------------------------------------------------------- |
|
|
156
|
+
| Number | TINYINT,SMALLINT,INT,MEDIUMINT,YEAR.FLOAT,DOUBLE,BIGINT |
|
|
157
|
+
| Date | TIMESTAMP,DATE,DATETIME |
|
|
158
|
+
| Buffer | TINYBLOB,MEDIUMBLOB,LONGBLOB,BLOB,BINARY,VARBINARY,BIT |
|
|
159
|
+
| String | CHAR,VARCHAR,TINYTEXT,MEDIUMTEXT,LONGTEXT,TEXT,ENUM,SET,DECIMAL,TIME |
|
|
160
|
+
|
|
161
|
+
对于可空字段,可以在 ts 里也定义为可空:
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
export interface User {
|
|
165
|
+
/**
|
|
166
|
+
* 头像文件在对象存储中的 key,可空
|
|
167
|
+
*/
|
|
168
|
+
avatar_oss_key?: string
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
枚举类型也可以映射的,但是注意是值映射,例如:
|
|
173
|
+
|
|
174
|
+
```ts
|
|
175
|
+
enum Type {
|
|
176
|
+
COURSE,
|
|
177
|
+
EXAM
|
|
178
|
+
}
|
|
179
|
+
// 实体类
|
|
180
|
+
class Entity {
|
|
181
|
+
type: Type
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
上面的枚举,实际上 Type.COURSE 映射的值是 0, Type.EXAM 映射的值是 1。
|
|
186
|
+
如果需要 Type.COURSE 映射 字符串 COURSE,需要像下面这样处理:
|
|
187
|
+
|
|
188
|
+
```ts
|
|
189
|
+
enum Type {
|
|
190
|
+
COURSE = 'COURSE',
|
|
191
|
+
EXAM = 'EXAM'
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
一般情况下,为了使用起来更方便,更推荐使用合并类型。
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
class Entity {
|
|
199
|
+
type: 'course' | 'exam'
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## 增删改查
|
|
204
|
+
|
|
205
|
+
接下来就可以通过 MysqlManager 实例做增删改查的操作了,所有的方法第一个参数都是表信息。
|
|
206
|
+
|
|
207
|
+
下面是一些增删改查的操作演示。更多的方法信息可参照 MysqlManager 的类型定义,所有方法和参数都有注释。
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
// 获取 MysqlManager 实例
|
|
211
|
+
const manager = getMysqlManager()
|
|
212
|
+
// 按 id 查询
|
|
213
|
+
const admin = await manager.findById(tableUser, 'admin001')
|
|
214
|
+
// 查询一批 id 对应的记录
|
|
215
|
+
const users = await manager.findByIdIn(tableUser, ['admin001', 't001', 't002'])
|
|
216
|
+
// 判定某个 id 是否存在
|
|
217
|
+
const res = await manager.existsById(tableUser, 'admin001')
|
|
218
|
+
// 删除 id 为 d0001 的记录
|
|
219
|
+
await manager.deleteById(tableUser, 'd0001')
|
|
220
|
+
// 查询表中所有记录,危险操作,慎用
|
|
221
|
+
const list = await manager.findAll(tableUser)
|
|
222
|
+
// 插入记录
|
|
223
|
+
await manager.insert(tableUser, {
|
|
224
|
+
id: 'in001',
|
|
225
|
+
nickname: '小明',
|
|
226
|
+
balance: 1
|
|
227
|
+
})
|
|
228
|
+
// 批量插入
|
|
229
|
+
await manager.insertMany(tableUser, [
|
|
230
|
+
{ id: 'im001', nickname: '张飞', balance: 0 },
|
|
231
|
+
{ id: 'im002', nickname: '关羽', balance: 2 },
|
|
232
|
+
{ id: 'im003', nickname: '刘备', balance: 5 }
|
|
233
|
+
])
|
|
234
|
+
// 根据指定的条件查询第一条符合的记录
|
|
235
|
+
const user = await manager.findFirst(tableUser, c =>
|
|
236
|
+
c.like('nickname', 'ff0%').gt('balance', 75).lt('balance', 77)
|
|
237
|
+
)
|
|
238
|
+
// 更新记录,完整更新
|
|
239
|
+
await manager.update(tableUser, { id: 'xxxxxxx', nickname: '王五', balance: 44 })
|
|
240
|
+
// 部分更新,支持置空和递增等操作
|
|
241
|
+
await manager.partialUpdate(tableUser, { id: 'pu000', balance: ['inc', 22] })
|
|
242
|
+
// 批量更新,对所有符合条件的记录进行局部更新
|
|
243
|
+
await manager.updateMany(tableUser, c => c.like('nickname', 'um%').between('balance', 23, 24), {
|
|
244
|
+
balance: ['inc', 2]
|
|
245
|
+
})
|
|
246
|
+
// 查找所有符合条件的记录
|
|
247
|
+
await manager.find({
|
|
248
|
+
table: tableUser,
|
|
249
|
+
criteria: c => c.between('balance', 700, 800).like('id', 'find%'),
|
|
250
|
+
offset: 1,
|
|
251
|
+
limit: 10,
|
|
252
|
+
orderBy: [['balance', 'asc']]
|
|
253
|
+
})
|
|
254
|
+
// 统计符合条件的记录数量
|
|
255
|
+
const count = await manager.count(tableUser, c => c.like('id', 'c00%').like('nickname', '李%'))
|
|
256
|
+
// 分页查询
|
|
257
|
+
await manager.paginate({
|
|
258
|
+
table: tableUser,
|
|
259
|
+
criteria: c => c.like('id', 'pg0%'),
|
|
260
|
+
pn: 2,
|
|
261
|
+
pz: 5,
|
|
262
|
+
orderBy: [
|
|
263
|
+
['balance', 'asc'],
|
|
264
|
+
['id', 'asc']
|
|
265
|
+
]
|
|
266
|
+
})
|
|
267
|
+
// 自定义查询,手写 sql
|
|
268
|
+
interface QueryResult {
|
|
269
|
+
author: string
|
|
270
|
+
book: string
|
|
271
|
+
}
|
|
272
|
+
const list = await manager.query<QueryResult>(
|
|
273
|
+
'select u.nickname as author,b.name as book ' +
|
|
274
|
+
' from ?? u left join ?? b on u.id=b.author_id ' +
|
|
275
|
+
' where b.id is not null',
|
|
276
|
+
['user', 'book']
|
|
277
|
+
)
|
|
278
|
+
// 自定义修改,手写 sql
|
|
279
|
+
await manager.modify(`update user set nickname='无名' where nickname='佚名'`)
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
### 所有操作方法
|
|
283
|
+
|
|
284
|
+
| 方法 | 功能说明 |
|
|
285
|
+
| :------------ | :-------------------------------------------------------------------------- |
|
|
286
|
+
| findById | 按 id 查询 |
|
|
287
|
+
| findByIdIn | 按 id 列表查询多条记录 |
|
|
288
|
+
| existsBy | 判定指定的条件是否存在记录 |
|
|
289
|
+
| existsById | 判定 id 是否存在 |
|
|
290
|
+
| deleteById | 按 id 删除 |
|
|
291
|
+
| deleteMany | 按指定条件删除,危险操作,建议尽可能设置 limit 参数来限制数量 |
|
|
292
|
+
| findAll | 查询表下所有记录,危险操作,建议只对数据量非常小的表使用 |
|
|
293
|
+
| findFirst | 查询符合条件的第一条记录 |
|
|
294
|
+
| insert | 插入记录 |
|
|
295
|
+
| insertMany | 一次性插入多条记录 |
|
|
296
|
+
| update | 更新记录,需要完整信息 |
|
|
297
|
+
| partialUpdate | 局部更新,只提供 id 和需要更新的字段信息 |
|
|
298
|
+
| updateOne | 只更新指定条件的第一条记录,必须是相等条件,不支持范围条件 |
|
|
299
|
+
| updateMany | 更新所有符合条件的记录,危险操作,建议对条件严加限制,控制受影响的范围 |
|
|
300
|
+
| find | 按条件查询所有符合条件的记录,危险操作,建议尽可能设置 limit 参数来限制数量 |
|
|
301
|
+
| count | 统计符合条件的记录数量,危险操作,建议严格限制条件,注意索引的利用 |
|
|
302
|
+
| paginate | 分页查询 ,危险操作,基于 find 和 count |
|
|
303
|
+
| query | 自定义 sql 查询,返回记录列表,支持预编译 sql |
|
|
304
|
+
| modify | 执行自定义 sql,返回操作记录数 ,支持预编译 sql |
|
|
305
|
+
|
|
306
|
+
### 预编译 sql
|
|
307
|
+
|
|
308
|
+
使用 query 或 midify 方法传入自定义 sql 时,sql 是支持预编译的,参数值使用 ? (问号)来占位,表名和
|
|
309
|
+
字段名使用 ?? (双问号)来占位。
|
|
310
|
+
|
|
311
|
+
```sql
|
|
312
|
+
update ?? set ?? = ? where ?? = ?
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
上而的预编译 sql 对应的参数:
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
const values = ['user', 'name', 'tom', 'id', '001']
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
最终编译后的 sql :
|
|
322
|
+
|
|
323
|
+
```sql
|
|
324
|
+
update `user` set `name` = 'tom' where `id` = '001'
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
实际开发中,表名和字段名可不必参与预编译,以免影响代码可读性。
|
|
328
|
+
但是对于一些特殊的名称或者是动态名称,建议使用预编译,相比字符串拼接更安全。
|
|
329
|
+
|
|
330
|
+
## 版本控制
|
|
331
|
+
|
|
332
|
+
前面环境变量有介绍,变量 MYSQL_VERSION_CONTROL_ENABLED 启用管理,变量 MYSQL_VERSION_CONTROL_DIR 设置版本目录,
|
|
333
|
+
目前支持绝对路径或者相对于进程工作目录的相对路径。
|
|
334
|
+
|
|
335
|
+
在版本目录中,所有的文件的格式都是“数字版本号加.sql”。
|
|
336
|
+
|
|
337
|
+
版本管理目录文件列表示例:
|
|
338
|
+
|
|
339
|
+
```
|
|
340
|
+
1.sql
|
|
341
|
+
2.sql
|
|
342
|
+
3.sql
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
版本号是从 1 开始的,逐个递增。**程序迭代,新版本必须添加新的文件,而不能改动已有的版本文件。**
|
|
346
|
+
组件并没有文件校验功能,来防止改动旧文件,也不支持为版本加注释,这些需要在项目中做作好代码的版本控制。
|
|
347
|
+
|
|
348
|
+
**注意不要在版本管理中执行耗时较久的 sql,每个版本的 sql 都尽可能要短。**这主要是因为版本管理在执行在事务中的,
|
|
349
|
+
时间太长会因事务会超导致失败,程序的启动时间也会很长。对于大表创建索引等非常耗时的场景,只能手动操作数据库,无法在版本管理中完成。
|
|
350
|
+
|
|
351
|
+
## 事务
|
|
352
|
+
|
|
353
|
+
使用 MysqlManager 对象的 tx 方法可以执行事务操作,方法接受一个函数参数,函数的参数是 session 对象,
|
|
354
|
+
**所在事务中的操作,都必须调用 session 的方法,session 的操作方法与 mananger 是一样的**。
|
|
355
|
+
|
|
356
|
+
```ts
|
|
357
|
+
mysqlManager.tx(
|
|
358
|
+
async session => {
|
|
359
|
+
// 在事务中更新订单和帐号余额
|
|
360
|
+
// orderId 订单ID
|
|
361
|
+
// accountId 帐号ID
|
|
362
|
+
// amount 订单金额
|
|
363
|
+
await session.partialUpdate(tableOrder, { id: orderId, status: 'finished' })
|
|
364
|
+
await session.partialUpdate(tableAccount, { id: accountId, balance: ['inc', -amount] })
|
|
365
|
+
},
|
|
366
|
+
// 设置隔离级别和超时时间,可选
|
|
367
|
+
{ isolationLevel: 'READ UNCOMMITTED', timeout: 1000 }
|
|
368
|
+
)
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
**注意事务中的异步调用不要忘了 await ,一定要等这些异步执行完,否则相关操作将不会参与事务。**
|
|
372
|
+
|
|
373
|
+
### 严格模式
|
|
374
|
+
|
|
375
|
+
因此事务默认是打开严格模式的,在严格模式下,事务中的很多操作都被禁止,
|
|
376
|
+
通过将环境变量 MYSQL_TRANSACTION_STRICT (默认变量名称,多实例的情况下使用对应名称)
|
|
377
|
+
设置为 false 可以关闭。
|
|
378
|
+
|
|
379
|
+
严格模式下,禁止在事务中进行以下的操作:
|
|
380
|
+
|
|
381
|
+
1. 批量插入 insertMany
|
|
382
|
+
2. 批量更新 updateMany
|
|
383
|
+
3. 批量删除 deleteMany
|
|
384
|
+
4. 批量查询和计数 find、count、paginate
|
|
385
|
+
5. findByIdIn 参数超过 100 个
|
|
386
|
+
6. 使用 query 和 modify 执行自定义 sql
|
|
387
|
+
7. 调用 session 进行的任何操作累计超过 10 次
|
|
388
|
+
|
|
389
|
+
长事务有很大的风险,在生产环境下推荐使用严格事务,并且将事务的超时时间设置的尽可能短一些。
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# 调度任务
|
|
2
|
+
|
|
3
|
+
任务调度提供了一些发起周期性任务的功能,满足基本需要。
|
|
4
|
+
|
|
5
|
+
## 环境变量
|
|
6
|
+
|
|
7
|
+
| 函数名称 | 说明 |
|
|
8
|
+
| :--------------------- | :----------------------------------------------------------------------- |
|
|
9
|
+
| scheduleWithFixedRate | 以固定频率执行任务 |
|
|
10
|
+
| scheduleWithFixedDelay | 以固定的延迟时间执行任务,也即每次任务执行完之后都会在一定的间隔后再执行 |
|
|
11
|
+
| scheduleDailyTask | 每天定时执行任务 |
|
|
12
|
+
|
|
13
|
+
## 使用示例
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
// 启动一个固定延迟的任务,10秒后首次执行,每分钟执行一次
|
|
17
|
+
const controller = scheduleWithFixedDelay(10, 60, {
|
|
18
|
+
name: '记录在线人数',
|
|
19
|
+
async run() {
|
|
20
|
+
const count = await countAuth()
|
|
21
|
+
await createPcu({
|
|
22
|
+
count,
|
|
23
|
+
time: new Date()
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
// 在必要的时候可以通过函数返回的任务控制器停止掉任务
|
|
28
|
+
controller.stop()
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
scheduleWithFixedRate 函数的参数和 scheduleWithFixedDelay 一模一样,
|
|
32
|
+
不同的是 scheduleWithFixedRate 的周期是任务的开始时间,每次任务执行开始时间的间隙是一致的,
|
|
33
|
+
如果任务执行时间过长以致于超过周期,那么下次任务会立即执行。而 scheduleWithFixedDelay 是保持每次任务执行完,
|
|
34
|
+
再间隔指定的时间再会执行下一次任务。
|
|
35
|
+
|
|
36
|
+
```ts
|
|
37
|
+
// 启动一个在每天 1点 30分执行的任务
|
|
38
|
+
const controller = scheduleDailyTask(1, 30, {
|
|
39
|
+
name: '学习报表',
|
|
40
|
+
async run() {
|
|
41
|
+
// 逻辑省略
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## 与内置定时器的区别
|
|
47
|
+
|
|
48
|
+
如果要求不高,也可以使用 Nodejs 内置的 setTimeout 和 setInterval 来执行周期性任务。
|
|
49
|
+
任务组件不同的地方就在于,用起来稍微方便一些,常用的功能已经封装好了,运行方法是异步函数。
|
|
50
|
+
自动记录任务开始时间和异常信息,对于执行时间过长的任务记录运行时间。
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# 单元测试
|
|
2
|
+
|
|
3
|
+
要把项目的单元测试跑起来,需要先启动数据库服务,然后再运行测试。
|
|
4
|
+
|
|
5
|
+
## 启动数据库服务
|
|
6
|
+
|
|
7
|
+
项目源码中有提供脚本来启动本地数据库服务,用于跑测试,服务需要运行在 docker 中,所以
|
|
8
|
+
必须在本地先安装 docker-desktop 。docker 的安装不再介绍,可以自行访问官网查看文档。
|
|
9
|
+
|
|
10
|
+
首先启动 mysql 服务,这个比较的简单,运行 script 目录下的 docker-mysql.bat 或 docker-mysql.sh 即可。
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
./script/docker-mysql.sh
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
然后启动测试用的 mongodb 服务,运行 script 目录下的 docker-mongo.bat 或 docker-mongo.sh。
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
./script/docker-mongo.sh
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
mongodb 光启动服务是不行的,必须要将启动的服务设置成副本集,这样才可以支持事务。
|
|
23
|
+
|
|
24
|
+
在 mongodb 服务的容器中运行 mongosh。
|
|
25
|
+
|
|
26
|
+
```
|
|
27
|
+
docker exec -it mongo_test mongosh
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
在 mongosh 中,执行下面的脚本,初始化成为副本集。
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
rs.initiate({
|
|
34
|
+
_id: 'rs0',
|
|
35
|
+
members: [{ _id: 0, host: '127.0.0.1:27017' }]
|
|
36
|
+
})
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
创建测试帐号。
|
|
40
|
+
|
|
41
|
+
```js
|
|
42
|
+
db.createUser({
|
|
43
|
+
user: 'test',
|
|
44
|
+
pwd: 'abc123',
|
|
45
|
+
roles: [{ role: 'readWrite', db: 'test' }]
|
|
46
|
+
})
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
做完上面的操作,mongodb 服务就可以用来跑测试了。
|
|
50
|
+
|
|
51
|
+
## 运行测试
|
|
52
|
+
|
|
53
|
+
在项目的根目录下运行下面的脚本。
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
npm run test
|
|
57
|
+
```
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# 校验
|
|
2
|
+
|
|
3
|
+
校验组件提供了 validate 函数来校验对象,内置了很多通用的校验规则。
|
|
4
|
+
组件是支持国际化的,提示信息与当前的语言有关,详细可以参考国际化部分。
|
|
5
|
+
|
|
6
|
+
下面是简单的使用示例:
|
|
7
|
+
|
|
8
|
+
```ts
|
|
9
|
+
validate(
|
|
10
|
+
// 校验对象
|
|
11
|
+
{ name: 'tom' },
|
|
12
|
+
// 校验规则,每个属性可设置多个规则
|
|
13
|
+
{
|
|
14
|
+
name: [notNull(), length({ min: 2, max: 16 })]
|
|
15
|
+
}
|
|
16
|
+
)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
自带的校验规则函数。
|
|
20
|
+
|
|
21
|
+
| 函数 | 作用 |
|
|
22
|
+
| :---------- | :--------------------------------------------------- |
|
|
23
|
+
| notNull | 非空校验,不能是 null 或 undefinded |
|
|
24
|
+
| notBlank | 字符非空校验,不能是 null 或 undefinded 或空白字符串 |
|
|
25
|
+
| min | 校验数字最小值 |
|
|
26
|
+
| max | 校验数字最大值 |
|
|
27
|
+
| length | 校验长度,适用于字符串和数组 |
|
|
28
|
+
| maxLength | 检查长度最大值,适用于字符串和数组 |
|
|
29
|
+
| minLength | 检查长度最小值,适用于字符串和数组 |
|
|
30
|
+
| regexp | 正则校验 |
|
|
31
|
+
| enumerate | 枚举校验,验证值必须是指定列表中的某一个 |
|
|
32
|
+
| array | 数组校验,设置元素对象的校验规则来校验每一个元素 |
|
|
33
|
+
| plainObject | 对象校验,如果属性是对象可进一步校验属性值的属性 |
|
|
34
|
+
|
|
35
|
+
**注意: array 和 plainObject 在校验层级深的对象时,可能无法拥有准确的类型推断,必须在使用这两个函数时指定泛型,比如 `plainObject<User>({...})`,否则编译会报错。**
|
|
36
|
+
|
|
37
|
+
下面是对象和数组嵌套的校验示例。
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
interface Tag {
|
|
41
|
+
id: string
|
|
42
|
+
name: string
|
|
43
|
+
permissinos: { edit?: boolean; read?: boolean }
|
|
44
|
+
}
|
|
45
|
+
interface User {
|
|
46
|
+
profile: {
|
|
47
|
+
theme: string
|
|
48
|
+
}
|
|
49
|
+
tags: Tag[]
|
|
50
|
+
}
|
|
51
|
+
validate<User>(
|
|
52
|
+
{
|
|
53
|
+
profile: {
|
|
54
|
+
theme: 'light'
|
|
55
|
+
},
|
|
56
|
+
tags: [
|
|
57
|
+
{ id: '001', name: 'basketball', permissinos: { edit: true, read: true } },
|
|
58
|
+
{ id: '002', name: 'soccer', permissinos: { edit: true } }
|
|
59
|
+
]
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
profile: [
|
|
63
|
+
notNull(),
|
|
64
|
+
plainObject({
|
|
65
|
+
theme: [notBlank()]
|
|
66
|
+
})
|
|
67
|
+
],
|
|
68
|
+
tags: [
|
|
69
|
+
array({
|
|
70
|
+
id: [notBlank()],
|
|
71
|
+
name: [notBlank()],
|
|
72
|
+
permissinos: [
|
|
73
|
+
notNull(),
|
|
74
|
+
// 这里无法自动进行推断类型,必须指定类型,否则编译会有错误
|
|
75
|
+
// 层级过深就必须指定泛型
|
|
76
|
+
plainObject<{ edit?: boolean; read?: boolean }>({
|
|
77
|
+
edit: [notNull()],
|
|
78
|
+
read: [notNull()]
|
|
79
|
+
})
|
|
80
|
+
]
|
|
81
|
+
})
|
|
82
|
+
]
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
在实际开发中,建议最好只有一层,不要嵌套,否则程序将难以维护。
|
|
88
|
+
|
|
89
|
+
## 自定义校验规则
|
|
90
|
+
|
|
91
|
+
如果自带的校验规则无法满足需要,也可以编写自定义的校验规则。
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
/**
|
|
95
|
+
* 自定义校验
|
|
96
|
+
* @returns 属性校验器
|
|
97
|
+
*/
|
|
98
|
+
function customValidate(): PropValidator {
|
|
99
|
+
// 校验器名称,用于跟踪信息
|
|
100
|
+
const validator = 'custom'
|
|
101
|
+
const message = '不能以 t 开头'
|
|
102
|
+
return val => {
|
|
103
|
+
// 不校验空
|
|
104
|
+
if (!val) {
|
|
105
|
+
return { ok: true }
|
|
106
|
+
}
|
|
107
|
+
if (typeof val !== 'string') {
|
|
108
|
+
return { ok: false, validator, message: '值不是字符串' }
|
|
109
|
+
}
|
|
110
|
+
if (val.startsWith('t')) {
|
|
111
|
+
return { ok: false, validator, message }
|
|
112
|
+
}
|
|
113
|
+
return { ok: true }
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
validate(
|
|
118
|
+
{ name: 'tim' },
|
|
119
|
+
{
|
|
120
|
+
name: [customValidate()]
|
|
121
|
+
}
|
|
122
|
+
)
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
内置的校验规则函数都做了国际化的支持,自定义的校验规则如有国际化的要求,需要自行处理,详细可以参考国际化章节。
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "wok-server",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"packageManager": "pnpm@8.9.0",
|
|
5
|
+
"description": "一个基于 NodeJs 和 TypeScript 的后端框架,轻量级、克制、简洁。A lightweight, restrained, and concise backend framework based on Node.js and TypeScript.",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"build": "rm -rf ./types && rm -rf ./dist && tsc -p ./ -d --declarationDir ./types --outDir ./dist",
|
|
8
|
+
"test": "mocha --timeout 300000"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"web",
|
|
12
|
+
"server"
|
|
13
|
+
],
|
|
14
|
+
"files": [
|
|
15
|
+
"types/",
|
|
16
|
+
"dist/",
|
|
17
|
+
"docs/",
|
|
18
|
+
"documentation/",
|
|
19
|
+
"README.md"
|
|
20
|
+
],
|
|
21
|
+
"author": "peak",
|
|
22
|
+
"license": "ISC",
|
|
23
|
+
"publishConfig": {
|
|
24
|
+
"registry": "https://registry.npmjs.org"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/formidable": "^3.4.4",
|
|
28
|
+
"@types/mocha": "^10.0.1",
|
|
29
|
+
"@types/node": "^18.14.5",
|
|
30
|
+
"assert": "^2.0.0",
|
|
31
|
+
"formidable": "^3.5.1",
|
|
32
|
+
"mocha": "^10.2.0",
|
|
33
|
+
"socket.io": "^4.7.2",
|
|
34
|
+
"socket.io-client": "^4.7.2",
|
|
35
|
+
"ts-node": "^10.9.1",
|
|
36
|
+
"tslib": "^2.5.0",
|
|
37
|
+
"typescript": "^4.9.5"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"dotenv": "^16.0.3",
|
|
41
|
+
"mongodb": "^5.7.0",
|
|
42
|
+
"mysql2": "^3.2.0"
|
|
43
|
+
},
|
|
44
|
+
"main": "dist/index.js",
|
|
45
|
+
"types": "types/index.d.ts"
|
|
46
|
+
}
|