@axiosleo/orm-mysql 0.6.3 → 0.8.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.md +33 -0
- package/index.d.ts +17 -3
- package/index.js +2 -0
- package/package.json +2 -2
- package/src/builder.js +6 -0
- package/src/operator.js +52 -33
- package/src/query.js +14 -1
- package/src/transaction.js +13 -2
package/README.md
CHANGED
|
@@ -195,6 +195,39 @@ try {
|
|
|
195
195
|
}
|
|
196
196
|
```
|
|
197
197
|
|
|
198
|
+
### Custom query driver
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
const {
|
|
202
|
+
createClient,
|
|
203
|
+
QueryHandler,
|
|
204
|
+
Query,
|
|
205
|
+
Builder
|
|
206
|
+
} = require("@axiosleo/orm-mysql");
|
|
207
|
+
|
|
208
|
+
const conn = createClient({
|
|
209
|
+
host: process.env.MYSQL_HOST,
|
|
210
|
+
port: process.env.MYSQL_PORT,
|
|
211
|
+
user: process.env.MYSQL_USER,
|
|
212
|
+
password: process.env.MYSQL_PASS,
|
|
213
|
+
database: process.env.MYSQL_DB,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
const hanlder = new QueryHandler(conn, {
|
|
217
|
+
driver: 'custom',
|
|
218
|
+
query_handler: (con, options) => {
|
|
219
|
+
const builder = new Builder(options);
|
|
220
|
+
return new Promise((resolve, reject) => {
|
|
221
|
+
if (options.operator === 'select') {
|
|
222
|
+
resolve([{ a: 1, b: 2 }]);
|
|
223
|
+
} else {
|
|
224
|
+
reject(new Error('some error'));
|
|
225
|
+
}
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
```
|
|
230
|
+
|
|
198
231
|
## License
|
|
199
232
|
|
|
200
233
|
This project is open-sourced software licensed under the [MIT](LICENSE).
|
package/index.d.ts
CHANGED
|
@@ -48,7 +48,12 @@ export interface TableOption {
|
|
|
48
48
|
alias: string | null;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
export type
|
|
51
|
+
export type QueryOperatorBaseOptions = {
|
|
52
|
+
driver?: string | 'mysql';
|
|
53
|
+
query_handler?: QueryHandler;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type QueryOperatorOptions = QueryOperatorBaseOptions & {
|
|
52
57
|
conditions: WhereOptions[];
|
|
53
58
|
attrs?: string[] | null;
|
|
54
59
|
orders: OrderByOptions[];
|
|
@@ -79,6 +84,8 @@ export declare class Query {
|
|
|
79
84
|
|
|
80
85
|
whereConditions(...condition: WhereOptions[]): this;
|
|
81
86
|
|
|
87
|
+
groupWhere(...condition: WhereOptions[]): this;
|
|
88
|
+
|
|
82
89
|
orWhere(key: string | null, opt: OptType, value: ConditionValueType | WhereOptions[]): this;
|
|
83
90
|
|
|
84
91
|
andWhere(key: string | null, opt: OptType, value: ConditionValueType | WhereOptions[]): this;
|
|
@@ -104,7 +111,7 @@ export declare class QueryOperator extends Query {
|
|
|
104
111
|
conn: Connection;
|
|
105
112
|
options: QueryOperatorOptions
|
|
106
113
|
|
|
107
|
-
constructor(conn: Connection);
|
|
114
|
+
constructor(conn: Connection, opt?: QueryOperatorBaseOptions);
|
|
108
115
|
|
|
109
116
|
buildSql(operator: OperatorType): { sql: string, values: any[] };
|
|
110
117
|
|
|
@@ -130,8 +137,9 @@ export declare class QueryOperator extends Query {
|
|
|
130
137
|
|
|
131
138
|
export declare class QueryHandler {
|
|
132
139
|
conn: Connection;
|
|
140
|
+
options: QueryOperatorBaseOptions;
|
|
133
141
|
|
|
134
|
-
constructor(conn: Connection);
|
|
142
|
+
constructor(conn: Connection, options?: QueryOperatorBaseOptions);
|
|
135
143
|
|
|
136
144
|
/**
|
|
137
145
|
* select table
|
|
@@ -239,3 +247,9 @@ export declare class Hook {
|
|
|
239
247
|
...args: any[]
|
|
240
248
|
) => void
|
|
241
249
|
}
|
|
250
|
+
|
|
251
|
+
export declare class Builder {
|
|
252
|
+
sql: string;
|
|
253
|
+
values: any[];
|
|
254
|
+
constructor(options: QueryOperatorOptions);
|
|
255
|
+
}
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axiosleo/orm-mysql",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "MySQL ORM tool",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mysql",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"url": "https://github.com/AxiosLeo/node-orm-mysql"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@types/node": "^
|
|
31
|
+
"@types/node": "^20.8.3",
|
|
32
32
|
"chai": "^4.2.0",
|
|
33
33
|
"chai-as-promised": "^7.1.1",
|
|
34
34
|
"eslint": "^7.0",
|
package/src/builder.js
CHANGED
|
@@ -216,6 +216,12 @@ class Builder {
|
|
|
216
216
|
let sql = typeof prefix === 'undefined' ? 'WHERE ' : prefix;
|
|
217
217
|
if (conditions.length) {
|
|
218
218
|
sql += `${conditions.map((c) => {
|
|
219
|
+
if (typeof c.key === 'undefined') {
|
|
220
|
+
c.key = null;
|
|
221
|
+
}
|
|
222
|
+
if (typeof c.value === 'undefined') {
|
|
223
|
+
c.value = null;
|
|
224
|
+
}
|
|
219
225
|
if (c.key === null && c.value === null) {
|
|
220
226
|
return ` ${c.opt} `;
|
|
221
227
|
}
|
package/src/operator.js
CHANGED
|
@@ -4,31 +4,59 @@ const { Builder } = require('./builder');
|
|
|
4
4
|
const Query = require('./query');
|
|
5
5
|
const Hook = require('./hook');
|
|
6
6
|
|
|
7
|
-
const query = async (conn, options,
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
const query = async (conn, options, opt = null) => {
|
|
8
|
+
switch (options.driver) {
|
|
9
|
+
case 'mysql': {
|
|
10
|
+
if (opt === null) {
|
|
11
|
+
const builder = new Builder(options);
|
|
12
|
+
opt = {
|
|
13
|
+
sql: builder.sql,
|
|
14
|
+
values: builder.values || [],
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
if (options.transaction) {
|
|
19
|
+
conn.execute(opt)
|
|
20
|
+
.then((res) => resolve(res))
|
|
21
|
+
.catch((err) => reject(err));
|
|
17
22
|
} else {
|
|
18
|
-
|
|
23
|
+
conn.query(opt, (err, result) => {
|
|
24
|
+
if (err) {
|
|
25
|
+
reject(err);
|
|
26
|
+
} else {
|
|
27
|
+
resolve(result);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
19
30
|
}
|
|
20
31
|
});
|
|
21
32
|
}
|
|
22
|
-
|
|
33
|
+
default: {
|
|
34
|
+
const promise = options.query_handler(conn, options, opt);
|
|
35
|
+
if (!(promise instanceof Promise)) {
|
|
36
|
+
throw new Error('query_handler must return a promise');
|
|
37
|
+
}
|
|
38
|
+
return promise;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
23
41
|
};
|
|
24
42
|
|
|
25
43
|
class QueryOperator extends Query {
|
|
26
44
|
/**
|
|
27
45
|
* @param {*} conn
|
|
28
46
|
*/
|
|
29
|
-
constructor(conn = null) {
|
|
47
|
+
constructor(conn = null, options = {}) {
|
|
30
48
|
super(null);
|
|
31
49
|
this.conn = conn;
|
|
50
|
+
this.options.driver = options.driver || 'mysql';
|
|
51
|
+
this.options.query_handler = options.query_handler || null;
|
|
52
|
+
if (this.options.driver !== 'mysql') {
|
|
53
|
+
if (!this.options.query_handler) {
|
|
54
|
+
throw new Error('query_handler is required');
|
|
55
|
+
}
|
|
56
|
+
if (!(this.options.query_handler instanceof Function)) {
|
|
57
|
+
throw new Error('query_handler must be a function');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
32
60
|
}
|
|
33
61
|
|
|
34
62
|
buildSql(operator) {
|
|
@@ -43,28 +71,23 @@ class QueryOperator extends Query {
|
|
|
43
71
|
if (this.conn === null) {
|
|
44
72
|
throw new Error('Connection is null');
|
|
45
73
|
}
|
|
46
|
-
const builder = this.buildSql(this.options.operator);
|
|
47
|
-
const { sql, values } = builder;
|
|
48
|
-
const options = {
|
|
49
|
-
sql, values
|
|
50
|
-
};
|
|
51
74
|
const from = this.options.tables.map(t => t.tableName).join(',');
|
|
52
75
|
Hook.listen({ label: 'pre', table: from, opt: this.options.operator }, this.options);
|
|
53
76
|
let res;
|
|
54
77
|
try {
|
|
55
78
|
switch (this.options.operator) {
|
|
56
79
|
case 'find': {
|
|
57
|
-
const tmp = await query(this.conn,
|
|
80
|
+
const tmp = await query(this.conn, this.options);
|
|
58
81
|
res = tmp[0];
|
|
59
82
|
break;
|
|
60
83
|
}
|
|
61
84
|
case 'count': {
|
|
62
|
-
const [tmp] = await query(this.conn,
|
|
85
|
+
const [tmp] = await query(this.conn, this.options);
|
|
63
86
|
res = tmp.count;
|
|
64
87
|
break;
|
|
65
88
|
}
|
|
66
89
|
default:
|
|
67
|
-
res = await query(this.conn,
|
|
90
|
+
res = await query(this.conn, this.options);
|
|
68
91
|
}
|
|
69
92
|
Hook.listen({ label: 'post', table: from, opt: this.options.operator }, this.options, res);
|
|
70
93
|
} catch (err) {
|
|
@@ -115,24 +138,20 @@ class QueryOperator extends Query {
|
|
|
115
138
|
}
|
|
116
139
|
|
|
117
140
|
class QueryHandler {
|
|
118
|
-
constructor(conn) {
|
|
141
|
+
constructor(conn, options = {}) {
|
|
119
142
|
this.conn = conn;
|
|
143
|
+
this.optinos = options;
|
|
120
144
|
}
|
|
121
145
|
|
|
122
|
-
async query(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
} else {
|
|
128
|
-
resolve(result);
|
|
129
|
-
}
|
|
130
|
-
});
|
|
131
|
-
});
|
|
146
|
+
async query(opt) {
|
|
147
|
+
if (!opt) {
|
|
148
|
+
throw new Error('opt is required');
|
|
149
|
+
}
|
|
150
|
+
return await query(this.conn, this.options, opt);
|
|
132
151
|
}
|
|
133
152
|
|
|
134
153
|
table(table, alias = null) {
|
|
135
|
-
return (new QueryOperator(this.conn)).table(table, alias);
|
|
154
|
+
return (new QueryOperator(this.conn, this.optinos)).table(table, alias);
|
|
136
155
|
}
|
|
137
156
|
|
|
138
157
|
async upsert(tableName, data, condition = {}) {
|
package/src/query.js
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
class Query {
|
|
4
4
|
constructor(operator = 'select') {
|
|
5
5
|
this.options = {
|
|
6
|
+
driver: 'mysql',
|
|
7
|
+
query_handler: null,
|
|
6
8
|
conditions: [],
|
|
7
9
|
orders: [],
|
|
8
10
|
tables: [],
|
|
@@ -69,6 +71,18 @@ class Query {
|
|
|
69
71
|
return this;
|
|
70
72
|
}
|
|
71
73
|
|
|
74
|
+
groupWhere(...conditions) {
|
|
75
|
+
if (!conditions.length) {
|
|
76
|
+
return this;
|
|
77
|
+
}
|
|
78
|
+
const condition = { key: null, opt: 'group', value: [] };
|
|
79
|
+
conditions.forEach((c) => {
|
|
80
|
+
condition.value.push(c);
|
|
81
|
+
});
|
|
82
|
+
this.options.conditions.push(condition);
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
85
|
+
|
|
72
86
|
orWhere(key, opt, value) {
|
|
73
87
|
if (!this.options.conditions.length) {
|
|
74
88
|
throw new Error('At least one where condition is required');
|
|
@@ -124,7 +138,6 @@ class Query {
|
|
|
124
138
|
let lastOpt = this.options.having[this.options.having.length - 1].opt.toUpperCase();
|
|
125
139
|
if (lastOpt !== 'AND' && lastOpt !== 'OR') {
|
|
126
140
|
this.options.having.push({ key: null, opt: 'AND', value: null });
|
|
127
|
-
return this;
|
|
128
141
|
}
|
|
129
142
|
}
|
|
130
143
|
this.options.having.push({ key, opt, value });
|
package/src/transaction.js
CHANGED
|
@@ -15,9 +15,19 @@ class TransactionOperator extends QueryOperator {
|
|
|
15
15
|
/**
|
|
16
16
|
* @param {*} conn
|
|
17
17
|
*/
|
|
18
|
-
constructor(conn) {
|
|
18
|
+
constructor(conn, options) {
|
|
19
19
|
super(conn);
|
|
20
20
|
this.options.transaction = true;
|
|
21
|
+
this.options.driver = options.driver || 'mysql';
|
|
22
|
+
this.options.query_handler = options.query_handler || null;
|
|
23
|
+
if (this.options.driver !== 'mysql') {
|
|
24
|
+
if (!this.options.query_handler) {
|
|
25
|
+
throw new Error('query_handler is required');
|
|
26
|
+
}
|
|
27
|
+
if (!(this.options.query_handler instanceof Function)) {
|
|
28
|
+
throw new Error('query_handler must be a function');
|
|
29
|
+
}
|
|
30
|
+
}
|
|
21
31
|
}
|
|
22
32
|
|
|
23
33
|
/**
|
|
@@ -42,6 +52,7 @@ class TransactionHandler {
|
|
|
42
52
|
if (levels[this.level]) {
|
|
43
53
|
this.level = levels[this.level];
|
|
44
54
|
}
|
|
55
|
+
this.options = options;
|
|
45
56
|
if (!Object.values(levels).includes(this.level)) {
|
|
46
57
|
throw new Error('Invalid transaction level: ' + this.level);
|
|
47
58
|
}
|
|
@@ -79,7 +90,7 @@ class TransactionHandler {
|
|
|
79
90
|
if (!this.isbegin) {
|
|
80
91
|
throw new Error('Transaction is not begin');
|
|
81
92
|
}
|
|
82
|
-
return (new TransactionOperator(this.conn)).table(table, alias);
|
|
93
|
+
return (new TransactionOperator(this.conn, this.options)).table(table, alias);
|
|
83
94
|
}
|
|
84
95
|
|
|
85
96
|
async upsert(tableName, data, condition = {}) {
|