Skip to content

Commit cc3af59

Browse files
Bingmang高鸣飞
authored andcommitted
[feature] support Promise/async/await (resolve #26)
1 parent 3c24925 commit cc3af59

File tree

9 files changed

+249
-4
lines changed

9 files changed

+249
-4
lines changed

.travis.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
language: node_js
2+
node_js:
3+
- "7"
4+
- "8"
5+
- "9"
6+
services:
7+
- mysql
8+
- mongodb
9+
- redis
10+
after_success:
11+
- nyc report --reporter=text-lcov | coveralls

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) [2015-2018] [Rong Yin]
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1+
# SQLX
2+
3+
> Database driver with extended features like mysql changelog/oplog, connection auto release.
4+
5+
[![NPM version][npm-image]][npm-url]
6+
[![Build status][travis-image]][travis-url]
7+
[![Coverage Status][coveralls-image]][coveralls-url]
8+
[![License][license-image]][license-url]
9+
[![Downloads][downloads-image]][downloads-url]
10+
111
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
212
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
313
**Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)*
@@ -59,11 +69,22 @@ var operator_info = {
5969
}
6070
const conn = client.getConnection(operator_info)
6171

72+
// callback
6273
conn.insert('table7', {a:1, b:2}, function(err, rows, info) {
6374
if (err) throw err
6475
console.log(rows, info)
6576
})
6677

78+
// Promise/async/await
79+
let result
80+
try {
81+
result = await conn.insert('table7', {a:1, b:2})
82+
console.log(result.rows) // rows
83+
console.log(result.info) // info
84+
} catch (err) {
85+
throw err
86+
}
87+
6788
```
6889

6990
### action whitelist: operator_info.actions
@@ -157,6 +178,7 @@ const InterfaceTwo = {
157178

158179
### method
159180
```javascript
181+
// callback
160182
conn.selectEx(
161183
/* table */ 'table0',
162184
/* custom sql */ 'select ... join ...where field1 = ? and field2 = ?',
@@ -196,6 +218,19 @@ conn.delete(
196218
/* where */ {field1: 10},
197219
function(err, rows, info) {
198220
})
221+
222+
// Promise/async/await
223+
let result
224+
try {
225+
result = await conn.insert(
226+
/* table */ 'table0',
227+
/* set */ {field1: 20})
228+
console.log(result.rows) // rows
229+
console.log(result.info) // info
230+
} catch (err) {
231+
throw err
232+
}
233+
// other functions also works.
199234
```
200235

201236

@@ -239,3 +274,15 @@ cd node-sqlx
239274
npm i
240275
npm test
241276
```
277+
278+
279+
[npm-image]: https://img.shields.io/npm/v/sqlx.svg?style=flat-square
280+
[npm-url]: https://npmjs.org/package/sqlx
281+
[travis-image]: https://img.shields.io/travis/yinrong/node-sqlx/master.svg?style=flat-square
282+
[travis-url]: https://travis-ci.org/yinrong/node-sqlx
283+
[license-image]: http://img.shields.io/npm/l/sqlx.svg?style=flat-square
284+
[license-url]: LICENSE
285+
[downloads-image]: http://img.shields.io/npm/dm/sqlx.svg?style=flat-square
286+
[downloads-url]: https://npmjs.org/package/sqlx
287+
[coveralls-image]: https://img.shields.io/coveralls/github/yinrong/node-sqlx/master.svg?style=flat-square
288+
[coveralls-url]: https://coveralls.io/github/yinrong/node-sqlx

lib/$/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ util: require('util'),
1414

1515
_: require('lodash'),
1616

17+
thenifyApi: require('./thenifyApi')
18+
1719
}

lib/$/thenifyApi.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Convert the API to support Promise
3+
*/
4+
module.exports = (source, methods) => {
5+
let thenify_api = {}
6+
methods.forEach((name) => {
7+
// promisify only if it's a function
8+
if (typeof source[name] === 'function') {
9+
thenify_api[name] = thenify(source[name])
10+
}
11+
})
12+
return thenify_api
13+
}
14+
15+
/**
16+
* Turn async functions into promises and backward compatible with callback
17+
*
18+
* @param {Function} __fn__
19+
* @return {Function}
20+
*/
21+
22+
function thenify(__fn__) {
23+
return function (...args) {
24+
let self = this
25+
// callback was assigned
26+
if (typeof args[args.length - 1] === 'function') {
27+
return __fn__.apply(self, args)
28+
}
29+
// no callback, return Promise
30+
return new Promise((resolve, reject) => {
31+
let args_with_callback = args
32+
args_with_callback.push(createCallback(resolve, reject))
33+
__fn__.apply(self, args_with_callback)
34+
})
35+
}
36+
}
37+
38+
function createCallback(resolve, reject) {
39+
return function (err, ...values) {
40+
if (err) {
41+
return reject(err)
42+
}
43+
let result = {
44+
rows: values[0],
45+
info: values[1],
46+
}
47+
resolve(result)
48+
}
49+
}

lib/Connection.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ Connection.prototype.release = function() {
9999
return
100100
}
101101

102+
// support Promise/async/await and callback
103+
Connection.prototype = $.thenifyApi(Connection.prototype, $.ALL_METHODS)
104+
102105
var local = {}
103106

104107
local.assureNoUndefined = (obj) => {

package.json

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
{
22
"name": "sqlx",
3-
"version": "3.0.2",
4-
"description": "database driver with extended features like mysql changelog/oplog, connection auto release.",
3+
"version": "4.0.0",
4+
"description": "Database driver with extended features like mysql changelog/oplog, connection auto release.",
55
"main": "index.js",
66
"directories": {
77
"test": "test"
88
},
99
"scripts": {
10-
"test": "istanbul cover --dir .cov _mocha test; echo .cov/lcov-report/index.html"
10+
"test": "nyc ./node_modules/.bin/_mocha; echo .cov/index.html"
1111
},
1212
"repository": {
1313
"type": "git",
@@ -35,6 +35,26 @@
3535
"redis": "^2.8.0"
3636
},
3737
"devDependencies": {
38-
"lodash": "^4.15.0"
38+
"coveralls": "^3.0.0",
39+
"lodash": "^4.15.0",
40+
"mocha": "^3.5.3",
41+
"nyc": "^11.4.1"
42+
},
43+
"nyc": {
44+
"check-coverage": true,
45+
"report-dir": "./.cov",
46+
"include": [
47+
"$/*.js",
48+
"lib/*.js",
49+
"lib/**/*.js"
50+
],
51+
"extension": [
52+
".js"
53+
],
54+
"reporter": [
55+
"html",
56+
"text-summary"
57+
],
58+
"all": true
3959
}
4060
}

test/mysql.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ it('where in delete', function(done) {
165165
})
166166
})
167167

168+
168169
it('release', (done) => {
169170
const client = sqlx.createClient()
170171
client.define('*', MYSQL_CONFIG_1)

test/thenifyApi.js

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
describe('sqlx-promise', function() {
2+
3+
it('mysql async/await', async () => {
4+
child_process.execSync('mysql -uroot < test/mysql_initdb.txt')
5+
const client = sqlx.createClient()
6+
client.define('*', MYSQL_CONFIG_1)
7+
8+
const conn = client.getConnection(OPERATER_INFO)
9+
let result
10+
// insert
11+
await conn.insert(
12+
'table1',
13+
[
14+
{a:1, b:21},
15+
{a:2, b:22},
16+
{a:3, b:23},
17+
{a:3, b:123},
18+
])
19+
// select
20+
result = await conn.select('table1', '*', { $and: { a: 3, b: 123 } })
21+
assert.equal(result.rows.length, 1)
22+
// update
23+
result = await conn.update('table1', {b:1}, {a:3})
24+
assert.equal(result.rows.affected_rows, 2)
25+
assert.equal(result.rows.changed_rows, 2)
26+
// selectEx
27+
result = await conn.selectEx('table1', 'select * from table1 where a = ?', [2])
28+
assert.equal(result.rows.length, 1)
29+
assert.equal(result.rows[0].b, 22)
30+
// delete
31+
result = await conn.delete('table1', {a:3})
32+
assert.equal(result.rows.affected_rows, 2)
33+
conn.release()
34+
})
35+
36+
it('redis async/await', async () => {
37+
const client = sqlx.createClient()
38+
client.define('budget', {type: 'redis', config: REDIS_CONIFG})
39+
40+
const conn = client.getConnection(OPERATER_INFO)
41+
let result
42+
// insert
43+
result = await conn.insert('budget', {key1: 'value1'})
44+
assert.equal(result.rows, 'OK')
45+
// select
46+
result = await conn.select('budget', '*', {key1: 1})
47+
assert.equal(result.rows, 'value1')
48+
// update
49+
result = await conn.update('budget', {key1: 'value2'}, {key1: 1})
50+
assert.equal(result.rows, 'OK')
51+
result = await conn.select('budget', '*', {key1: 1})
52+
assert.equal(result.rows, 'value2')
53+
// delete
54+
result = await conn.delete('budget', {key1: 1})
55+
assert.equal(result.rows, 1)
56+
result = await conn.select('budget', '*', {key1: 1})
57+
assert.equal(result.rows, null)
58+
conn.release()
59+
})
60+
})
61+
62+
63+
const assert = require('assert')
64+
const async = require('async')
65+
const sqlx = require('..')
66+
const child_process = require('child_process')
67+
const _ = require('lodash')
68+
69+
// mysql
70+
const MYSQL_CONFIG_1 = {
71+
type: 'mysql',
72+
config: {
73+
connectionLimit: 1,
74+
host: '127.0.0.1',
75+
user: 'root',
76+
password: '',
77+
//debug: ['ComQueryPacket'],
78+
database: 'sqlx_mysql',
79+
} }
80+
81+
// redis
82+
const REDIS_CONIFG = {
83+
host: '127.0.0.1',
84+
port: '6379',
85+
}
86+
87+
// sqlx operater
88+
const OPERATER_INFO = {
89+
user: '101,23',
90+
actions: '*',
91+
}

0 commit comments

Comments
 (0)