@axiosleo/orm-mysql 0.3.1 → 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/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 +64 -30
- package/src/hook.js +67 -0
- package/src/operator.js +23 -10
- package/src/query.js +1 -0
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,51 +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
|
-
if (options.groupField.length) {
|
|
57
|
-
sql += ` GROUP BY ${options.groupField.map(f => this._buildFieldKey(f)).join(',')}`;
|
|
58
|
-
sql += this._buildHaving(options.having);
|
|
59
|
-
} 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) {
|
|
60
73
|
throw new Error('having is not allowed without "GROUP BY"');
|
|
61
74
|
}
|
|
75
|
+
emit(tmp, this._buildGroupField(options.groupField));
|
|
76
|
+
emit(tmp, this._buildHaving(options.having));
|
|
77
|
+
sql = tmp.join(' ');
|
|
62
78
|
break;
|
|
63
79
|
}
|
|
64
80
|
default:
|
|
@@ -68,16 +84,31 @@ class Builder {
|
|
|
68
84
|
this.sql = sql;
|
|
69
85
|
}
|
|
70
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
|
+
|
|
71
94
|
_buildHaving(having) {
|
|
72
|
-
if (!having.length) {
|
|
95
|
+
if (!having || !having.length) {
|
|
73
96
|
return '';
|
|
74
97
|
}
|
|
75
|
-
return this._buildContidion(having, '
|
|
98
|
+
return this._buildContidion(having, 'HAVING ');
|
|
76
99
|
}
|
|
77
100
|
|
|
78
101
|
_buildJoins(joins = []) {
|
|
79
102
|
return joins.map((j) => {
|
|
80
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
|
+
}
|
|
81
112
|
if (alias) {
|
|
82
113
|
table = `\`${table}\` AS \`${alias}\``;
|
|
83
114
|
} else {
|
|
@@ -86,13 +117,13 @@ class Builder {
|
|
|
86
117
|
let sql = '';
|
|
87
118
|
switch (join_type) {
|
|
88
119
|
case 'left':
|
|
89
|
-
sql = '
|
|
120
|
+
sql = 'LEFT JOIN ';
|
|
90
121
|
break;
|
|
91
122
|
case 'right':
|
|
92
|
-
sql = '
|
|
123
|
+
sql = 'RIGHT JOIN ';
|
|
93
124
|
break;
|
|
94
125
|
default:
|
|
95
|
-
sql = '
|
|
126
|
+
sql = 'INNER JOIN ';
|
|
96
127
|
break;
|
|
97
128
|
}
|
|
98
129
|
sql += `${table} ON ${this._buildFieldWithTableName(self_column)} = ${this._buildFieldWithTableName(foreign_column)}`;
|
|
@@ -101,14 +132,17 @@ class Builder {
|
|
|
101
132
|
}
|
|
102
133
|
|
|
103
134
|
_buildOrders(orders = []) {
|
|
104
|
-
|
|
135
|
+
if (!orders || !orders.length) {
|
|
136
|
+
return '';
|
|
137
|
+
}
|
|
138
|
+
const sql = 'ORDER BY ' + orders.map((o) => {
|
|
105
139
|
return `${this._buildFieldKey(o.sortField)} ${o.sortOrder}`;
|
|
106
140
|
}).join(',');
|
|
107
141
|
return sql;
|
|
108
142
|
}
|
|
109
143
|
|
|
110
144
|
_buildTables(tables) {
|
|
111
|
-
if (!tables.length) {
|
|
145
|
+
if (!tables || !tables.length) {
|
|
112
146
|
throw new Error('At least one table is required');
|
|
113
147
|
}
|
|
114
148
|
return tables.map((t) => {
|
|
@@ -156,10 +190,10 @@ class Builder {
|
|
|
156
190
|
}
|
|
157
191
|
|
|
158
192
|
_buildContidion(conditions, prefix) {
|
|
159
|
-
if (!conditions.length) {
|
|
193
|
+
if (!conditions || !conditions.length) {
|
|
160
194
|
return '';
|
|
161
195
|
}
|
|
162
|
-
let sql = typeof prefix === 'undefined' ? '
|
|
196
|
+
let sql = typeof prefix === 'undefined' ? 'WHERE ' : prefix;
|
|
163
197
|
if (conditions.length) {
|
|
164
198
|
sql += `${conditions.map((c) => {
|
|
165
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 });
|