pg-promise
Advanced tools
Comparing version 0.4.9 to 0.5.0
115
index.js
// Cannot declare 'use strict' here, because queryResult | ||
// needs to be exported into the global namespace. | ||
var npm = { | ||
promise: require('promise'), | ||
pg: require('pg') | ||
}; | ||
var npm; // dynamic package namespace; | ||
@@ -31,9 +28,38 @@ /////////////////////////////////////////////////////// | ||
// }, | ||
// | ||
// disconnect: function(client){ | ||
// client is disconnecting; | ||
// client - pg connection object. | ||
// } | ||
// }, | ||
// | ||
// pgFormatting: false, | ||
// - Redirects query formatting into PG library; | ||
// - Default is false, and all queries are formatted | ||
// - within 'pg-promise'. | ||
// | ||
// promiseLib: null | ||
// - Overrides the promise library instance used by | ||
// the library. | ||
// } | ||
module.exports = function (options) { | ||
if (npm) { | ||
throw new Error('Cannot initialize the library more than once.'); | ||
} else { | ||
var promiseLib; | ||
if (options && options.promiseLib) { | ||
if (typeof(options.promiseLib) === 'function') { | ||
promiseLib = options.promiseLib; | ||
} else { | ||
throw new Error('Invalid or unsupported promise library override.'); | ||
} | ||
} else { | ||
promiseLib = require('promise'); | ||
} | ||
npm = { | ||
pg: require('pg'), | ||
promise: promiseLib | ||
}; | ||
} | ||
var lib = function (cn) { | ||
@@ -71,3 +97,3 @@ if (!cn) { | ||
if (db) { | ||
return $query(db.client, query, values, qrm); | ||
return $query(db.client, query, values, qrm, options); | ||
} else { | ||
@@ -113,3 +139,3 @@ throw new Error("Cannot execute a query on a disconnected client."); | ||
$notify(true, db, options); | ||
$query(db.client, query, values, qrm) | ||
$query(db.client, query, values, qrm, options) | ||
.then(function (data) { | ||
@@ -149,3 +175,3 @@ $notify(false, db, options); | ||
} | ||
return $query(db.client, query, values, qrm); | ||
return $query(db.client, query, values, qrm, options); | ||
} | ||
@@ -310,3 +336,3 @@ }; | ||
result.success = false; | ||
result.error = "Parameter 'query' must be a text string"; | ||
result.error = "Parameter 'query' must be a text string."; | ||
} else { | ||
@@ -357,3 +383,3 @@ if (values) { | ||
// Generic, static query call for the specified connection + query + result. | ||
function $query(client, query, values, qrm) { | ||
function $query(client, query, values, qrm, options) { | ||
return $p(function (resolve, reject) { | ||
@@ -363,3 +389,3 @@ if ($isNull(qrm)) { | ||
} | ||
var errMsg, req; | ||
var errMsg, req, pgFormatting = (options && options.pgFormatting); | ||
if (!query) { | ||
@@ -372,5 +398,12 @@ errMsg = "Invalid query specified."; | ||
} else { | ||
req = $formatValues(query, values); | ||
if (!req.success) { | ||
errMsg = req.error; | ||
if (pgFormatting) { | ||
req = { | ||
success: true, | ||
query: query | ||
}; | ||
} else { | ||
req = $formatValues(query, values); | ||
if (!req.success) { | ||
errMsg = req.error; | ||
} | ||
} | ||
@@ -382,30 +415,36 @@ } | ||
} else { | ||
client.query(req.query, function (err, result) { | ||
if (err) { | ||
reject(err.message); | ||
} else { | ||
var data = result.rows; | ||
var l = result.rows.length; | ||
if (l) { | ||
if (l > 1 && (qrm & queryResult.one)) { | ||
reject("Single row was expected from query: " + req.query); | ||
} else { | ||
if (!(qrm & (queryResult.one | queryResult.many))) { | ||
reject("No return data was expected from query: " + req.query); | ||
var params = pgFormatting ? values : null; | ||
try { | ||
client.query(req.query, params, function (err, result) { | ||
if (err) { | ||
reject(err.message); | ||
} else { | ||
var data = result.rows; | ||
var l = result.rows.length; | ||
if (l) { | ||
if (l > 1 && (qrm & queryResult.one)) { | ||
reject("Single row was expected from query: " + req.query); | ||
} else { | ||
if (!(qrm & queryResult.many)) { | ||
data = result.rows[0]; | ||
if (!(qrm & (queryResult.one | queryResult.many))) { | ||
reject("No return data was expected from query: " + req.query); | ||
} else { | ||
if (!(qrm & queryResult.many)) { | ||
data = result.rows[0]; | ||
} | ||
} | ||
} | ||
} | ||
} else { | ||
if (qrm & queryResult.none) { | ||
data = (qrm & queryResult.many) ? [] : null; | ||
} else { | ||
reject("No rows returned from query: " + req.query); | ||
if (qrm & queryResult.none) { | ||
data = (qrm & queryResult.many) ? [] : null; | ||
} else { | ||
reject("No rows returned from query: " + req.query); | ||
} | ||
} | ||
resolve(data); | ||
} | ||
resolve(data); | ||
} | ||
}); | ||
}); | ||
} catch (err) { | ||
// Not likely to ever get here, but just in case; | ||
reject(err); | ||
} | ||
} | ||
@@ -476,3 +515,3 @@ }); | ||
if (typeof(cb) !== 'function') { | ||
return npm.promise.reject("Cannot invoke tx.exec() without a callback function."); | ||
return npm.promise.reject("Cannot invoke tx() without a callback function."); | ||
} | ||
@@ -488,3 +527,3 @@ var result; | ||
} else { | ||
return npm.promise.reject("Callback function passed into tx.exec() didn't return a valid promise object."); | ||
return npm.promise.reject("Callback function passed into tx() didn't return a valid promise object."); | ||
} | ||
@@ -491,0 +530,0 @@ } |
{ | ||
"name": "pg-promise", | ||
"version": "0.4.9", | ||
"version": "0.5.0", | ||
"description": "PG + Promise made easy, with transactions support.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
120
README.md
pg-promise | ||
=========== | ||
This library joins [Promise] and [PG] to help writing easy-to-read database code built on promises. | ||
Complete access layer to [PG] with any [Promises/A+] library. | ||
[![Build Status](https://travis-ci.org/vitaly-t/pg-promise.svg?branch=master)](https://travis-ci.org/vitaly-t/pg-promise) | ||
@@ -11,6 +12,6 @@ | ||
* Streamlined database code structure, thanks to [Promise]; | ||
* Robust, declarative approach to handling results from queries; | ||
* Database connections are managed automatically for every query; | ||
* Functions, Procedures and Transactions are all fully supported. | ||
* Full support of functions + transactions; | ||
* Declarative result handling for queries; | ||
* Use your favourite [Promises/A+] library; | ||
* Automatic database connections. | ||
@@ -23,7 +24,7 @@ # Installing | ||
# Testing | ||
* install all of the project's dependencies: | ||
* Install project dependencies | ||
``` | ||
$ npm install | ||
``` | ||
* run tests: | ||
* Run tests | ||
``` | ||
@@ -46,5 +47,5 @@ $ make test | ||
``` | ||
You can pass additional `options` parameter when initializing the library (see chapter **Advanced** for details). | ||
You can pass additional `options` parameter when initializing the library (see chapter [Initialization Options](#advanced) for details). | ||
**NOTE:** Only one instance of such `pgp` object should exist throughout the application. | ||
**NOTE:** Only one instance of such `pgp` object can exist throughout the application. | ||
### 3. Configure database connection | ||
@@ -140,3 +141,3 @@ Use one of the two ways to specify connection details: | ||
##### Example of a detached transaction: | ||
###### Example of a detached transaction: | ||
@@ -163,3 +164,5 @@ ```javascript | ||
And when executing a transaction within a shared connection chain, the only thing that changes is that parameter ```ctx``` becomes the | ||
same as parameter ```sco``` from opening a shared connection, so either one can be used inside such a transaction interchangeably: | ||
same as parameter ```sco``` from opening a shared connection, so either one can be used inside such a transaction interchangeably. | ||
###### Shared-connection transaction: | ||
```javascript | ||
@@ -309,22 +312,90 @@ var promise = require('promise'); | ||
### Initialization options | ||
Initialization options are supported as shown in the example: | ||
### Initialization Options | ||
When initializing the library, you can pass object `options` with a set of properties | ||
for global override of the library's behaviour: | ||
```javascript | ||
var options = { | ||
// override properties; | ||
}; | ||
var pgp = pgpLib(options); | ||
``` | ||
Below is the list of all such properties that are currently supported. | ||
##### pgFormatting | ||
By default, **pg-promise** provides its own implementation of the query value formatting, | ||
using the standard syntax of $1, $2, etc. | ||
Any query request accepts values for the variable within query string as the second parameter. | ||
It accepts a single simple value for queries that use only one variable, as well as an array of simple values, | ||
for queries with multiple variables in them. | ||
**pg-promise** implementation of query formatting supports only the basic javascript types: text, boolean, date, numeric and null. | ||
If, instead, you want to use query formatting that's implemented by the [PG] library, set parameter `pgFormatting` | ||
to be `true` when initializing the library, and every query formatting will redirect to the [PG]'s implementation. | ||
Although this has huge implication to the library's functionality, it is not within the scope of this project to detail. | ||
For any further reference you should use documentation of the [PG] library. | ||
**NOTE:** As of the current implementation, formatting parameters for calling functions (methods `func` and `proc`) is not affected by this | ||
override. If needed, use the generic `query` instead to invoke functions with redirected query formatting. | ||
##### promiseLib | ||
Set this property to any promise library that's compliant with the [Promises/A+] standard. | ||
By default, **pg-promise** uses version of [Promises/A+] provided by [Promise]. If you want to override | ||
this and force the library to use a different implementation of the standard, just set this parameter | ||
to the library's instance. | ||
Example of switching over to [Bluebird]: | ||
```javascript | ||
var promise = require('bluebird'); | ||
var options = { | ||
promiseLib: promise | ||
}; | ||
var pgp = pgpLib(options); | ||
``` | ||
As of this writing, [Bluebird] is the only alternative [Promises/A+] library that **pg-promise** | ||
has been tested against. Compatibility with other [Promises/A+] though expected, hasn't been tested, and thus unknown. | ||
##### connect | ||
This property represents a global `connect` event handler: whenever a new connection has been established with the database, | ||
this event function is called: | ||
```javascript | ||
var options = { | ||
connect: function(client){ | ||
var cp = client.connectionParameters; | ||
console.log("Connected to database '" + cp.database + "'"); | ||
}, | ||
} | ||
} | ||
``` | ||
It can be used for diagnostics / connection monitoring within your application. | ||
The function takes only one parameter - `client` object from the [PG] library that represents connection | ||
with the database. | ||
##### disconnect | ||
This property represents a global `disconnect` event handler: whenever a connection is about to be released, | ||
this event function is called: | ||
```javascript | ||
var options = { | ||
disconnect: function(client){ | ||
var cp = client.connectionParameters; | ||
console.log("Disconnected from database '" + cp.database + "'"); | ||
console.log("Disconnecting from database '" + cp.database + "'"); | ||
} | ||
}; | ||
var pgp = pgpLib(options); | ||
} | ||
``` | ||
Two events are supported at the moment - `connect` and `disconnect`, to notify of virtual connections being established or released accordingly. | ||
Each event takes parameter `client`, which is the client connection object. These events are mostly for connection monitoring, | ||
while debugging your application. | ||
It can be used for diagnostics / connection monitoring within your application. | ||
### De-initialization | ||
The function takes only one parameter - `client` object from the [PG] library that represents the connection | ||
that's being released. | ||
### Library de-initialization | ||
When exiting your application, make the following call: | ||
@@ -338,5 +409,6 @@ ```javascript | ||
# History | ||
* Version 0.5.0 introduces many new features and fixes, such as properties **pgFormatting** and **promiseLib**. Released on March 11, 2015. | ||
* Version 0.4.9 represents a solid code base, backed up by comprehensive testing. Released on March 10, 2015. | ||
* Version 0.4.0 is a complete rewrite of most of the library, made first available on March 8, 2015 | ||
* Version 0.2.0 introduced on March 6th, 2015, supporting multiple databases | ||
* Version 0.4.0 is a complete rewrite of most of the library, made first available on March 8, 2015. | ||
* Version 0.2.0 introduced on March 6th, 2015, supporting multiple databases. | ||
* A refined version 0.1.4 released on March 5th, 2015. | ||
@@ -350,2 +422,4 @@ * First solid Beta, 0.1.2 on March 4th, 2015. | ||
[ConnectionParameters]:https://github.com/brianc/node-postgres/blob/master/lib/connection-parameters.js | ||
[Promises/A+]:https://promisesaplus.com/ | ||
[Bluebird]:https://github.com/petkaantonov/bluebird | ||
@@ -352,0 +426,0 @@ # License |
@@ -1,21 +0,32 @@ | ||
var pgpLib = require('../index') | ||
var pgpLib = require('../index'); | ||
var pgp = pgpLib(); // initializing the library; | ||
describe("Library entry object", function () { | ||
it("must be a function", function () { | ||
expect(typeof(pgpLib)).toBe('function'); | ||
}); | ||
}); | ||
var pgp = pgpLib(); // initializing the library; | ||
describe("Library initialization object", function () { | ||
describe("Library initialization object", function () { | ||
it("can be created only once", function () { | ||
expect(function(){ | ||
pgpLib(); | ||
}).toThrow('Cannot initialize the library more than once.'); | ||
}); | ||
it("must be a function", function () { | ||
expect(typeof(pgp)).toBe('function'); | ||
}); | ||
it("must have property 'pg'", function () { | ||
expect(typeof(pgp.pg)).toBe('object'); | ||
}); | ||
it("must have function 'end'", function () { | ||
expect(typeof(pgp.end)).toBe('function'); | ||
}); | ||
it("must have valid property 'as'", function () { | ||
@@ -114,2 +125,4 @@ expect(typeof(pgp.as)).toBe('object'); | ||
}).toThrow("'function () {}' doesn't represent a valid Date object or value."); | ||
expect(pgp.as.date(new Date(2015, 2, 8, 16, 24, 8))).toBe("'Sun, 08 Mar 2015 16:24:08 GMT'"); | ||
}); | ||
@@ -150,11 +163,11 @@ | ||
expect(q.success).toBe(false); | ||
expect(q.error).toBe("Parameter 'query' must be a text string"); | ||
expect(q.error).toBe("Parameter 'query' must be a text string."); | ||
q = pgp.as.format(null); | ||
expect(q.success).toBe(false); | ||
expect(q.error).toBe("Parameter 'query' must be a text string"); | ||
expect(q.error).toBe("Parameter 'query' must be a text string."); | ||
q = pgp.as.format(null, [1, 2, 3]); | ||
expect(q.success).toBe(false); | ||
expect(q.error).toBe("Parameter 'query' must be a text string"); | ||
expect(q.error).toBe("Parameter 'query' must be a text string."); | ||
@@ -161,0 +174,0 @@ q = pgp.as.format("$1", null); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
749
432
50003
7