UNPKG

2.73 kBJavaScriptView Raw
1import Promise from 'bluebird';
2import pgDriver from 'pg';
3import debug from './debug';
4import makeAsyncApi from './makeAsyncApi';
5
6function checkAsyncFunction(asyncFunc) {
7 if (typeof asyncFunc !== 'function')
8 throw new TypeError('async function expected');
9}
10
11export default class PgAsync {
12 constructor(connectionOptions, driver) {
13 this.setConnectionOptions(connectionOptions);
14 this.setDriver(driver);
15
16 const wrap = name => {
17 this[name] = (sql, ...values) =>
18 this.connect(client => client[`${name}Args`](sql, values));
19 };
20 const wrapArgs = name => {
21 this[name] = (sql, values) =>
22 this.connect(client => client[name](sql, values));
23 };
24
25 wrap('query');
26 wrapArgs('queryArgs');
27
28 wrap('rows');
29 wrapArgs('rowsArgs');
30
31 wrap('row');
32 wrapArgs('rowArgs');
33
34 wrap('value');
35 wrapArgs('valueArgs');
36 }
37
38 setConnectionOptions(options) {
39 this._connectionOptions = options;
40 return this;
41 }
42
43 getConnectionOptions() {
44 return this._connectionOptions || this.getDriver().defaults;
45 }
46
47 getDriver() {
48 return this._driver;
49 }
50
51 setDriver(driver) {
52 if (typeof driver === 'string')
53 switch (driver) {
54 case '': case 'pg':
55 driver = pgDriver;
56 break;
57 case 'native': case 'pg.native':
58 driver = pgDriver.native;
59 break;
60 default:
61 throw new Error(`Unrecognized driver name: ${driver}`);
62 }
63 this._driver = driver || pgDriver;
64 return this;
65 }
66
67 async getClient() {
68 return new Promise((resolve, reject) => {
69 this.getDriver().connect(this.getConnectionOptions(), (err, client, done) => {
70 if (err) {
71 debug('%s getClient(%j)', err, this.getConnectionOptions());
72 if (done) done(err);
73 return reject(err);
74 }
75 return resolve({client, done});
76 });
77 });
78 }
79
80 async connect(asyncFunc) {
81 checkAsyncFunction(asyncFunc);
82
83 const {client, done} = await this.getClient();
84 try {
85 const api = makeAsyncApi(client);
86 const result = await asyncFunc(api);
87 await api.end();
88 done();
89 return result;
90 } catch (err) {
91 done(err);
92 throw err;
93 }
94 }
95
96 async transaction(asyncFunc) {
97 checkAsyncFunction(asyncFunc);
98
99 return await this.connect(async (client) => {
100 await client.startTransaction();
101 try {
102 const result = await asyncFunc(client);
103 await client.commit();
104 return result;
105 } catch (err) {
106 try {
107 await client.rollback();
108 } catch (_) {
109 // client disconnected?
110 }
111 throw err;
112 }
113 });
114 }
115
116 closeConnections = () => this.getDriver().end();
117
118}