@axiosleo/orm-mysql 0.7.0 → 0.8.1

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 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 QueryOperatorOptions = {
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[];
@@ -106,7 +111,7 @@ export declare class QueryOperator extends Query {
106
111
  conn: Connection;
107
112
  options: QueryOperatorOptions
108
113
 
109
- constructor(conn: Connection);
114
+ constructor(conn: Connection, opt?: QueryOperatorBaseOptions);
110
115
 
111
116
  buildSql(operator: OperatorType): { sql: string, values: any[] };
112
117
 
@@ -132,8 +137,9 @@ export declare class QueryOperator extends Query {
132
137
 
133
138
  export declare class QueryHandler {
134
139
  conn: Connection;
140
+ options: QueryOperatorBaseOptions;
135
141
 
136
- constructor(conn: Connection);
142
+ constructor(conn: Connection, options?: QueryOperatorBaseOptions);
137
143
 
138
144
  /**
139
145
  * select table
@@ -241,3 +247,9 @@ export declare class Hook {
241
247
  ...args: any[]
242
248
  ) => void
243
249
  }
250
+
251
+ export declare class Builder {
252
+ sql: string;
253
+ values: any[];
254
+ constructor(options: QueryOperatorOptions);
255
+ }
package/index.js CHANGED
@@ -19,9 +19,11 @@ const {
19
19
  } = require('./src/client');
20
20
 
21
21
  const Hook = require('./src/hook');
22
+ const { Builder } = require('./src/builder');
22
23
 
23
24
  module.exports = {
24
25
  Hook,
26
+ Builder,
25
27
 
26
28
  Query,
27
29
  QueryHandler,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axiosleo/orm-mysql",
3
- "version": "0.7.0",
3
+ "version": "0.8.1",
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": "^15.12.1",
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/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, transaction) => {
8
- return new Promise((resolve, reject) => {
9
- if (transaction) {
10
- conn.execute(options)
11
- .then((res) => resolve(res))
12
- .catch((err) => reject(err));
13
- } else {
14
- conn.query(options, (err, result) => {
15
- if (err) {
16
- reject(err);
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
- resolve(result);
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, options, this.options.transaction);
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, options, this.options.transaction);
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, options, this.options.transaction);
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.options = options;
120
144
  }
121
145
 
122
- async query(options) {
123
- return new Promise((resolve, reject) => {
124
- this.conn.query(options, (err, result) => {
125
- if (err) {
126
- reject(err);
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.options)).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: [],
@@ -136,7 +138,6 @@ class Query {
136
138
  let lastOpt = this.options.having[this.options.having.length - 1].opt.toUpperCase();
137
139
  if (lastOpt !== 'AND' && lastOpt !== 'OR') {
138
140
  this.options.having.push({ key: null, opt: 'AND', value: null });
139
- return this;
140
141
  }
141
142
  }
142
143
  this.options.having.push({ key, opt, value });
@@ -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 = {}) {