@axiosleo/orm-mysql 0.0.1 → 0.1.0-alpha.3

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
@@ -1,2 +1,85 @@
1
- # node-orm-mysql
2
- MySQL ORM tool
1
+ # @axiosleo/orm-mysql
2
+
3
+ ## Installation
4
+
5
+ ```bash
6
+ npm install @axiosleo/orm-mysql
7
+ ```
8
+
9
+ ## Usage
10
+
11
+ ```javascript
12
+ const { createClient, QueryHandler } = require('@axiosleo/orm-mysql');
13
+
14
+ const conn = createClient({
15
+ host: process.env.MYSQL_HOST,
16
+ port: process.env.MYSQL_PORT,
17
+ user: process.env.MYSQL_USER,
18
+ password: process.env.MYSQL_PASS,
19
+ database: process.env.MYSQL_DB,
20
+ });
21
+
22
+ const hanlder = new QueryHandler(conn);
23
+
24
+ async function selectExample(){
25
+ const query = handler.table('users'); // init QueryOperator by table name
26
+
27
+ query.attr('id', 'name', 'age'); // set attributes
28
+ query.where('name','Joe'); // set where condition
29
+ query.orWhere('age', '>', 18); // set or where condition
30
+ query.andWhere('age', '<', 30); // set and where condition
31
+ query.orderBy('age', 'desc'); // set order by
32
+ query.limit(10); // set limit
33
+ query.offset(0); // set offset
34
+
35
+ let rows = await query.select(); // select
36
+ }
37
+
38
+ async function findExample(){
39
+ const query = handler.table('users'); // init QueryOperator by table name
40
+
41
+ query.attr('id', 'name', 'age'); // set attributes
42
+ query.where('name','Joe'); // set where condition
43
+ query.orWhere('age', '>', 18); // set or where condition
44
+ query.andWhere('age', '<', 30); // set and where condition
45
+ query.orderBy('age', 'desc'); // set order by
46
+ // query.limit(10); // not supported set limit
47
+ // query.offset(10); // not supported set offset
48
+
49
+ let row = await query.find(); // find single row
50
+ }
51
+
52
+ async function insertExample(){
53
+ const query = handler.table('users');
54
+
55
+ // insert
56
+ let row = await query.insert({
57
+ name: 'Joe',
58
+ age: 18,
59
+ });
60
+ }
61
+
62
+ async function updateExample(){
63
+ const query = handler.table('users');
64
+
65
+ // update
66
+ let row = await query.where('name','Joe').update({
67
+ name: 'Joe',
68
+ age: 18,
69
+ });
70
+ }
71
+
72
+ async function deleteExample(){
73
+ const query = handler.table('users');
74
+
75
+ // delete with conditions
76
+ let result = await query.where('name','Joe').delete();
77
+
78
+ // delete by id
79
+ result = await query.delete(1);
80
+ }
81
+ ```
82
+
83
+ ## License
84
+
85
+ This project is open-sourced software licensed under the [MIT](LICENSE).
package/index.d.ts CHANGED
@@ -6,42 +6,42 @@ import {
6
6
  ConnectionOptions
7
7
  } from 'mysql2';
8
8
 
9
- type Clients = {
9
+ export type Clients = {
10
10
  [key: string]: Connection
11
11
  }
12
12
 
13
- type ConditionValueType = null | string | number | boolean | Date | Array<string | number | boolean | Date>;
13
+ export type ConditionValueType = null | string | number | boolean | Date | Array<string | number | boolean | Date>;
14
14
 
15
- type OptType = '=' | '!=' | '>' | '<' | '>=' | '<=' | 'LIKE'
15
+ export type OptType = '=' | '!=' | '>' | '<' | '>=' | '<=' | 'LIKE'
16
16
  | 'NOT LIKE' | 'IN' | 'NOT IN' | 'BETWEEN' | 'NOT BETWEEN' | 'IS' | 'IS NOT' | 'REGEXP' | 'NOT REGEXP'
17
17
  | 'AND' | 'OR' | 'GROUP' | 'like' | 'not like' | 'in' | 'not in' | 'between' | 'not between' | 'is' | 'is not' | 'regexp' | 'not regexp' | 'group';
18
18
 
19
- interface WhereOptions {
19
+ export interface WhereOptions {
20
20
  key: string | null;
21
21
  opt: OptType;
22
22
  value: ConditionValueType | WhereOptions[];
23
23
  }
24
24
 
25
- interface OrderByOptions {
25
+ export interface OrderByOptions {
26
26
  sortField: string,
27
27
  sortOrder: 'asc' | 'desc'
28
28
  }
29
29
 
30
- type OperatorType = 'select' | 'find' | 'insert' | 'update' | 'delete' | 'count';
30
+ export type OperatorType = 'select' | 'find' | 'insert' | 'update' | 'delete' | 'count';
31
31
 
32
- interface JoinOption {
32
+ export interface JoinOption {
33
33
  table: string;
34
34
  alias: string;
35
35
  on: string;
36
36
  type: 'left' | 'right' | 'inner';
37
37
  }
38
38
 
39
- interface TableOption {
39
+ export interface TableOption {
40
40
  tableName: string;
41
41
  alias: string | null;
42
42
  }
43
43
 
44
- interface QueryOperatorOptions {
44
+ export interface QueryOperatorOptions {
45
45
  sql: string;
46
46
  values: any[];
47
47
  conditions: WhereOptions[];
@@ -70,6 +70,8 @@ export declare class QueryOperator {
70
70
 
71
71
  where(key: string | null, value: ConditionValueType | WhereOptions[], opt?: OptType): this;
72
72
 
73
+ whereObject(obj: Record<string, ConditionValueType>): this;
74
+
73
75
  whereConditions(...condition: WhereOptions[]): this;
74
76
 
75
77
  orWhere(key: string | null, opt: OptType, value: ConditionValueType | WhereOptions[]): this;
@@ -101,6 +103,8 @@ export declare class QueryOperator {
101
103
  insert(data?: any): Promise<OkPacket>;
102
104
 
103
105
  count(): Promise<number>;
106
+
107
+ delete(id?: number): Promise<OkPacket>;
104
108
  }
105
109
 
106
110
  export declare class QueryHandler {
@@ -112,9 +116,9 @@ export declare class QueryHandler {
112
116
 
113
117
  query(options: QueryOptions): Promise<any>;
114
118
 
115
- upsert(tableName: string, obj: any, condition: WhereOptions[]): Promise<OkPacket>;
119
+ upsert(tableName: string, data: any, condition: Record<string, ConditionValueType>): Promise<OkPacket>;
116
120
  }
117
121
 
118
- export function createClient(options: ConnectionOptions): Connection;
122
+ export function createClient(options: ConnectionOptions, name?: string | null | undefined): Connection;
119
123
 
120
124
  export function getClient(name: string): Connection;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axiosleo/orm-mysql",
3
- "version": "0.0.1",
3
+ "version": "0.1.0-alpha.3",
4
4
  "description": "MySQL ORM tool",
5
5
  "keywords": [
6
6
  "mysql",
@@ -0,0 +1,23 @@
1
+ 'use strict';
2
+
3
+ const { debug } = require('@axiosleo/cli-tool');
4
+ const mm = require('mm');
5
+ // const expect = require('chai').expect;
6
+ const mysql = require('mysql2');
7
+ const { QueryHandler } = require('../src/query');
8
+
9
+ mm(mysql, 'createConnection', (options) => {
10
+ return {
11
+
12
+ };
13
+ });
14
+
15
+ const conn = mysql.createConnection({});
16
+ const hanlder = new QueryHandler(conn);
17
+ const query = hanlder.table('meta_items', 'u');
18
+
19
+ // query.attr('UNIX_TIMESTAMP(deleted_at) AS deleted_at');
20
+ query.where('u.meta->$.id', '06fbd857-7006-fee7-259d-fd3ed8f19b35');
21
+ debug.log(query.buildSql('select').sql);
22
+ // expect(query.buildSql('select').sql).to.be.equal('SELECT * FROM `users` AS `u` WHERE `u`.`id` = ?');
23
+
package/src/builder.js CHANGED
@@ -2,15 +2,36 @@
2
2
 
3
3
  const is = require('@axiosleo/cli-tool/src/helper/is');
4
4
 
5
+ const _buildFieldWithTableName = (key) => {
6
+ if (key.indexOf('$') !== -1) {
7
+ return key;
8
+ }
9
+ return key.split('.').map((k) => k.indexOf('`') !== -1 ? k : `\`${k}\``).join('.');
10
+ };
11
+
5
12
  const _buildFieldKey = (key) => {
6
- if (!key) {
13
+ if (key === null) {
7
14
  return '';
8
15
  }
9
- return key.split('.').map((k) => `\`${k}\``).join('.');
16
+ if (key.indexOf('(') !== -1 && key.indexOf(')') !== -1) {
17
+ let field = key.substring(key.indexOf('(') + 1, key.indexOf(')'));
18
+ key = key.substring(0, key.indexOf('(')) + '(' + _buildFieldWithTableName(field) + ')' + key.substring(key.indexOf(')') + 1);
19
+ }
20
+ if (key.indexOf(' as ') !== -1) {
21
+ const field = key.substring(key.indexOf(' as ') + 4);
22
+ key = key.substring(0, key.indexOf(' as ')) + ' AS ' + _buildFieldWithTableName(field);
23
+ } else if (key.indexOf(' AS ') !== -1) {
24
+ const field = key.substring(key.indexOf(' AS ') + 4);
25
+ key = key.substring(0, key.indexOf(' AS ')) + ' AS ' + _buildFieldWithTableName(field);
26
+ }
27
+ return _buildFieldWithTableName(key);
10
28
  };
11
29
 
12
30
  const _buildContidion = (conditions, prefix) => {
13
31
  const values = [];
32
+ if (is.empty(conditions)) {
33
+ return { sql: '', values };
34
+ }
14
35
  let sql = typeof prefix === 'undefined' ? ' WHERE ' : '';
15
36
  if (conditions.length) {
16
37
  sql += `${conditions.map((c) => {
@@ -20,6 +41,19 @@ const _buildContidion = (conditions, prefix) => {
20
41
  if (c.value === null) {
21
42
  return c.opt === '=' ? `ISNULL(${_buildFieldKey(c.key)})` : `!ISNULL(${_buildFieldKey(c.key)})`;
22
43
  }
44
+ if (c.key && c.key.indexOf('->') !== -1) {
45
+ const keys = c.key.split('->');
46
+ values.push(c.value);
47
+ const res = _buildContidion([
48
+ {
49
+ key: `JSON_EXTRACT(${_buildFieldKey(keys[0])}, '${keys[1]}')`,
50
+ opt: c.opt,
51
+ value: c.value
52
+ }
53
+ ], '');
54
+ values.push(...res.values);
55
+ return res.sql;
56
+ }
23
57
  const opt = c.opt.toLowerCase();
24
58
  if (opt === 'in' && Array.isArray(c.value)) {
25
59
  values.push(c.value.join(','));
@@ -44,10 +78,6 @@ const _buildValues = (obj) => {
44
78
  const values = [];
45
79
  Object.keys(obj).forEach((key) => {
46
80
  fields.push(`${key}`);
47
- if (obj[key] === null) {
48
- values.push('NULL');
49
- return;
50
- }
51
81
  if (Array.isArray(obj[key]) || is.object(obj[key])) {
52
82
  values.push(JSON.stringify(obj[key]));
53
83
  } else {
@@ -128,7 +158,7 @@ const buildSql = (options) => {
128
158
  case 'update': {
129
159
  const buildValueRes = _buildValues(options.data);
130
160
  sql = `UPDATE ${_buildTables(options.tables)} SET ${buildValueRes.fields.map(f => `${_buildFieldKey(f)} = ?`).join(',')}`;
131
- values = values.concat(values);
161
+ values = values.concat(buildValueRes.values);
132
162
  const buildConditionRes = _buildContidion(options.conditions);
133
163
  sql += buildConditionRes.sql;
134
164
  values = values.concat(buildConditionRes.values);
package/src/client.js CHANGED
@@ -10,16 +10,15 @@ const clients = {};
10
10
  * @param {mysql.ConnectionOptions} options
11
11
  * @returns {mysql.Connection}
12
12
  */
13
- const createClient = (options) => {
13
+ const createClient = (options, name = null) => {
14
14
  validate(options, {
15
- name: 'string',
16
15
  host: 'required|string',
17
16
  user: 'required|string',
18
17
  password: 'required|string',
19
18
  port: 'required|integer',
20
19
  database: 'required|string',
21
20
  });
22
- const key = options.name ? options.name :
21
+ const key = name ? name :
23
22
  `${options.host}:${options.port}:${options.user}:${options.password}:${options.database}`;
24
23
  if (clients[key]) {
25
24
  return clients[key];
package/src/query.js CHANGED
@@ -60,6 +60,11 @@ class QueryOperator {
60
60
  return this;
61
61
  }
62
62
 
63
+ whereObject(object = {}) {
64
+ Object.keys(object).forEach((key) => this.where(key, object[key]));
65
+ return this;
66
+ }
67
+
63
68
  whereConditions(...condition) {
64
69
  if (this.options.conditions.length) {
65
70
  this.options.conditions.push({ key: null, opt: 'AND', value: null });
@@ -102,7 +107,7 @@ class QueryOperator {
102
107
  return this;
103
108
  }
104
109
 
105
- orderBy(sortField, sortOrder) {
110
+ orderBy(sortField, sortOrder = 'asc') {
106
111
  this.options.orders.push({ sortField, sortOrder });
107
112
  return this;
108
113
  }
@@ -165,8 +170,7 @@ class QueryOperator {
165
170
 
166
171
  async find() {
167
172
  this.options.operator = 'find';
168
- const [res] = await this.exec();
169
- return res;
173
+ return await this.exec();
170
174
  }
171
175
 
172
176
  async update(data) {
@@ -187,8 +191,15 @@ class QueryOperator {
187
191
 
188
192
  async count() {
189
193
  this.options.operator = 'count';
190
- const res = await this.exec();
191
- return res;
194
+ return await this.exec();
195
+ }
196
+
197
+ async delete(id) {
198
+ if (id) {
199
+ this.where('id', id);
200
+ }
201
+ this.options.operator = 'delete';
202
+ return await this.exec();
192
203
  }
193
204
  }
194
205
 
@@ -216,12 +227,12 @@ class QueryHandler {
216
227
  });
217
228
  }
218
229
 
219
- async upsert(tableName, obj, condition = []) {
220
- const [row] = await this.table(tableName).whereConditions(...condition).select();
221
- if (row) {
222
- return await this.table(tableName).update(obj);
230
+ async upsert(tableName, data, condition = {}) {
231
+ const count = await this.table(tableName).whereObject(condition).count();
232
+ if (count) {
233
+ return await this.table(tableName).whereObject(condition).update(data);
223
234
  }
224
- return await this.table(tableName).insert(obj);
235
+ return await this.table(tableName).insert(data);
225
236
  }
226
237
  }
227
238