wok-server 0.1.9 → 0.2.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/dist/cache/cache.js +11 -7
- package/dist/mvc/index.js +5 -0
- package/dist/mysql/manager/ops/criteria.js +46 -29
- package/dist/mysql/manager/ops/insert.js +7 -2
- package/dist/mysql/manager/ops/update.js +3 -2
- package/dist/mysql/manager/ops/utils.js +20 -0
- package/documentation/zh-cn/mysql.md +110 -6
- package/package.json +1 -1
- package/types/mysql/manager/ops/criteria.d.ts +21 -13
- package/types/mysql/manager/ops/utils.d.ts +5 -0
package/dist/cache/cache.js
CHANGED
|
@@ -79,13 +79,17 @@ class Cache {
|
|
|
79
79
|
}
|
|
80
80
|
// 创建新的异步流程
|
|
81
81
|
const promise = Promise.resolve().then(async () => {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
82
|
+
try {
|
|
83
|
+
const finalExpireInSeconds = typeof expiresInSeconds === 'number' ? expiresInSeconds : config_1.config.defaultExpireInSeconds;
|
|
84
|
+
// 计算值
|
|
85
|
+
const res = provider();
|
|
86
|
+
const val = res instanceof Promise ? await res : res;
|
|
87
|
+
this.put(key, val, finalExpireInSeconds);
|
|
88
|
+
return val;
|
|
89
|
+
}
|
|
90
|
+
finally {
|
|
91
|
+
this.promiseMap.delete(key);
|
|
92
|
+
}
|
|
89
93
|
});
|
|
90
94
|
this.promiseMap.set(key, promise);
|
|
91
95
|
return promise;
|
package/dist/mvc/index.js
CHANGED
|
@@ -5,6 +5,7 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
const promises_1 = require("fs/promises");
|
|
7
7
|
const http_1 = require("http");
|
|
8
|
+
const https_1 = require("https");
|
|
8
9
|
const os_1 = require("os");
|
|
9
10
|
const path_1 = require("path");
|
|
10
11
|
const log_1 = require("../log");
|
|
@@ -197,6 +198,10 @@ let SERVER;
|
|
|
197
198
|
* @param opts
|
|
198
199
|
*/
|
|
199
200
|
async function startWebServer(opts) {
|
|
201
|
+
(0, https_1.createServer)({
|
|
202
|
+
cert: '', key: ''
|
|
203
|
+
}, () => {
|
|
204
|
+
});
|
|
200
205
|
if (SERVER) {
|
|
201
206
|
throw new Error('The server has already been started!');
|
|
202
207
|
}
|
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.buildQuery = exports.MysqlCriteria = void 0;
|
|
4
4
|
const exception_1 = require("../../exception");
|
|
5
|
+
/**
|
|
6
|
+
* 生成条件查询中键的sql片段,包含 sql 内容和要传递的值
|
|
7
|
+
*/
|
|
8
|
+
function generateMysqlCriteriaKeySqlSeg(key) {
|
|
9
|
+
if (Array.isArray(key)) {
|
|
10
|
+
if (key[0] === 'json_extract') {
|
|
11
|
+
return { sqlSeg: `JSON_EXTRACT(??, ${JSON.stringify(key[2])})`, value: key[1] };
|
|
12
|
+
}
|
|
13
|
+
if (key[0] === 'json_length') {
|
|
14
|
+
return { sqlSeg: `JSON_LENGTH(??)`, value: key[1] };
|
|
15
|
+
}
|
|
16
|
+
throw new exception_1.MysqlException(`Unsupported MysqlCriteriaKey type: ${key[0]}`);
|
|
17
|
+
}
|
|
18
|
+
return { sqlSeg: '??', value: key };
|
|
19
|
+
}
|
|
5
20
|
/**
|
|
6
21
|
* mysql 查询条件( query criterion ),默认查询条件都是并且关系(and), 部分方法会有例外,在使用的时候请注意方法说明。
|
|
7
22
|
*
|
|
@@ -18,7 +33,7 @@ class MysqlCriteria {
|
|
|
18
33
|
* @param value
|
|
19
34
|
*/
|
|
20
35
|
eq(column, value) {
|
|
21
|
-
this.criteria.push({ type: 'eq',
|
|
36
|
+
this.criteria.push({ type: 'eq', key: column, value });
|
|
22
37
|
return this;
|
|
23
38
|
}
|
|
24
39
|
/**
|
|
@@ -27,7 +42,7 @@ class MysqlCriteria {
|
|
|
27
42
|
* @param value
|
|
28
43
|
*/
|
|
29
44
|
neq(column, value) {
|
|
30
|
-
this.criteria.push({ type: 'neq',
|
|
45
|
+
this.criteria.push({ type: 'neq', key: column, value });
|
|
31
46
|
return this;
|
|
32
47
|
}
|
|
33
48
|
/**
|
|
@@ -37,7 +52,7 @@ class MysqlCriteria {
|
|
|
37
52
|
* @returns
|
|
38
53
|
*/
|
|
39
54
|
like(column, value) {
|
|
40
|
-
this.criteria.push({ type: 'like',
|
|
55
|
+
this.criteria.push({ type: 'like', key: column, value });
|
|
41
56
|
return this;
|
|
42
57
|
}
|
|
43
58
|
/**
|
|
@@ -47,14 +62,14 @@ class MysqlCriteria {
|
|
|
47
62
|
* @returns
|
|
48
63
|
*/
|
|
49
64
|
notLike(column, value) {
|
|
50
|
-
this.criteria.push({ type: 'notLike',
|
|
65
|
+
this.criteria.push({ type: 'notLike', key: column, value });
|
|
51
66
|
return this;
|
|
52
67
|
}
|
|
53
68
|
/**
|
|
54
69
|
* BETWEEN x and y
|
|
55
70
|
*/
|
|
56
71
|
between(column, min, max) {
|
|
57
|
-
this.criteria.push({ type: 'between',
|
|
72
|
+
this.criteria.push({ type: 'between', key: column, value: [min, max] });
|
|
58
73
|
return this;
|
|
59
74
|
}
|
|
60
75
|
/**
|
|
@@ -63,7 +78,7 @@ class MysqlCriteria {
|
|
|
63
78
|
* @param value
|
|
64
79
|
*/
|
|
65
80
|
gt(column, value) {
|
|
66
|
-
this.criteria.push({ type: 'gt',
|
|
81
|
+
this.criteria.push({ type: 'gt', key: column, value });
|
|
67
82
|
return this;
|
|
68
83
|
}
|
|
69
84
|
/**
|
|
@@ -72,7 +87,7 @@ class MysqlCriteria {
|
|
|
72
87
|
* @param value
|
|
73
88
|
*/
|
|
74
89
|
gte(column, value) {
|
|
75
|
-
this.criteria.push({ type: 'gte',
|
|
90
|
+
this.criteria.push({ type: 'gte', key: column, value });
|
|
76
91
|
return this;
|
|
77
92
|
}
|
|
78
93
|
/**
|
|
@@ -81,7 +96,7 @@ class MysqlCriteria {
|
|
|
81
96
|
* @param value
|
|
82
97
|
*/
|
|
83
98
|
lt(column, value) {
|
|
84
|
-
this.criteria.push({ type: 'lt',
|
|
99
|
+
this.criteria.push({ type: 'lt', key: column, value });
|
|
85
100
|
return this;
|
|
86
101
|
}
|
|
87
102
|
/**
|
|
@@ -90,7 +105,7 @@ class MysqlCriteria {
|
|
|
90
105
|
* @param value
|
|
91
106
|
*/
|
|
92
107
|
lte(column, value) {
|
|
93
|
-
this.criteria.push({ type: 'lte',
|
|
108
|
+
this.criteria.push({ type: 'lte', key: column, value });
|
|
94
109
|
return this;
|
|
95
110
|
}
|
|
96
111
|
/**
|
|
@@ -99,7 +114,7 @@ class MysqlCriteria {
|
|
|
99
114
|
* @param values
|
|
100
115
|
*/
|
|
101
116
|
in(column, values) {
|
|
102
|
-
this.criteria.push({ type: 'in',
|
|
117
|
+
this.criteria.push({ type: 'in', key: column, value: values });
|
|
103
118
|
return this;
|
|
104
119
|
}
|
|
105
120
|
/**
|
|
@@ -108,7 +123,7 @@ class MysqlCriteria {
|
|
|
108
123
|
* @param values
|
|
109
124
|
*/
|
|
110
125
|
notIn(column, values) {
|
|
111
|
-
this.criteria.push({ type: 'notIn',
|
|
126
|
+
this.criteria.push({ type: 'notIn', key: column, value: values });
|
|
112
127
|
return this;
|
|
113
128
|
}
|
|
114
129
|
/**
|
|
@@ -137,7 +152,7 @@ class MysqlCriteria {
|
|
|
137
152
|
* @returns
|
|
138
153
|
*/
|
|
139
154
|
isNull(field) {
|
|
140
|
-
this.criteria.push({ type: 'isNull',
|
|
155
|
+
this.criteria.push({ type: 'isNull', key: field });
|
|
141
156
|
return this;
|
|
142
157
|
}
|
|
143
158
|
/**
|
|
@@ -146,7 +161,7 @@ class MysqlCriteria {
|
|
|
146
161
|
* @returns
|
|
147
162
|
*/
|
|
148
163
|
isNotNull(field) {
|
|
149
|
-
this.criteria.push({ type: 'isNotNull',
|
|
164
|
+
this.criteria.push({ type: 'isNotNull', key: field });
|
|
150
165
|
return this;
|
|
151
166
|
}
|
|
152
167
|
/**
|
|
@@ -168,7 +183,7 @@ class MysqlCriteria {
|
|
|
168
183
|
criterion.criteria.check();
|
|
169
184
|
continue;
|
|
170
185
|
}
|
|
171
|
-
if (!criterion.
|
|
186
|
+
if (!criterion.key) {
|
|
172
187
|
throw new exception_1.MysqlException('The column name of the query criteria cannot be blank.');
|
|
173
188
|
}
|
|
174
189
|
if (criterion.type === 'isNull' || criterion.type === 'isNotNull') {
|
|
@@ -176,19 +191,19 @@ class MysqlCriteria {
|
|
|
176
191
|
}
|
|
177
192
|
if (criterion.type === 'in' || criterion.type === 'notIn') {
|
|
178
193
|
if (!Array.isArray(criterion.value)) {
|
|
179
|
-
throw new exception_1.MysqlException(`Invalid ${criterion.type} condition,the condition value is not a array type,column name:${criterion.
|
|
194
|
+
throw new exception_1.MysqlException(`Invalid ${criterion.type} condition,the condition value is not a array type,column name:${criterion.key.toString()}`);
|
|
180
195
|
}
|
|
181
196
|
if (!criterion.value.length) {
|
|
182
|
-
throw new exception_1.MysqlException(`Invalid ${criterion.type} condition,the condition value cannot be an empty array,column name:${criterion.
|
|
197
|
+
throw new exception_1.MysqlException(`Invalid ${criterion.type} condition,the condition value cannot be an empty array,column name:${criterion.key.toString()}`);
|
|
183
198
|
}
|
|
184
199
|
continue;
|
|
185
200
|
}
|
|
186
201
|
if (criterion.type === 'between') {
|
|
187
202
|
if (!Array.isArray(criterion.value)) {
|
|
188
|
-
throw new exception_1.MysqlException(`Invalid between condition,the condition value is not an array type,column name:${criterion.
|
|
203
|
+
throw new exception_1.MysqlException(`Invalid between condition,the condition value is not an array type,column name:${criterion.key.toString()}, value:${criterion.value}`);
|
|
189
204
|
}
|
|
190
205
|
if (criterion.value.length !== 2) {
|
|
191
|
-
throw new exception_1.MysqlException(`Invalid between condition,the condition value must be an array of length 2,column: ${criterion.
|
|
206
|
+
throw new exception_1.MysqlException(`Invalid between condition,the condition value must be an array of length 2,column: ${criterion.key.toString()},value:${criterion.value.length}`);
|
|
192
207
|
}
|
|
193
208
|
continue;
|
|
194
209
|
}
|
|
@@ -196,7 +211,7 @@ class MysqlCriteria {
|
|
|
196
211
|
typeof criterion.value !== 'string' &&
|
|
197
212
|
!(criterion.value instanceof Date)) {
|
|
198
213
|
throw new exception_1.MysqlException('The value of the query criteria is invalid,only number,string and Date are supported,' +
|
|
199
|
-
`column name : ${criterion.
|
|
214
|
+
`column name : ${criterion.key.toString()},value : ${criterion.value} .`);
|
|
200
215
|
}
|
|
201
216
|
}
|
|
202
217
|
}
|
|
@@ -209,11 +224,11 @@ class MysqlCriteria {
|
|
|
209
224
|
const values = [];
|
|
210
225
|
for (const criterion of this.criteria) {
|
|
211
226
|
// 普通的查询
|
|
212
|
-
if (criterion.
|
|
227
|
+
if (criterion.key && criterion.value !== undefined) {
|
|
213
228
|
// between 特殊处理
|
|
214
229
|
if (criterion.type === 'between') {
|
|
215
230
|
sqlFragments.push('and ?? between ? and ? ');
|
|
216
|
-
values.push(criterion.
|
|
231
|
+
values.push(criterion.key, criterion.value[0], criterion.value[1]);
|
|
217
232
|
continue;
|
|
218
233
|
}
|
|
219
234
|
// 符号
|
|
@@ -249,25 +264,27 @@ class MysqlCriteria {
|
|
|
249
264
|
sign = 'not like';
|
|
250
265
|
}
|
|
251
266
|
if (sign) {
|
|
267
|
+
const keySeg = generateMysqlCriteriaKeySqlSeg(criterion.key);
|
|
252
268
|
if (criterion.type === 'in' || criterion.type === 'notIn') {
|
|
253
|
-
sqlFragments.push(`and
|
|
269
|
+
sqlFragments.push(`and ${keySeg.sqlSeg} ${sign} (?) `);
|
|
254
270
|
}
|
|
255
271
|
else {
|
|
256
|
-
sqlFragments.push(`and
|
|
272
|
+
sqlFragments.push(`and ${keySeg.sqlSeg} ${sign} ? `);
|
|
257
273
|
}
|
|
258
|
-
values.push(
|
|
274
|
+
values.push(keySeg.value, criterion.value);
|
|
259
275
|
}
|
|
260
276
|
continue;
|
|
261
277
|
}
|
|
262
|
-
else if (criterion.
|
|
278
|
+
else if (criterion.key) {
|
|
279
|
+
const keySeg = generateMysqlCriteriaKeySqlSeg(criterion.key);
|
|
263
280
|
if (criterion.type === 'isNull') {
|
|
264
|
-
sqlFragments.push(`and
|
|
265
|
-
values.push(
|
|
281
|
+
sqlFragments.push(`and ${keySeg.sqlSeg} is null `);
|
|
282
|
+
values.push(keySeg.value);
|
|
266
283
|
continue;
|
|
267
284
|
}
|
|
268
285
|
if (criterion.type === 'isNotNull') {
|
|
269
|
-
sqlFragments.push(`and
|
|
270
|
-
values.push(
|
|
286
|
+
sqlFragments.push(`and ${keySeg.sqlSeg} is not null `);
|
|
287
|
+
values.push(keySeg.value);
|
|
271
288
|
continue;
|
|
272
289
|
}
|
|
273
290
|
}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.insertMany = exports.insert = void 0;
|
|
4
4
|
const exception_1 = require("../../exception");
|
|
5
5
|
const utils_1 = require("../utils");
|
|
6
|
+
const utils_2 = require("./utils");
|
|
6
7
|
/**
|
|
7
8
|
* 为表插入数据
|
|
8
9
|
* @param connection
|
|
@@ -34,7 +35,11 @@ async function insert(config, connection, table, data) {
|
|
|
34
35
|
const sql = `insert into ??(${columns.map(() => '??').join(',')}) values(${columns
|
|
35
36
|
.map(() => '?')
|
|
36
37
|
.join(',')})`;
|
|
37
|
-
const values = [
|
|
38
|
+
const values = [
|
|
39
|
+
table.tableName,
|
|
40
|
+
...columns,
|
|
41
|
+
...columns.map(col => (0, utils_2.processColumnValue)(data[col]))
|
|
42
|
+
];
|
|
38
43
|
const res = await (0, utils_1.promiseQuery)(config, connection, sql, values);
|
|
39
44
|
const packet = res;
|
|
40
45
|
if (packet.affectedRows !== 1) {
|
|
@@ -89,7 +94,7 @@ async function insertMany(config, connection, table, list) {
|
|
|
89
94
|
if (table.updatedDate) {
|
|
90
95
|
data[table.updatedDate.column] = updatedDate;
|
|
91
96
|
}
|
|
92
|
-
values.push(...columns.map(col => data[col]));
|
|
97
|
+
values.push(...columns.map(col => (0, utils_2.processColumnValue)(data[col])));
|
|
93
98
|
});
|
|
94
99
|
const res = await (0, utils_1.promiseQuery)(config, connection, sql, values);
|
|
95
100
|
const rsh = res;
|
|
@@ -4,6 +4,7 @@ exports.updateMany = exports.updateOne = exports.partialUpdate = exports.update
|
|
|
4
4
|
const exception_1 = require("../../exception");
|
|
5
5
|
const criteria_1 = require("./criteria");
|
|
6
6
|
const utils_1 = require("../utils");
|
|
7
|
+
const utils_2 = require("./utils");
|
|
7
8
|
/**
|
|
8
9
|
* 更新
|
|
9
10
|
* @param config
|
|
@@ -30,7 +31,7 @@ async function update(config, connection, table, data) {
|
|
|
30
31
|
// 值
|
|
31
32
|
const values = [
|
|
32
33
|
table.tableName,
|
|
33
|
-
...columns.flatMap(col => [col, data[col]]),
|
|
34
|
+
...columns.flatMap(col => [col, (0, utils_2.processColumnValue)(data[col])]),
|
|
34
35
|
table.id,
|
|
35
36
|
data[table.id]
|
|
36
37
|
];
|
|
@@ -79,7 +80,7 @@ function updatorToSql(table, updater) {
|
|
|
79
80
|
continue;
|
|
80
81
|
}
|
|
81
82
|
updateFragList.push(' ?? = ? ');
|
|
82
|
-
values.push(column, val);
|
|
83
|
+
values.push(column, (0, utils_2.processColumnValue)(val));
|
|
83
84
|
}
|
|
84
85
|
return { sql: updateFragList.join(','), values };
|
|
85
86
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processColumnValue = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* 处理列的值,对特殊类型 json 进行加工处理后返回
|
|
6
|
+
* @param value
|
|
7
|
+
*/
|
|
8
|
+
function processColumnValue(value) {
|
|
9
|
+
// date 类型 typeof 也是 object ,先排除
|
|
10
|
+
if (value instanceof Date) {
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
// json
|
|
14
|
+
if (typeof value === 'object') {
|
|
15
|
+
return JSON.stringify(value);
|
|
16
|
+
}
|
|
17
|
+
// 其它的情况直接返回
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
exports.processColumnValue = processColumnValue;
|
|
@@ -151,12 +151,14 @@ export const tableUser: Table<User> = {
|
|
|
151
151
|
实体类字段和查询方法的返回对象的字段有一套类型映射规则,这个需要写的时间注意,**数据库里是什么类型,就必须写对应的 js 原生类型**。
|
|
152
152
|
类型映射逻辑不支持修改,下面是对照表:
|
|
153
153
|
|
|
154
|
-
| js 原生类型
|
|
155
|
-
|
|
|
156
|
-
|
|
|
157
|
-
|
|
|
158
|
-
|
|
|
159
|
-
|
|
|
154
|
+
| js 原生类型 | mysql 字段类型 |
|
|
155
|
+
| :-------------- | :------------------------------------------------------------------- |
|
|
156
|
+
| Boolean | TINYINT |
|
|
157
|
+
| Number | TINYINT,SMALLINT,INT,MEDIUMINT,YEAR.FLOAT,DOUBLE,BIGINT |
|
|
158
|
+
| Date | TIMESTAMP,DATE,DATETIME |
|
|
159
|
+
| Buffer | TINYBLOB,MEDIUMBLOB,LONGBLOB,BLOB,BINARY,VARBINARY,BIT |
|
|
160
|
+
| String | CHAR,VARCHAR,TINYTEXT,MEDIUMTEXT,LONGTEXT,TEXT,ENUM,SET,DECIMAL,TIME |
|
|
161
|
+
| Object 或 Array | JSON |
|
|
160
162
|
|
|
161
163
|
对于可空字段,可以在 ts 里也定义为可空:
|
|
162
164
|
|
|
@@ -303,6 +305,108 @@ await manager.modify(`update user set nickname='无名' where nickname='佚名'`
|
|
|
303
305
|
| query | 自定义 sql 查询,返回记录列表,支持预编译 sql |
|
|
304
306
|
| modify | 执行自定义 sql,返回操作记录数 ,支持预编译 sql |
|
|
305
307
|
|
|
308
|
+
### json 类型
|
|
309
|
+
|
|
310
|
+
0.2.0 版本开始增加了对 JSON 类型的有限支持,可以正常插入和查询,过滤条件也部分支持了 mysql 的 json 相关函数。
|
|
311
|
+
相比使用字符类型来存储 json ,然后在程序里反序列化解析,使用 json 格式要方便很多,开发更高效。
|
|
312
|
+
下面是一个完整的例子。
|
|
313
|
+
|
|
314
|
+
数据库建表语句,字段的类型设置为 json 。
|
|
315
|
+
|
|
316
|
+
```sql
|
|
317
|
+
CREATE TABLE
|
|
318
|
+
question (
|
|
319
|
+
id VARCHAR(32) PRIMARY KEY,
|
|
320
|
+
title VARCHAR(256) NOT NULL COMMENT '标题',
|
|
321
|
+
options json NOT NULL COMMENT '选项列表,json 数组',
|
|
322
|
+
question_setter json NOT NULL COMMENT '出题人信息,json 对象',
|
|
323
|
+
create_at BIGINT UNSIGNED NOT NULL COMMENT '创建时间',
|
|
324
|
+
update_at BIGINT UNSIGNED NOT NULL COMMENT '更新时间'
|
|
325
|
+
) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '试题';
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
表映射配置,json 类型对应的字段申明为自定义的格式即可。
|
|
329
|
+
|
|
330
|
+
```ts
|
|
331
|
+
// 选项
|
|
332
|
+
export interface QuesOption {
|
|
333
|
+
title: string
|
|
334
|
+
correct?: boolean
|
|
335
|
+
}
|
|
336
|
+
// 出题人
|
|
337
|
+
export interface QuestionSetter {
|
|
338
|
+
id: string
|
|
339
|
+
name: string
|
|
340
|
+
}
|
|
341
|
+
// 试题
|
|
342
|
+
export interface Question {
|
|
343
|
+
id: string
|
|
344
|
+
title: string
|
|
345
|
+
// 选项
|
|
346
|
+
options: QuesOption[]
|
|
347
|
+
// 出题人
|
|
348
|
+
question_setter: QuestionSetter
|
|
349
|
+
create_at?: number
|
|
350
|
+
update_at?: number
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export const tableQuestion: Table<Question> = {
|
|
354
|
+
tableName: 'question',
|
|
355
|
+
id: 'id',
|
|
356
|
+
columns: ['title', 'options', 'question_setter'],
|
|
357
|
+
createdDate: {
|
|
358
|
+
type: 'number',
|
|
359
|
+
column: 'create_at'
|
|
360
|
+
},
|
|
361
|
+
updatedDate: {
|
|
362
|
+
type: 'number',
|
|
363
|
+
column: 'update_at'
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
常用的方法,使用起来没有任何区别,json 按字段定义的格式传递数据即可。
|
|
369
|
+
|
|
370
|
+
```ts
|
|
371
|
+
await getMysqlManager().insert(tableQuestion, {
|
|
372
|
+
id: '003',
|
|
373
|
+
title: '下面哪个类型是 Mysql 不支持的',
|
|
374
|
+
options: [
|
|
375
|
+
{ title: 'TINYINT' },
|
|
376
|
+
{ title: 'BOOLEAN', correct: true },
|
|
377
|
+
{ title: 'CHAR' },
|
|
378
|
+
{ title: 'TEXT' }
|
|
379
|
+
],
|
|
380
|
+
question_setter: { id: 'x333', name: '小李老师' }
|
|
381
|
+
})
|
|
382
|
+
// 查询到的数据是完整的,不需要再做任何处理,相应的 json 字段就是对应的类型
|
|
383
|
+
const q1 = await getMysqlManager().findById(tableQuestion, '003')
|
|
384
|
+
q1.question_setter.name // 小李老师
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
查询条件支持 json_extract 和 json_length,凡是支持查询条件的地方都可以使用,
|
|
388
|
+
使用时不能再传递列名,取而代之的是一个元组。
|
|
389
|
+
|
|
390
|
+
```ts
|
|
391
|
+
await mananger.findFirst(tableQuestion, c =>
|
|
392
|
+
// 查询 question_setter 字段下的属性 id 为 x333 的记录
|
|
393
|
+
c.eq(['json_extract', 'question_setter', '$.id'], 'x333')
|
|
394
|
+
)
|
|
395
|
+
await mananger.findFirst(tableQuestion, c =>
|
|
396
|
+
// 查询 options 字段中第一个元素的 title 属性为 地球 的记录
|
|
397
|
+
c.eq(['json_extract', 'options', '$[0].title'], '地球')
|
|
398
|
+
)
|
|
399
|
+
await mananger.find({
|
|
400
|
+
table: tableQuestion,
|
|
401
|
+
// 查询 options 字段的元素数量大于等于 5 的记录,也就是查询选项多于5个的试题
|
|
402
|
+
criteria: c => c.gte(['json_length', 'options'], 5)
|
|
403
|
+
})
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
json_extract 和 json_length 查询都需要传递元组,第一个参数就是查询的类型,第二个参数是字段名称,
|
|
407
|
+
json_extract 还有第三个参数是属性路径。属性路径的格式和 js 获取属性的语法是一样的,只是用 $ 来指代字段的值。
|
|
408
|
+
|
|
409
|
+
|
|
306
410
|
### 预编译 sql
|
|
307
411
|
|
|
308
412
|
使用 query 或 midify 方法传入自定义 sql 时,sql 是支持预编译的,参数值使用 ? (问号)来占位,表名和
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wok-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"packageManager": "pnpm@8.9.0",
|
|
5
5
|
"description": "一个基于 NodeJs 和 TypeScript 的后端框架,轻量级、克制、简洁。A lightweight, restrained, and concise backend framework based on Node.js and TypeScript.",
|
|
6
6
|
"scripts": {
|
|
@@ -2,6 +2,14 @@ export interface MysqlQuery {
|
|
|
2
2
|
sql: string;
|
|
3
3
|
values: any[];
|
|
4
4
|
}
|
|
5
|
+
/**
|
|
6
|
+
* mysql 查询条件中的键,左侧表达式,可以是提取信息的表达式,也可以直接是列名
|
|
7
|
+
*
|
|
8
|
+
* keyof T 列名,直接用列的值来比较
|
|
9
|
+
* ['json_extract', keyof T, string] 使用 json_extract 函数提取 json 信息,第二个参数是列名,最后一个参数是表达式(如:'$.name')
|
|
10
|
+
* ['json_length',keyof T] 使用 json_length 函数提取 json 数组的元素数量
|
|
11
|
+
*/
|
|
12
|
+
export type MysqlCriteriaKey<T> = keyof T | ['json_extract', keyof T, string] | ['json_length', keyof T];
|
|
5
13
|
/**
|
|
6
14
|
* mysql 查询条件( query criterion ),默认查询条件都是并且关系(and), 部分方法会有例外,在使用的时候请注意方法说明。
|
|
7
15
|
*
|
|
@@ -17,67 +25,67 @@ export declare class MysqlCriteria<T> {
|
|
|
17
25
|
* @param column
|
|
18
26
|
* @param value
|
|
19
27
|
*/
|
|
20
|
-
eq(column:
|
|
28
|
+
eq(column: MysqlCriteriaKey<T>, value: any): this;
|
|
21
29
|
/**
|
|
22
30
|
* 不等于,注意不相等不能走索引,谨慎使用
|
|
23
31
|
* @param column
|
|
24
32
|
* @param value
|
|
25
33
|
*/
|
|
26
|
-
neq(column:
|
|
34
|
+
neq(column: MysqlCriteriaKey<T>, value: any): this;
|
|
27
35
|
/**
|
|
28
36
|
* like
|
|
29
37
|
* @param column
|
|
30
38
|
* @param value
|
|
31
39
|
* @returns
|
|
32
40
|
*/
|
|
33
|
-
like(column:
|
|
41
|
+
like(column: MysqlCriteriaKey<T>, value: string): this;
|
|
34
42
|
/**
|
|
35
43
|
* not like
|
|
36
44
|
* @param column
|
|
37
45
|
* @param value
|
|
38
46
|
* @returns
|
|
39
47
|
*/
|
|
40
|
-
notLike(column:
|
|
48
|
+
notLike(column: MysqlCriteriaKey<T>, value: string): this;
|
|
41
49
|
/**
|
|
42
50
|
* BETWEEN x and y
|
|
43
51
|
*/
|
|
44
|
-
between(column:
|
|
52
|
+
between(column: MysqlCriteriaKey<T>, min: number, max: number): this;
|
|
45
53
|
/**
|
|
46
54
|
* 大于
|
|
47
55
|
* @param column
|
|
48
56
|
* @param value
|
|
49
57
|
*/
|
|
50
|
-
gt(column:
|
|
58
|
+
gt(column: MysqlCriteriaKey<T>, value: number | Date | string): this;
|
|
51
59
|
/**
|
|
52
60
|
* 大于等于
|
|
53
61
|
* @param column
|
|
54
62
|
* @param value
|
|
55
63
|
*/
|
|
56
|
-
gte(column:
|
|
64
|
+
gte(column: MysqlCriteriaKey<T>, value: number | Date | string): this;
|
|
57
65
|
/**
|
|
58
66
|
* 小于
|
|
59
67
|
* @param column
|
|
60
68
|
* @param value
|
|
61
69
|
*/
|
|
62
|
-
lt(column:
|
|
70
|
+
lt(column: MysqlCriteriaKey<T>, value: number | Date | string): this;
|
|
63
71
|
/**
|
|
64
72
|
* 小于等于
|
|
65
73
|
* @param column
|
|
66
74
|
* @param value
|
|
67
75
|
*/
|
|
68
|
-
lte(column:
|
|
76
|
+
lte(column: MysqlCriteriaKey<T>, value: number | Date | string): this;
|
|
69
77
|
/**
|
|
70
78
|
* in 条件
|
|
71
79
|
* @param column
|
|
72
80
|
* @param values
|
|
73
81
|
*/
|
|
74
|
-
in(column:
|
|
82
|
+
in(column: MysqlCriteriaKey<T>, values: Array<string | number>): this;
|
|
75
83
|
/**
|
|
76
84
|
* not in 条件
|
|
77
85
|
* @param column
|
|
78
86
|
* @param values
|
|
79
87
|
*/
|
|
80
|
-
notIn(column:
|
|
88
|
+
notIn(column: MysqlCriteriaKey<T>, values: Array<string | number>): this;
|
|
81
89
|
/**
|
|
82
90
|
* 嵌入其它的查询条件,与现有的查询条件是或者关系.
|
|
83
91
|
* @param criteria
|
|
@@ -93,13 +101,13 @@ export declare class MysqlCriteria<T> {
|
|
|
93
101
|
* @param field
|
|
94
102
|
* @returns
|
|
95
103
|
*/
|
|
96
|
-
isNull(field:
|
|
104
|
+
isNull(field: MysqlCriteriaKey<T>): this;
|
|
97
105
|
/**
|
|
98
106
|
* 字段非空
|
|
99
107
|
* @param field
|
|
100
108
|
* @returns
|
|
101
109
|
*/
|
|
102
|
-
isNotNull(field:
|
|
110
|
+
isNotNull(field: MysqlCriteriaKey<T>): this;
|
|
103
111
|
/**
|
|
104
112
|
* 判定是否空,未设置条件.
|
|
105
113
|
* @returns
|