@axiosleo/orm-mysql 0.3.0 → 0.4.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/.eslintrc +1 -1
- package/README.md +22 -1
- package/index.d.ts +16 -2
- package/index.js +4 -0
- package/package.json +1 -1
- package/runtimes/hook.js +104 -0
- package/runtimes/test.js +24 -20
- package/src/builder.js +65 -30
- package/src/hook.js +67 -0
- package/src/operator.js +23 -10
- package/src/query.js +1 -0
package/.eslintrc
CHANGED
package/README.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# @axiosleo/orm-mysql
|
|
2
2
|
|
|
3
|
+
[](https://npmjs.org/package/@axiosleo/orm-mysql)
|
|
4
|
+
[](https://npmjs.org/package/@axiosleo/orm-mysql)
|
|
5
|
+
[](LICENSE)
|
|
6
|
+
[](https://app.fossa.com/projects/git%2Bgithub.com%2FAxiosLeo%2Fnode-orm-mysql/refs/branch/master)
|
|
7
|
+
|
|
3
8
|
## Installation
|
|
4
9
|
|
|
5
10
|
```bash
|
|
@@ -46,7 +51,7 @@ query.offset(0); // set offset
|
|
|
46
51
|
let rows = await query.select(); // select
|
|
47
52
|
```
|
|
48
53
|
|
|
49
|
-
### Some Examples
|
|
54
|
+
### Some Query Examples
|
|
50
55
|
|
|
51
56
|
```javascript
|
|
52
57
|
const { createClient, QueryHandler, Query } = require("@axiosleo/orm-mysql");
|
|
@@ -129,6 +134,22 @@ async function subqueryExample() {
|
|
|
129
134
|
}
|
|
130
135
|
```
|
|
131
136
|
|
|
137
|
+
### Hook
|
|
138
|
+
|
|
139
|
+
```javascript
|
|
140
|
+
const { Hook } = require("@axiosleo/orm-mysql");
|
|
141
|
+
|
|
142
|
+
// opt: 'select' | 'find' | 'insert' | 'update' | 'delete' | 'count'
|
|
143
|
+
|
|
144
|
+
Hook.pre(async (options) => {
|
|
145
|
+
debug.log('options', options);
|
|
146
|
+
}, { table: 'table_name', opt: 'insert'});
|
|
147
|
+
|
|
148
|
+
Hook.post(async (options, result) => {
|
|
149
|
+
throw new Error('some error');
|
|
150
|
+
}, { table: 'table_name', opt: 'insert' });
|
|
151
|
+
```
|
|
152
|
+
|
|
132
153
|
## License
|
|
133
154
|
|
|
134
155
|
This project is open-sourced software licensed under the [MIT](LICENSE).
|
package/index.d.ts
CHANGED
|
@@ -30,7 +30,7 @@ export interface OrderByOptions {
|
|
|
30
30
|
export type OperatorType = 'select' | 'find' | 'insert' | 'update' | 'delete' | 'count';
|
|
31
31
|
|
|
32
32
|
export interface JoinOption {
|
|
33
|
-
table: string;
|
|
33
|
+
table: string | Query;
|
|
34
34
|
table_alias?: string;
|
|
35
35
|
self_column: string;
|
|
36
36
|
foreign_column: string;
|
|
@@ -90,6 +90,8 @@ export declare class Query {
|
|
|
90
90
|
join(opt: JoinOption): this;
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
export type QueryResult = any | undefined | RowDataPacket[] | RowDataPacket | OkPacket;
|
|
94
|
+
|
|
93
95
|
export declare class QueryOperator extends Query {
|
|
94
96
|
conn: Connection;
|
|
95
97
|
options: QueryOperatorOptions
|
|
@@ -98,7 +100,7 @@ export declare class QueryOperator extends Query {
|
|
|
98
100
|
|
|
99
101
|
buildSql(operator: OperatorType): { sql: string, values: any[] };
|
|
100
102
|
|
|
101
|
-
exec(): Promise<
|
|
103
|
+
exec(): Promise<QueryResult>;
|
|
102
104
|
|
|
103
105
|
select<T>(): Promise<T[]>;
|
|
104
106
|
|
|
@@ -128,3 +130,15 @@ export declare class QueryHandler {
|
|
|
128
130
|
export function createClient(options: ConnectionOptions, name?: string | null | undefined): Connection;
|
|
129
131
|
|
|
130
132
|
export function getClient(name: string): Connection;
|
|
133
|
+
|
|
134
|
+
export declare class Hook {
|
|
135
|
+
static pre: (
|
|
136
|
+
callback: (options: QueryOperatorOptions) => void,
|
|
137
|
+
option: { table?: string, opt?: OperatorType }
|
|
138
|
+
) => string;
|
|
139
|
+
|
|
140
|
+
static post: (
|
|
141
|
+
callback: (options: QueryOperatorOptions, result: QueryResult | Error) => void,
|
|
142
|
+
option: { table?: string, opt?: OperatorType }
|
|
143
|
+
) => string;
|
|
144
|
+
}
|
package/index.js
CHANGED
package/package.json
CHANGED
package/runtimes/hook.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const EventEmitter = require('events');
|
|
5
|
+
const { debug } = require('@axiosleo/cli-tool');
|
|
6
|
+
const events = {}; // event tree
|
|
7
|
+
const hook = new EventEmitter();
|
|
8
|
+
|
|
9
|
+
const pushEvent = ({ label, table, opt, callback }) => {
|
|
10
|
+
label = label || '*';
|
|
11
|
+
if (!events[label]) {
|
|
12
|
+
events[label] = {};
|
|
13
|
+
}
|
|
14
|
+
table = table || '*';
|
|
15
|
+
if (!events[label][table]) {
|
|
16
|
+
events[label][table] = {};
|
|
17
|
+
}
|
|
18
|
+
opt = opt || '*';
|
|
19
|
+
if (!events[label][table][opt]) {
|
|
20
|
+
events[label][table][opt] = 0;
|
|
21
|
+
}
|
|
22
|
+
events[label][table][opt]++;
|
|
23
|
+
hook.on(`${label}::${table}::${opt}`, callback);
|
|
24
|
+
return { label, table, opt, callback };
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const eventRecur = (curr, trace, step, paths, args) => {
|
|
28
|
+
if (step === trace.length) {
|
|
29
|
+
hook.emit(paths.join('::'), ...args);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const t = trace[step];
|
|
33
|
+
if (curr['*']) {
|
|
34
|
+
paths[step] = '*';
|
|
35
|
+
eventRecur(curr[t], trace, step + 1, paths, args);
|
|
36
|
+
}
|
|
37
|
+
if (curr[t]) {
|
|
38
|
+
paths[step] = t;
|
|
39
|
+
eventRecur(curr[t], trace, step + 1, paths, args);
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const handleEvent = (label, table, opt, ...args) => {
|
|
45
|
+
let curr = events;
|
|
46
|
+
let step = 0;
|
|
47
|
+
let trace = [label, table, opt];
|
|
48
|
+
eventRecur(curr, trace, step, [], args);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
pushEvent({
|
|
52
|
+
label: 'before',
|
|
53
|
+
table: 'table1',
|
|
54
|
+
opt: 'insert',
|
|
55
|
+
callback: (...args) => {
|
|
56
|
+
debug.log(args);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
pushEvent({
|
|
60
|
+
table: 'table1',
|
|
61
|
+
opt: 'insert',
|
|
62
|
+
callback: (...args) => {
|
|
63
|
+
debug.log(args);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
pushEvent({
|
|
67
|
+
label: 'before',
|
|
68
|
+
table: 'table1',
|
|
69
|
+
callback: (...args) => {
|
|
70
|
+
debug.log(args);
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
pushEvent({
|
|
74
|
+
label: 'before',
|
|
75
|
+
opt: 'insert',
|
|
76
|
+
callback: (...args) => {
|
|
77
|
+
debug.log(args);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
pushEvent({
|
|
81
|
+
label: 'before',
|
|
82
|
+
callback: (...args) => {
|
|
83
|
+
debug.log(args);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
pushEvent({
|
|
87
|
+
table: 'table1',
|
|
88
|
+
callback: (...args) => {
|
|
89
|
+
debug.log(args);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
pushEvent({
|
|
93
|
+
opt: 'insert',
|
|
94
|
+
callback: (...args) => {
|
|
95
|
+
debug.log(args);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
pushEvent({
|
|
99
|
+
callback: (...args) => {
|
|
100
|
+
debug.log(args);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
debug.log(JSON.stringify(events, null, 2));
|
|
104
|
+
handleEvent('before', 'table1', 'insert', 1, 2, 3);
|
package/runtimes/test.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
1
2
|
'use strict';
|
|
2
3
|
|
|
3
4
|
const dotenv = require('dotenv');
|
|
@@ -9,6 +10,7 @@ const {
|
|
|
9
10
|
QueryHandler,
|
|
10
11
|
// Query
|
|
11
12
|
} = require('../src/operator');
|
|
13
|
+
const { Hook } = require('../index');
|
|
12
14
|
|
|
13
15
|
const conn = mysql.createConnection({
|
|
14
16
|
host: process.env.MYSQL_HOST,
|
|
@@ -19,27 +21,29 @@ const conn = mysql.createConnection({
|
|
|
19
21
|
});
|
|
20
22
|
const hanlder = new QueryHandler(conn);
|
|
21
23
|
|
|
24
|
+
Hook.pre(async (options) => {
|
|
25
|
+
debug.log('options', options);
|
|
26
|
+
}, {
|
|
27
|
+
table: 'test',
|
|
28
|
+
opt: 'insert'
|
|
29
|
+
});
|
|
30
|
+
Hook.postInsert(async (options, result) => {
|
|
31
|
+
throw new Error('some error');
|
|
32
|
+
}, { table: 'test', opt: 'insert' });
|
|
33
|
+
|
|
22
34
|
const test = async () => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
table: 'meta_items',
|
|
36
|
-
table_alias: 'mi_c',
|
|
37
|
-
self_column: 'mir.item_child',
|
|
38
|
-
foreign_column: 'mi_c.id',
|
|
39
|
-
}).buildSql('select');
|
|
40
|
-
const result = await query.select();
|
|
41
|
-
debug.halt(res, result);
|
|
35
|
+
console.time('query');
|
|
36
|
+
const query = hanlder.table('test');
|
|
37
|
+
const result = await query.insert({
|
|
38
|
+
name: 'test',
|
|
39
|
+
item_code: '178eb48aa207a59ef8e3cb6944b5ed35'
|
|
40
|
+
});
|
|
41
|
+
await hanlder.table('test')
|
|
42
|
+
.where('name', 'test')
|
|
43
|
+
.where('item_code', '178eb48aa207a59ef8e3cb6944b5ed35')
|
|
44
|
+
.delete();
|
|
45
|
+
console.timeEnd('query');
|
|
46
|
+
debug.halt(result);
|
|
42
47
|
};
|
|
43
48
|
|
|
44
49
|
test();
|
|
45
|
-
|
package/src/builder.js
CHANGED
|
@@ -3,10 +3,21 @@
|
|
|
3
3
|
const Query = require('./query');
|
|
4
4
|
const is = require('@axiosleo/cli-tool/src/helper/is');
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* @param {array} arr
|
|
8
|
+
* @param {string} res
|
|
9
|
+
*/
|
|
10
|
+
const emit = (arr, res) => {
|
|
11
|
+
if (res) {
|
|
12
|
+
arr.push(res);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
|
|
6
16
|
class Builder {
|
|
7
17
|
constructor(options) {
|
|
8
18
|
let sql = '';
|
|
9
19
|
this.values = [];
|
|
20
|
+
let tmp = [];
|
|
10
21
|
switch (options.operator) {
|
|
11
22
|
case 'find': {
|
|
12
23
|
options.pageLimit = 1;
|
|
@@ -14,50 +25,56 @@ class Builder {
|
|
|
14
25
|
}
|
|
15
26
|
// eslint-disable-next-line no-fallthrough
|
|
16
27
|
case 'select': {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (options.groupField.length) {
|
|
23
|
-
sql += ` GROUP BY ${options.groupField.map(f => this._buildFieldKey(f)).join(',')}`;
|
|
24
|
-
sql += this._buildHaving(options.having);
|
|
25
|
-
} else if (options.having && options.having.length) {
|
|
28
|
+
emit(tmp, `SELECT ${options.attrs ? options.attrs.map((a) => this._buildFieldKey(a)).join(',') : '*'} FROM ${this._buildTables(options.tables)}`);
|
|
29
|
+
emit(tmp, this._buildJoins(options.joins));
|
|
30
|
+
emit(tmp, this._buildContidion(options.conditions));
|
|
31
|
+
emit(tmp, this._buildOrders(options.orders));
|
|
32
|
+
emit(tmp, this._buldPagenation(options.pageLimit, options.pageOffset));
|
|
33
|
+
if (options.having && options.having.length && !options.groupField.length) {
|
|
26
34
|
throw new Error('having is not allowed without "GROUP BY"');
|
|
27
35
|
}
|
|
36
|
+
emit(tmp, this._buildGroupField(options.groupField));
|
|
37
|
+
emit(tmp, this._buildHaving(options.having));
|
|
38
|
+
sql = tmp.join(' ');
|
|
28
39
|
break;
|
|
29
40
|
}
|
|
30
41
|
case 'insert': {
|
|
31
42
|
const fields = this._buildValues(options.data);
|
|
32
|
-
|
|
43
|
+
emit(tmp, `INSERT INTO ${this._buildTables(options.tables)}(${fields.map((f) => `\`${f}\``).join(',')})`);
|
|
44
|
+
emit(tmp, `VALUES (${fields.map((f) => '?').join(',')})`);
|
|
45
|
+
sql = tmp.join(' ');
|
|
33
46
|
break;
|
|
34
47
|
}
|
|
35
48
|
case 'update': {
|
|
36
49
|
const fields = this._buildValues(options.data);
|
|
37
|
-
|
|
50
|
+
emit(tmp, `UPDATE ${this._buildTables(options.tables)}`);
|
|
51
|
+
emit(tmp, `SET ${fields.map((f) => `\`${f}\` = ?`).join(',')}`);
|
|
38
52
|
if (!options.conditions.length) {
|
|
39
53
|
throw new Error('At least one condition is required for update operation');
|
|
40
54
|
}
|
|
41
|
-
|
|
55
|
+
emit(tmp, this._buildContidion(options.conditions));
|
|
56
|
+
sql = tmp.join(' ');
|
|
42
57
|
break;
|
|
43
58
|
}
|
|
44
59
|
case 'delete': {
|
|
45
|
-
|
|
60
|
+
emit(tmp, `DELETE FROM ${this._buildTables(options.tables)}`);
|
|
46
61
|
if (!options.conditions.length) {
|
|
47
62
|
throw new Error('At least one where condition is required for delete operation');
|
|
48
63
|
}
|
|
49
|
-
|
|
64
|
+
emit(tmp, this._buildContidion(options.conditions));
|
|
65
|
+
sql = tmp.join(' ');
|
|
50
66
|
break;
|
|
51
67
|
}
|
|
52
68
|
case 'count': {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
sql += this._buildHaving(options.having);
|
|
58
|
-
} else if (options.having && options.having.length) {
|
|
69
|
+
emit(tmp, `SELECT COUNT(*) AS count FROM ${this._buildTables(options.tables)}`);
|
|
70
|
+
emit(tmp, this._buildJoins(options.joins));
|
|
71
|
+
emit(tmp, this._buildContidion(options.conditions));
|
|
72
|
+
if (options.having && options.having.length && !options.groupField.length) {
|
|
59
73
|
throw new Error('having is not allowed without "GROUP BY"');
|
|
60
74
|
}
|
|
75
|
+
emit(tmp, this._buildGroupField(options.groupField));
|
|
76
|
+
emit(tmp, this._buildHaving(options.having));
|
|
77
|
+
sql = tmp.join(' ');
|
|
61
78
|
break;
|
|
62
79
|
}
|
|
63
80
|
default:
|
|
@@ -67,16 +84,31 @@ class Builder {
|
|
|
67
84
|
this.sql = sql;
|
|
68
85
|
}
|
|
69
86
|
|
|
87
|
+
_buildGroupField(groupFields = []) {
|
|
88
|
+
if (!groupFields || !groupFields.length) {
|
|
89
|
+
return '';
|
|
90
|
+
}
|
|
91
|
+
return `GROUP BY ${groupFields.map(f => this._buildFieldKey(f)).join(',')}`;
|
|
92
|
+
}
|
|
93
|
+
|
|
70
94
|
_buildHaving(having) {
|
|
71
|
-
if (!having.length) {
|
|
95
|
+
if (!having || !having.length) {
|
|
72
96
|
return '';
|
|
73
97
|
}
|
|
74
|
-
return this._buildContidion(having, '
|
|
98
|
+
return this._buildContidion(having, 'HAVING ');
|
|
75
99
|
}
|
|
76
100
|
|
|
77
101
|
_buildJoins(joins = []) {
|
|
78
102
|
return joins.map((j) => {
|
|
79
103
|
let { table, alias, self_column, foreign_column, join_type } = j;
|
|
104
|
+
if (table instanceof Query) {
|
|
105
|
+
if (!alias) {
|
|
106
|
+
throw new Error('Alias is required for subquery');
|
|
107
|
+
}
|
|
108
|
+
const builder = new Builder(table.options);
|
|
109
|
+
this.values = this.values.concat(builder.values);
|
|
110
|
+
table = `(${builder.sql})`;
|
|
111
|
+
}
|
|
80
112
|
if (alias) {
|
|
81
113
|
table = `\`${table}\` AS \`${alias}\``;
|
|
82
114
|
} else {
|
|
@@ -85,13 +117,13 @@ class Builder {
|
|
|
85
117
|
let sql = '';
|
|
86
118
|
switch (join_type) {
|
|
87
119
|
case 'left':
|
|
88
|
-
sql = '
|
|
120
|
+
sql = 'LEFT JOIN ';
|
|
89
121
|
break;
|
|
90
122
|
case 'right':
|
|
91
|
-
sql = '
|
|
123
|
+
sql = 'RIGHT JOIN ';
|
|
92
124
|
break;
|
|
93
125
|
default:
|
|
94
|
-
sql = '
|
|
126
|
+
sql = 'INNER JOIN ';
|
|
95
127
|
break;
|
|
96
128
|
}
|
|
97
129
|
sql += `${table} ON ${this._buildFieldWithTableName(self_column)} = ${this._buildFieldWithTableName(foreign_column)}`;
|
|
@@ -100,14 +132,17 @@ class Builder {
|
|
|
100
132
|
}
|
|
101
133
|
|
|
102
134
|
_buildOrders(orders = []) {
|
|
103
|
-
|
|
104
|
-
return
|
|
135
|
+
if (!orders || !orders.length) {
|
|
136
|
+
return '';
|
|
137
|
+
}
|
|
138
|
+
const sql = 'ORDER BY ' + orders.map((o) => {
|
|
139
|
+
return `${this._buildFieldKey(o.sortField)} ${o.sortOrder}`;
|
|
105
140
|
}).join(',');
|
|
106
141
|
return sql;
|
|
107
142
|
}
|
|
108
143
|
|
|
109
144
|
_buildTables(tables) {
|
|
110
|
-
if (!tables.length) {
|
|
145
|
+
if (!tables || !tables.length) {
|
|
111
146
|
throw new Error('At least one table is required');
|
|
112
147
|
}
|
|
113
148
|
return tables.map((t) => {
|
|
@@ -155,10 +190,10 @@ class Builder {
|
|
|
155
190
|
}
|
|
156
191
|
|
|
157
192
|
_buildContidion(conditions, prefix) {
|
|
158
|
-
if (!conditions.length) {
|
|
193
|
+
if (!conditions || !conditions.length) {
|
|
159
194
|
return '';
|
|
160
195
|
}
|
|
161
|
-
let sql = typeof prefix === 'undefined' ? '
|
|
196
|
+
let sql = typeof prefix === 'undefined' ? 'WHERE ' : prefix;
|
|
162
197
|
if (conditions.length) {
|
|
163
198
|
sql += `${conditions.map((c) => {
|
|
164
199
|
if (c.key === null && c.value === null) {
|
package/src/hook.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const EventEmitter = require('events');
|
|
4
|
+
|
|
5
|
+
const events = {}; // event tree
|
|
6
|
+
const hook = new EventEmitter();
|
|
7
|
+
|
|
8
|
+
const pushEvent = ({ label, table, opt, callback }) => {
|
|
9
|
+
label = label || '*';
|
|
10
|
+
if (!events[label]) {
|
|
11
|
+
events[label] = {};
|
|
12
|
+
}
|
|
13
|
+
table = table || '*';
|
|
14
|
+
if (!events[label][table]) {
|
|
15
|
+
events[label][table] = {};
|
|
16
|
+
}
|
|
17
|
+
opt = opt || '*';
|
|
18
|
+
if (!events[label][table][opt]) {
|
|
19
|
+
events[label][table][opt] = 0;
|
|
20
|
+
}
|
|
21
|
+
events[label][table][opt]++;
|
|
22
|
+
hook.on(`${label}::${table}::${opt}`, callback);
|
|
23
|
+
return { label, table, opt, callback };
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const eventRecur = (curr, trace, step, paths, args) => {
|
|
27
|
+
if (step === trace.length) {
|
|
28
|
+
hook.emit(paths.join('::'), ...args);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const t = trace[step];
|
|
32
|
+
if (curr['*']) {
|
|
33
|
+
paths[step] = '*';
|
|
34
|
+
eventRecur(curr[t], trace, step + 1, paths, args);
|
|
35
|
+
}
|
|
36
|
+
if (curr[t]) {
|
|
37
|
+
paths[step] = t;
|
|
38
|
+
eventRecur(curr[t], trace, step + 1, paths, args);
|
|
39
|
+
}
|
|
40
|
+
return;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const handleEvent = (label, table, opt, ...args) => {
|
|
44
|
+
let curr = events;
|
|
45
|
+
let step = 0;
|
|
46
|
+
let trace = [label, table, opt];
|
|
47
|
+
eventRecur(curr, trace, step, [], args);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
class Hook {
|
|
51
|
+
static pre(callback, { table, opt }) {
|
|
52
|
+
return pushEvent({
|
|
53
|
+
label: 'pre', table, opt, callback
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static post(callback, { table, opt }) {
|
|
58
|
+
return pushEvent({
|
|
59
|
+
label: 'post', table, opt, callback
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
module.exports = {
|
|
65
|
+
Hook,
|
|
66
|
+
handleEvent
|
|
67
|
+
};
|
package/src/operator.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { Builder } = require('./builder');
|
|
4
4
|
const Query = require('./query');
|
|
5
|
+
const { handleEvent } = require('./hook');
|
|
5
6
|
|
|
6
7
|
const query = async (conn, options) => {
|
|
7
8
|
return new Promise((resolve, reject) => {
|
|
@@ -38,18 +39,30 @@ class QueryOperator extends Query {
|
|
|
38
39
|
const options = {
|
|
39
40
|
sql, values
|
|
40
41
|
};
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
const from = this.options.tables.map(t => t.tableName).join(',');
|
|
43
|
+
handleEvent('pre', from, this.options.operator, this.options);
|
|
44
|
+
let res;
|
|
45
|
+
try {
|
|
46
|
+
switch (this.options.operator) {
|
|
47
|
+
case 'find': {
|
|
48
|
+
const tmp = await query(this.conn, options);
|
|
49
|
+
res = tmp[0];
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
case 'count': {
|
|
53
|
+
const [tmp] = await query(this.conn, options);
|
|
54
|
+
res = tmp.count;
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
default:
|
|
58
|
+
res = await query(this.conn, options);
|
|
49
59
|
}
|
|
50
|
-
|
|
51
|
-
|
|
60
|
+
handleEvent('post', from, this.options.operator, this.options, res);
|
|
61
|
+
} catch (err) {
|
|
62
|
+
handleEvent('post', from, this.options.operator, this.options, err);
|
|
63
|
+
throw err;
|
|
52
64
|
}
|
|
65
|
+
return res;
|
|
53
66
|
}
|
|
54
67
|
|
|
55
68
|
async select() {
|
package/src/query.js
CHANGED
|
@@ -119,6 +119,7 @@ class Query {
|
|
|
119
119
|
let lastOpt = this.options.having[this.options.having.length - 1].opt.toUpperCase();
|
|
120
120
|
if (lastOpt !== 'AND' && lastOpt !== 'OR') {
|
|
121
121
|
this.options.having.push({ key: null, opt: 'AND', value: null });
|
|
122
|
+
return this;
|
|
122
123
|
}
|
|
123
124
|
}
|
|
124
125
|
this.options.having.push({ key, opt, value });
|