@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 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[];
@@ -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
@@ -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.6.3",
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": "^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/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, 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.optinos = 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.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 });
@@ -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 = {}) {