Einkaufslisten anzeigen, Datenbankeinbindung

This commit is contained in:
Lukas Nowy
2018-10-27 01:10:46 +02:00
parent 5e3c83707f
commit 8e7d96310f
425 changed files with 77158 additions and 3 deletions

2
express-server/node_modules/pg-pool/.npmignore generated vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules
npm-debug.log

10
express-server/node_modules/pg-pool/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,10 @@
language: node_js
matrix:
include:
- node_js: "4"
addons:
postgresql: "9.1"
- node_js: "6"
addons:
postgresql: "9.4"

21
express-server/node_modules/pg-pool/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 Brian M. Carlson
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

14
express-server/node_modules/pg-pool/Makefile generated vendored Normal file
View File

@ -0,0 +1,14 @@
.PHONY: jshint test publish-patch test
test:
npm test
patch: test
npm version patch -m "Bump version"
git push origin master --tags
npm publish
minor: test
npm version minor -m "Bump version"
git push origin master --tags
npm publish

351
express-server/node_modules/pg-pool/README.md generated vendored Normal file
View File

@ -0,0 +1,351 @@
# pg-pool
[![Build Status](https://travis-ci.org/brianc/node-pg-pool.svg?branch=master)](https://travis-ci.org/brianc/node-pg-pool)
A connection pool for node-postgres
## install
```sh
npm i pg-pool pg
```
## use
### create
to use pg-pool you must first create an instance of a pool
```js
var Pool = require('pg-pool')
// by default the pool uses the same
// configuration as whatever `pg` version you have installed
var pool = new Pool()
// you can pass properties to the pool
// these properties are passed unchanged to both the node-postgres Client constructor
// and the node-pool (https://github.com/coopernurse/node-pool) constructor
// allowing you to fully configure the behavior of both
var pool2 = new Pool({
database: 'postgres',
user: 'brianc',
password: 'secret!',
port: 5432,
ssl: true,
max: 20, // set pool max size to 20
min: 4, // set min pool size to 4
idleTimeoutMillis: 1000, // close idle clients after 1 second
connectionTimeoutMillis: 1000, // return an error after 1 second if connection could not be established
})
//you can supply a custom client constructor
//if you want to use the native postgres client
var NativeClient = require('pg').native.Client
var nativePool = new Pool({ Client: NativeClient })
//you can even pool pg-native clients directly
var PgNativeClient = require('pg-native')
var pgNativePool = new Pool({ Client: PgNativeClient })
```
##### Note:
The Pool constructor does not support passing a Database URL as the parameter. To use pg-pool on heroku, for example, you need to parse the URL into a config object. Here is an example of how to parse a Database URL.
```js
const Pool = require('pg-pool');
const url = require('url')
const params = url.parse(process.env.DATABASE_URL);
const auth = params.auth.split(':');
const config = {
user: auth[0],
password: auth[1],
host: params.hostname,
port: params.port,
database: params.pathname.split('/')[1],
ssl: true
};
const pool = new Pool(config);
/*
Transforms, 'progres://DBuser:secret@DBHost:#####/myDB', into
config = {
user: 'DBuser',
password: 'secret',
host: 'DBHost',
port: '#####',
database: 'myDB',
ssl: true
}
*/
```
### acquire clients with a promise
pg-pool supports a fully promise-based api for acquiring clients
```js
var pool = new Pool()
pool.connect().then(client => {
client.query('select $1::text as name', ['pg-pool']).then(res => {
client.release()
console.log('hello from', res.rows[0].name)
})
.catch(e => {
client.release()
console.error('query error', e.message, e.stack)
})
})
```
### plays nice with async/await
this ends up looking much nicer if you're using [co](https://github.com/tj/co) or async/await:
```js
// with async/await
(async () => {
var pool = new Pool()
var client = await pool.connect()
try {
var result = await client.query('select $1::text as name', ['brianc'])
console.log('hello from', result.rows[0])
} finally {
client.release()
}
})().catch(e => console.error(e.message, e.stack))
// with co
co(function * () {
var client = yield pool.connect()
try {
var result = yield client.query('select $1::text as name', ['brianc'])
console.log('hello from', result.rows[0])
} finally {
client.release()
}
}).catch(e => console.error(e.message, e.stack))
```
### your new favorite helper method
because its so common to just run a query and return the client to the pool afterward pg-pool has this built-in:
```js
var pool = new Pool()
var time = await pool.query('SELECT NOW()')
var name = await pool.query('select $1::text as name', ['brianc'])
console.log(name.rows[0].name, 'says hello at', time.rows[0].name)
```
you can also use a callback here if you'd like:
```js
var pool = new Pool()
pool.query('SELECT $1::text as name', ['brianc'], function (err, res) {
console.log(res.rows[0].name) // brianc
})
```
__pro tip:__ unless you need to run a transaction (which requires a single client for multiple queries) or you
have some other edge case like [streaming rows](https://github.com/brianc/node-pg-query-stream) or using a [cursor](https://github.com/brianc/node-pg-cursor)
you should almost always just use `pool.query`. Its easy, it does the right thing :tm:, and wont ever forget to return
clients back to the pool after the query is done.
### drop-in backwards compatible
pg-pool still and will always support the traditional callback api for acquiring a client. This is the exact API node-postgres has shipped with for years:
```js
var pool = new Pool()
pool.connect((err, client, done) => {
if (err) return done(err)
client.query('SELECT $1::text as name', ['pg-pool'], (err, res) => {
done()
if (err) {
return console.error('query error', e.message, e.stack)
}
console.log('hello from', res.rows[0].name)
})
})
```
### shut it down
When you are finished with the pool if all the clients are idle the pool will close them after `config.idleTimeoutMillis` and your app
will shutdown gracefully. If you don't want to wait for the timeout you can end the pool as follows:
```js
var pool = new Pool()
var client = await pool.connect()
console.log(await client.query('select now()'))
client.release()
await pool.end()
```
### a note on instances
The pool should be a __long-lived object__ in your application. Generally you'll want to instantiate one pool when your app starts up and use the same instance of the pool throughout the lifetime of your application. If you are frequently creating a new pool within your code you likely don't have your pool initialization code in the correct place. Example:
```js
// assume this is a file in your program at ./your-app/lib/db.js
// correct usage: create the pool and let it live
// 'globally' here, controlling access to it through exported methods
var pool = new pg.Pool()
// this is the right way to export the query method
module.exports.query = (text, values) => {
console.log('query:', text, values)
return pool.query(text, values)
}
// this would be the WRONG way to export the connect method
module.exports.connect = () => {
// notice how we would be creating a pool instance here
// every time we called 'connect' to get a new client?
// that's a bad thing & results in creating an unbounded
// number of pools & therefore connections
var aPool = new pg.Pool()
return aPool.connect()
}
```
### events
Every instance of a `Pool` is an event emitter. These instances emit the following events:
#### error
Emitted whenever an idle client in the pool encounters an error. This is common when your PostgreSQL server shuts down, reboots, or a network partition otherwise causes it to become unavailable while your pool has connected clients.
Example:
```js
const Pool = require('pg-pool')
const pool = new Pool()
// attach an error handler to the pool for when a connected, idle client
// receives an error by being disconnected, etc
pool.on('error', function(error, client) {
// handle this in the same way you would treat process.on('uncaughtException')
// it is supplied the error as well as the idle client which received the error
})
```
#### connect
Fired whenever the pool creates a __new__ `pg.Client` instance and successfully connects it to the backend.
Example:
```js
const Pool = require('pg-pool')
const pool = new Pool()
var count = 0
pool.on('connect', client => {
client.count = count++
})
pool
.connect()
.then(client => {
return client
.query('SELECT $1::int AS "clientCount"', [client.count])
.then(res => console.log(res.rows[0].clientCount)) // outputs 0
.then(() => client)
})
.then(client => client.release())
```
#### acquire
Fired whenever the a client is acquired from the pool
Example:
This allows you to count the number of clients which have ever been acquired from the pool.
```js
var Pool = require('pg-pool')
var pool = new Pool()
var acquireCount = 0
pool.on('acquire', function (client) {
acquireCount++
})
var connectCount = 0
pool.on('connect', function () {
connectCount++
})
for (var i = 0; i < 200; i++) {
pool.query('SELECT NOW()')
}
setTimeout(function () {
console.log('connect count:', connectCount) // output: connect count: 10
console.log('acquire count:', acquireCount) // output: acquire count: 200
}, 100)
```
### environment variables
pg-pool & node-postgres support some of the same environment variables as `psql` supports. The most common are:
```
PGDATABASE=my_db
PGUSER=username
PGPASSWORD="my awesome password"
PGPORT=5432
PGSSLMODE=require
```
Usually I will export these into my local environment via a `.env` file with environment settings or export them in `~/.bash_profile` or something similar. This way I get configurability which works with both the postgres suite of tools (`psql`, `pg_dump`, `pg_restore`) and node, I can vary the environment variables locally and in production, and it supports the concept of a [12-factor app](http://12factor.net/) out of the box.
## bring your own promise
In versions of node `<=0.12.x` there is no native promise implementation available globally. You can polyfill the promise globally like this:
```js
// first run `npm install promise-polyfill --save
if (typeof Promise == 'undefined') {
global.Promise = require('promise-polyfill')
}
```
You can use any other promise implementation you'd like. The pool also allows you to configure the promise implementation on a per-pool level:
```js
var bluebirdPool = new Pool({
Promise: require('bluebird')
})
```
__please note:__ in node `<=0.12.x` the pool will throw if you do not provide a promise constructor in one of the two ways mentioned above. In node `>=4.0.0` the pool will use the native promise implementation by default; however, the two methods above still allow you to "bring your own."
## tests
To run tests clone the repo, `npm i` in the working dir, and then run `npm test`
## contributions
I love contributions. Please make sure they have tests, and submit a PR. If you're not sure if the issue is worth it or will be accepted it never hurts to open an issue to begin the conversation. If you're interested in keeping up with node-postgres releated stuff, you can follow me on twitter at [@briancarlson](https://twitter.com/briancarlson) - I generally announce any noteworthy updates there.
## license
The MIT License (MIT)
Copyright (c) 2016 Brian M. Carlson
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

294
express-server/node_modules/pg-pool/index.js generated vendored Normal file
View File

@ -0,0 +1,294 @@
'use strict'
const EventEmitter = require('events').EventEmitter
const NOOP = function () { }
const removeWhere = (list, predicate) => {
const i = list.findIndex(predicate)
return i === -1
? undefined
: list.splice(i, 1)[0]
}
class IdleItem {
constructor (client, timeoutId) {
this.client = client
this.timeoutId = timeoutId
}
}
function throwOnRelease () {
throw new Error('Release called on client which has already been released to the pool.')
}
function release (client, err) {
client.release = throwOnRelease
if (err || this.ending) {
this._remove(client)
this._pulseQueue()
return
}
// idle timeout
let tid
if (this.options.idleTimeoutMillis) {
tid = setTimeout(() => {
this.log('remove idle client')
this._remove(client)
}, this.options.idleTimeoutMillis)
}
this._idle.push(new IdleItem(client, tid))
this._pulseQueue()
}
function promisify (Promise, callback) {
if (callback) {
return { callback: callback, result: undefined }
}
let rej
let res
const cb = function (err, client) {
err ? rej(err) : res(client)
}
const result = new Promise(function (resolve, reject) {
res = resolve
rej = reject
})
return { callback: cb, result: result }
}
class Pool extends EventEmitter {
constructor (options, Client) {
super()
this.options = Object.assign({}, options)
this.options.max = this.options.max || this.options.poolSize || 10
this.log = this.options.log || function () { }
this.Client = this.options.Client || Client || require('pg').Client
this.Promise = this.options.Promise || global.Promise
if (typeof this.options.idleTimeoutMillis === 'undefined') {
this.options.idleTimeoutMillis = 10000
}
this._clients = []
this._idle = []
this._pendingQueue = []
this._endCallback = undefined
this.ending = false
}
_isFull () {
return this._clients.length >= this.options.max
}
_pulseQueue () {
this.log('pulse queue')
if (this.ending) {
this.log('pulse queue on ending')
if (this._idle.length) {
this._idle.slice().map(item => {
this._remove(item.client)
})
}
if (!this._clients.length) {
this._endCallback()
}
return
}
// if we don't have any waiting, do nothing
if (!this._pendingQueue.length) {
this.log('no queued requests')
return
}
// if we don't have any idle clients and we have no more room do nothing
if (!this._idle.length && this._isFull()) {
return
}
const waiter = this._pendingQueue.shift()
if (this._idle.length) {
const idleItem = this._idle.pop()
clearTimeout(idleItem.timeoutId)
const client = idleItem.client
client.release = release.bind(this, client)
this.emit('acquire', client)
return waiter(undefined, client, client.release)
}
if (!this._isFull()) {
return this.connect(waiter)
}
throw new Error('unexpected condition')
}
_remove (client) {
const removed = removeWhere(
this._idle,
item => item.client === client
)
if (removed !== undefined) {
clearTimeout(removed.timeoutId)
}
this._clients = this._clients.filter(c => c !== client)
client.end()
this.emit('remove', client)
}
connect (cb) {
if (this.ending) {
const err = new Error('Cannot use a pool after calling end on the pool')
return cb ? cb(err) : this.Promise.reject(err)
}
// if we don't have to connect a new client, don't do so
if (this._clients.length >= this.options.max || this._idle.length) {
const response = promisify(this.Promise, cb)
const result = response.result
// if we have idle clients schedule a pulse immediately
if (this._idle.length) {
process.nextTick(() => this._pulseQueue())
}
if (!this.options.connectionTimeoutMillis) {
this._pendingQueue.push(response.callback)
return result
}
// set connection timeout on checking out an existing client
const tid = setTimeout(() => {
// remove the callback from pending waiters because
// we're going to call it with a timeout error
this._pendingQueue = this._pendingQueue.filter(cb => cb === response.callback)
response.callback(new Error('timeout exceeded when trying to connect'))
}, this.options.connectionTimeoutMillis)
this._pendingQueue.push(function (err, res, done) {
clearTimeout(tid)
response.callback(err, res, done)
})
return result
}
const client = new this.Client(this.options)
this._clients.push(client)
const idleListener = (err) => {
err.client = client
client.removeListener('error', idleListener)
client.on('error', () => {
this.log('additional client error after disconnection due to error', err)
})
this._remove(client)
// TODO - document that once the pool emits an error
// the client has already been closed & purged and is unusable
this.emit('error', err, client)
}
this.log('connecting new client')
// connection timeout logic
let tid
let timeoutHit = false
if (this.options.connectionTimeoutMillis) {
tid = setTimeout(() => {
this.log('ending client due to timeout')
timeoutHit = true
// force kill the node driver, and let libpq do its teardown
client.connection ? client.connection.stream.destroy() : client.end()
}, this.options.connectionTimeoutMillis)
}
const response = promisify(this.Promise, cb)
cb = response.callback
this.log('connecting new client')
client.connect((err) => {
this.log('new client connected')
if (tid) {
clearTimeout(tid)
}
client.on('error', idleListener)
if (err) {
// remove the dead client from our list of clients
this._clients = this._clients.filter(c => c !== client)
if (timeoutHit) {
err.message = 'Connection terminiated due to connection timeout'
}
cb(err, undefined, NOOP)
} else {
client.release = release.bind(this, client)
this.emit('connect', client)
this.emit('acquire', client)
if (this.options.verify) {
this.options.verify(client, cb)
} else {
cb(undefined, client, client.release)
}
}
})
return response.result
}
query (text, values, cb) {
// guard clause against passing a function as the first parameter
if (typeof text === 'function') {
const response = promisify(this.Promise, text)
setImmediate(function () {
return response.callback(new Error('Passing a function as the first parameter to pool.query is not supported'))
})
return response.result
}
// allow plain text query without values
if (typeof values === 'function') {
cb = values
values = undefined
}
const response = promisify(this.Promise, cb)
cb = response.callback
this.connect((err, client) => {
if (err) {
return cb(err)
}
this.log('dispatching query')
client.query(text, values, (err, res) => {
this.log('query dispatched')
client.release(err)
if (err) {
return cb(err)
} else {
return cb(undefined, res)
}
})
})
return response.result
}
end (cb) {
this.log('ending')
if (this.ending) {
const err = new Error('Called end on pool more than once')
return cb ? cb(err) : this.Promise.reject(err)
}
this.ending = true
const promised = promisify(this.Promise, cb)
this._endCallback = promised.callback
this._pulseQueue()
return promised.result
}
get waitingCount () {
return this._pendingQueue.length
}
get idleCount () {
return this._idle.length
}
get totalCount () {
return this._clients.length
}
}
module.exports = Pool

70
express-server/node_modules/pg-pool/package.json generated vendored Normal file
View File

@ -0,0 +1,70 @@
{
"_from": "pg-pool@~2.0.3",
"_id": "pg-pool@2.0.3",
"_inBundle": false,
"_integrity": "sha1-wCIDLIlJ8xKk+R+2QJzgQHa+Mlc=",
"_location": "/pg-pool",
"_phantomChildren": {},
"_requested": {
"type": "range",
"registry": true,
"raw": "pg-pool@~2.0.3",
"name": "pg-pool",
"escapedName": "pg-pool",
"rawSpec": "~2.0.3",
"saveSpec": null,
"fetchSpec": "~2.0.3"
},
"_requiredBy": [
"/pg"
],
"_resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.3.tgz",
"_shasum": "c022032c8949f312a4f91fb6409ce04076be3257",
"_spec": "pg-pool@~2.0.3",
"_where": "D:\\5CHITM\\Diplomarbeit\\smart-shopper\\SmartShopper\\express-server\\node_modules\\pg",
"author": {
"name": "Brian M. Carlson"
},
"bugs": {
"url": "https://github.com/brianc/node-pg-pool/issues"
},
"bundleDependencies": false,
"dependencies": {},
"deprecated": false,
"description": "Connection pool for node-postgres",
"devDependencies": {
"bluebird": "3.4.1",
"co": "4.6.0",
"expect.js": "0.3.1",
"lodash": "4.13.1",
"mocha": "^2.3.3",
"pg": "*",
"pg-cursor": "^1.3.0",
"standard": "7.1.2",
"standard-format": "2.2.1"
},
"directories": {
"test": "test"
},
"homepage": "https://github.com/brianc/node-pg-pool#readme",
"keywords": [
"pg",
"postgres",
"pool",
"database"
],
"license": "MIT",
"main": "index.js",
"name": "pg-pool",
"peerDependencies": {
"pg": ">5.0"
},
"repository": {
"type": "git",
"url": "git://github.com/brianc/node-pg-pool.git"
},
"scripts": {
"test": " node_modules/.bin/mocha && node_modules/.bin/standard"
},
"version": "2.0.3"
}

View File

@ -0,0 +1,36 @@
'use strict'
const co = require('co')
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const BluebirdPromise = require('bluebird')
const Pool = require('../')
const checkType = promise => {
expect(promise).to.be.a(BluebirdPromise)
return promise.catch(e => undefined)
}
describe('Bring your own promise', function () {
it('uses supplied promise for operations', co.wrap(function * () {
const pool = new Pool({ Promise: BluebirdPromise })
const client1 = yield checkType(pool.connect())
client1.release()
yield checkType(pool.query('SELECT NOW()'))
const client2 = yield checkType(pool.connect())
// TODO - make sure pg supports BYOP as well
client2.release()
yield checkType(pool.end())
}))
it('uses promises in errors', co.wrap(function * () {
const pool = new Pool({ Promise: BluebirdPromise, port: 48484 })
yield checkType(pool.connect())
yield checkType(pool.end())
yield checkType(pool.connect())
yield checkType(pool.query())
yield checkType(pool.end())
}))
})

View File

@ -0,0 +1,30 @@
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('Connection strings', function () {
it('pool delegates connectionString property to client', function (done) {
const connectionString = 'postgres://foo:bar@baz:1234/xur'
const pool = new Pool({
// use a fake client so we can check we're passed the connectionString
Client: function (args) {
expect(args.connectionString).to.equal(connectionString)
return {
connect: function (cb) {
cb(new Error('testing'))
},
on: function () { }
}
},
connectionString: connectionString
})
pool.connect(function (err, client) {
expect(err).to.not.be(undefined)
done()
})
})
})

View File

@ -0,0 +1,107 @@
'use strict'
const net = require('net')
const co = require('co')
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const before = require('mocha').before
const after = require('mocha').after
const Pool = require('../')
describe('connection timeout', () => {
before((done) => {
this.server = net.createServer((socket) => {
})
this.server.listen(() => {
this.port = this.server.address().port
done()
})
})
after((done) => {
this.server.close(done)
})
it('should callback with an error if timeout is passed', (done) => {
const pool = new Pool({ connectionTimeoutMillis: 10, port: this.port })
pool.connect((err, client, release) => {
expect(err).to.be.an(Error)
expect(err.message).to.contain('timeout')
expect(client).to.equal(undefined)
expect(pool.idleCount).to.equal(0)
done()
})
})
it('should reject promise with an error if timeout is passed', (done) => {
const pool = new Pool({ connectionTimeoutMillis: 10, port: this.port })
pool.connect().catch(err => {
expect(err).to.be.an(Error)
expect(err.message).to.contain('timeout')
expect(pool.idleCount).to.equal(0)
done()
})
})
it('should handle multiple timeouts', co.wrap(function * () {
const errors = []
const pool = new Pool({ connectionTimeoutMillis: 1, port: this.port })
for (var i = 0; i < 15; i++) {
try {
yield pool.connect()
} catch (e) {
errors.push(e)
}
}
expect(errors).to.have.length(15)
}.bind(this)))
it('should timeout on checkout of used connection', (done) => {
const pool = new Pool({ connectionTimeoutMillis: 100, max: 1 })
pool.connect((err, client, release) => {
expect(err).to.be(undefined)
expect(client).to.not.be(undefined)
pool.connect((err, client) => {
expect(err).to.be.an(Error)
expect(client).to.be(undefined)
release()
pool.end(done)
})
})
})
it('should timeout on query if all clients are busy', (done) => {
const pool = new Pool({ connectionTimeoutMillis: 100, max: 1 })
pool.connect((err, client, release) => {
expect(err).to.be(undefined)
expect(client).to.not.be(undefined)
pool.query('select now()', (err, result) => {
expect(err).to.be.an(Error)
expect(result).to.be(undefined)
release()
pool.end(done)
})
})
})
it('should recover from timeout errors', (done) => {
const pool = new Pool({ connectionTimeoutMillis: 100, max: 1 })
pool.connect((err, client, release) => {
expect(err).to.be(undefined)
expect(client).to.not.be(undefined)
pool.query('select now()', (err, result) => {
expect(err).to.be.an(Error)
expect(result).to.be(undefined)
release()
pool.query('select $1::text as name', ['brianc'], (err, res) => {
expect(err).to.be(undefined)
expect(res.rows).to.have.length(1)
pool.end(done)
})
})
})
})
})

34
express-server/node_modules/pg-pool/test/ending.js generated vendored Normal file
View File

@ -0,0 +1,34 @@
'use strict'
const co = require('co')
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('pool ending', () => {
it('ends without being used', (done) => {
const pool = new Pool()
pool.end(done)
})
it('ends with a promise', () => {
return new Pool().end()
})
it('ends with clients', co.wrap(function * () {
const pool = new Pool()
const res = yield pool.query('SELECT $1::text as name', ['brianc'])
expect(res.rows[0].name).to.equal('brianc')
return pool.end()
}))
it('allows client to finish', co.wrap(function * () {
const pool = new Pool()
const query = pool.query('SELECT $1::text as name', ['brianc'])
yield pool.end()
const res = yield query
expect(res.rows[0].name).to.equal('brianc')
}))
})

View File

@ -0,0 +1,146 @@
'use strict'
const co = require('co')
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('pool error handling', function () {
it('Should complete these queries without dying', function (done) {
const pool = new Pool()
let errors = 0
let shouldGet = 0
function runErrorQuery () {
shouldGet++
return new Promise(function (resolve, reject) {
pool.query("SELECT 'asd'+1 ").then(function (res) {
reject(res) // this should always error
}).catch(function (err) {
errors++
resolve(err)
})
})
}
const ps = []
for (let i = 0; i < 5; i++) {
ps.push(runErrorQuery())
}
Promise.all(ps).then(function () {
expect(shouldGet).to.eql(errors)
pool.end(done)
})
})
describe('calling release more than once', () => {
it('should throw each time', co.wrap(function * () {
const pool = new Pool()
const client = yield pool.connect()
client.release()
expect(() => client.release()).to.throwError()
expect(() => client.release()).to.throwError()
return yield pool.end()
}))
})
describe('calling connect after end', () => {
it('should return an error', function * () {
const pool = new Pool()
const res = yield pool.query('SELECT $1::text as name', ['hi'])
expect(res.rows[0].name).to.equal('hi')
const wait = pool.end()
pool.query('select now()')
yield wait
expect(() => pool.query('select now()')).to.reject()
})
})
describe('using an ended pool', () => {
it('rejects all additional promises', (done) => {
const pool = new Pool()
const promises = []
pool.end()
.then(() => {
const squash = promise => promise.catch(e => 'okay!')
promises.push(squash(pool.connect()))
promises.push(squash(pool.query('SELECT NOW()')))
promises.push(squash(pool.end()))
Promise.all(promises).then(res => {
expect(res).to.eql(['okay!', 'okay!', 'okay!'])
done()
})
})
})
it('returns an error on all additional callbacks', (done) => {
const pool = new Pool()
pool.end(() => {
pool.query('SELECT *', (err) => {
expect(err).to.be.an(Error)
pool.connect((err) => {
expect(err).to.be.an(Error)
pool.end((err) => {
expect(err).to.be.an(Error)
done()
})
})
})
})
})
})
describe('error from idle client', () => {
it('removes client from pool', co.wrap(function * () {
const pool = new Pool()
const client = yield pool.connect()
expect(pool.totalCount).to.equal(1)
expect(pool.waitingCount).to.equal(0)
expect(pool.idleCount).to.equal(0)
client.release()
yield new Promise((resolve, reject) => {
process.nextTick(() => {
pool.once('error', (err) => {
expect(err.message).to.equal('expected')
expect(pool.idleCount).to.equal(0)
expect(pool.totalCount).to.equal(0)
pool.end().then(resolve, reject)
})
client.emit('error', new Error('expected'))
})
})
}))
})
describe('passing a function to pool.query', () => {
it('calls back with error', (done) => {
const pool = new Pool()
console.log('passing fn to query')
pool.query((err) => {
expect(err).to.be.an(Error)
pool.end(done)
})
})
})
describe('pool with lots of errors', () => {
it('continues to work and provide new clients', co.wrap(function * () {
const pool = new Pool({ max: 1 })
const errors = []
for (var i = 0; i < 20; i++) {
try {
yield pool.query('invalid sql')
} catch (err) {
errors.push(err)
}
}
expect(errors).to.have.length(20)
expect(pool.idleCount).to.equal(0)
expect(pool.query).to.be.a(Function)
const res = yield pool.query('SELECT $1::text as name', ['brianc'])
expect(res.rows).to.have.length(1)
expect(res.rows[0].name).to.equal('brianc')
return pool.end()
}))
})
})

87
express-server/node_modules/pg-pool/test/events.js generated vendored Normal file
View File

@ -0,0 +1,87 @@
'use strict'
const expect = require('expect.js')
const EventEmitter = require('events').EventEmitter
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('events', function () {
it('emits connect before callback', function (done) {
const pool = new Pool()
let emittedClient = false
pool.on('connect', function (client) {
emittedClient = client
})
pool.connect(function (err, client, release) {
if (err) return done(err)
release()
pool.end()
expect(client).to.be(emittedClient)
done()
})
})
it('emits "connect" only with a successful connection', function (done) {
const pool = new Pool({
// This client will always fail to connect
Client: mockClient({
connect: function (cb) {
process.nextTick(() => {
cb(new Error('bad news'))
setImmediate(done)
})
}
})
})
pool.on('connect', function () {
throw new Error('should never get here')
})
return pool.connect().catch(e => expect(e.message).to.equal('bad news'))
})
it('emits acquire every time a client is acquired', function (done) {
const pool = new Pool()
let acquireCount = 0
pool.on('acquire', function (client) {
expect(client).to.be.ok()
acquireCount++
})
for (let i = 0; i < 10; i++) {
pool.connect(function (err, client, release) {
if (err) return done(err)
release()
})
pool.query('SELECT now()')
}
setTimeout(function () {
expect(acquireCount).to.be(20)
pool.end(done)
}, 100)
})
it('emits error and client if an idle client in the pool hits an error', function (done) {
const pool = new Pool()
pool.connect(function (err, client) {
expect(err).to.equal(undefined)
client.release()
setImmediate(function () {
client.emit('error', new Error('problem'))
})
pool.once('error', function (err, errClient) {
expect(err.message).to.equal('problem')
expect(errClient).to.equal(client)
done()
})
})
})
})
function mockClient (methods) {
return function () {
const client = new EventEmitter()
Object.assign(client, methods)
return client
}
}

View File

@ -0,0 +1,79 @@
'use strict'
const co = require('co')
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
const wait = time => new Promise((resolve) => setTimeout(resolve, time))
describe('idle timeout', () => {
it('should timeout and remove the client', (done) => {
const pool = new Pool({ idleTimeoutMillis: 10 })
pool.query('SELECT NOW()')
pool.on('remove', () => {
expect(pool.idleCount).to.equal(0)
expect(pool.totalCount).to.equal(0)
done()
})
})
it('times out and removes clients when others are also removed', co.wrap(function * () {
const pool = new Pool({ idleTimeoutMillis: 10 })
const clientA = yield pool.connect()
const clientB = yield pool.connect()
clientA.release()
clientB.release(new Error())
const removal = new Promise((resolve) => {
pool.on('remove', () => {
expect(pool.idleCount).to.equal(0)
expect(pool.totalCount).to.equal(0)
resolve()
})
})
const timeout = wait(100).then(() =>
Promise.reject(new Error('Idle timeout failed to occur')))
try {
yield Promise.race([removal, timeout])
} finally {
pool.end()
}
}))
it('can remove idle clients and recreate them', co.wrap(function * () {
const pool = new Pool({ idleTimeoutMillis: 1 })
const results = []
for (var i = 0; i < 20; i++) {
let query = pool.query('SELECT NOW()')
expect(pool.idleCount).to.equal(0)
expect(pool.totalCount).to.equal(1)
results.push(yield query)
yield wait(2)
expect(pool.idleCount).to.equal(0)
expect(pool.totalCount).to.equal(0)
}
expect(results).to.have.length(20)
}))
it('does not time out clients which are used', co.wrap(function * () {
const pool = new Pool({ idleTimeoutMillis: 1 })
const results = []
for (var i = 0; i < 20; i++) {
let client = yield pool.connect()
expect(pool.totalCount).to.equal(1)
expect(pool.idleCount).to.equal(0)
yield wait(10)
results.push(yield client.query('SELECT NOW()'))
client.release()
expect(pool.idleCount).to.equal(1)
expect(pool.totalCount).to.equal(1)
}
expect(results).to.have.length(20)
return pool.end()
}))
})

229
express-server/node_modules/pg-pool/test/index.js generated vendored Normal file
View File

@ -0,0 +1,229 @@
'use strict'
const expect = require('expect.js')
const _ = require('lodash')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('pool', function () {
describe('with callbacks', function () {
it('works totally unconfigured', function (done) {
const pool = new Pool()
pool.connect(function (err, client, release) {
if (err) return done(err)
client.query('SELECT NOW()', function (err, res) {
release()
if (err) return done(err)
expect(res.rows).to.have.length(1)
pool.end(done)
})
})
})
it('passes props to clients', function (done) {
const pool = new Pool({ binary: true })
pool.connect(function (err, client, release) {
release()
if (err) return done(err)
expect(client.binary).to.eql(true)
pool.end(done)
})
})
it('can run a query with a callback without parameters', function (done) {
const pool = new Pool()
pool.query('SELECT 1 as num', function (err, res) {
expect(res.rows[0]).to.eql({ num: 1 })
pool.end(function () {
done(err)
})
})
})
it('can run a query with a callback', function (done) {
const pool = new Pool()
pool.query('SELECT $1::text as name', ['brianc'], function (err, res) {
expect(res.rows[0]).to.eql({ name: 'brianc' })
pool.end(function () {
done(err)
})
})
})
it('passes connection errors to callback', function (done) {
const pool = new Pool({ port: 53922 })
pool.query('SELECT $1::text as name', ['brianc'], function (err, res) {
expect(res).to.be(undefined)
expect(err).to.be.an(Error)
// a connection error should not polute the pool with a dead client
expect(pool.totalCount).to.equal(0)
pool.end(function (err) {
done(err)
})
})
})
it('does not pass client to error callback', function (done) {
const pool = new Pool({ port: 58242 })
pool.connect(function (err, client, release) {
expect(err).to.be.an(Error)
expect(client).to.be(undefined)
expect(release).to.be.a(Function)
pool.end(done)
})
})
it('removes client if it errors in background', function (done) {
const pool = new Pool()
pool.connect(function (err, client, release) {
release()
if (err) return done(err)
client.testString = 'foo'
setTimeout(function () {
client.emit('error', new Error('on purpose'))
}, 10)
})
pool.on('error', function (err) {
expect(err.message).to.be('on purpose')
expect(err.client).to.not.be(undefined)
expect(err.client.testString).to.be('foo')
err.client.connection.stream.on('end', function () {
pool.end(done)
})
})
})
it('should not change given options', function (done) {
const options = { max: 10 }
const pool = new Pool(options)
pool.connect(function (err, client, release) {
release()
if (err) return done(err)
expect(options).to.eql({ max: 10 })
pool.end(done)
})
})
it('does not create promises when connecting', function (done) {
const pool = new Pool()
const returnValue = pool.connect(function (err, client, release) {
release()
if (err) return done(err)
pool.end(done)
})
expect(returnValue).to.be(undefined)
})
it('does not create promises when querying', function (done) {
const pool = new Pool()
const returnValue = pool.query('SELECT 1 as num', function (err) {
pool.end(function () {
done(err)
})
})
expect(returnValue).to.be(undefined)
})
it('does not create promises when ending', function (done) {
const pool = new Pool()
const returnValue = pool.end(done)
expect(returnValue).to.be(undefined)
})
it('never calls callback syncronously', function (done) {
const pool = new Pool()
pool.connect((err, client) => {
if (err) throw err
client.release()
setImmediate(() => {
let called = false
pool.connect((err, client) => {
if (err) throw err
called = true
client.release()
setImmediate(() => {
pool.end(done)
})
})
expect(called).to.equal(false)
})
})
})
})
describe('with promises', function () {
it('connects, queries, and disconnects', function () {
const pool = new Pool()
return pool.connect().then(function (client) {
return client.query('select $1::text as name', ['hi']).then(function (res) {
expect(res.rows).to.eql([{ name: 'hi' }])
client.release()
return pool.end()
})
})
})
it('executes a query directly', () => {
const pool = new Pool()
return pool
.query('SELECT $1::text as name', ['hi'])
.then(res => {
expect(res.rows).to.have.length(1)
expect(res.rows[0].name).to.equal('hi')
return pool.end()
})
})
it('properly pools clients', function () {
const pool = new Pool({ poolSize: 9 })
const promises = _.times(30, function () {
return pool.connect().then(function (client) {
return client.query('select $1::text as name', ['hi']).then(function (res) {
client.release()
return res
})
})
})
return Promise.all(promises).then(function (res) {
expect(res).to.have.length(30)
expect(pool.totalCount).to.be(9)
return pool.end()
})
})
it('supports just running queries', function () {
const pool = new Pool({ poolSize: 9 })
const text = 'select $1::text as name'
const values = ['hi']
const query = { text: text, values: values }
const promises = _.times(30, () => pool.query(query))
return Promise.all(promises).then(function (queries) {
expect(queries).to.have.length(30)
return pool.end()
})
})
it('recovers from query errors', function () {
const pool = new Pool()
const errors = []
const promises = _.times(30, () => {
return pool.query('SELECT asldkfjasldkf')
.catch(function (e) {
errors.push(e)
})
})
return Promise.all(promises).then(() => {
expect(errors).to.have.length(30)
expect(pool.totalCount).to.equal(0)
expect(pool.idleCount).to.equal(0)
return pool.query('SELECT $1::text as name', ['hi']).then(function (res) {
expect(res.rows).to.eql([{ name: 'hi' }])
return pool.end()
})
})
})
})
})

20
express-server/node_modules/pg-pool/test/logging.js generated vendored Normal file
View File

@ -0,0 +1,20 @@
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('logging', function () {
it('logs to supplied log function if given', function () {
const messages = []
const log = function (msg) {
messages.push(msg)
}
const pool = new Pool({ log: log })
return pool.query('SELECT NOW()').then(function () {
expect(messages.length).to.be.greaterThan(0)
return pool.end()
})
})
})

4
express-server/node_modules/pg-pool/test/mocha.opts generated vendored Normal file
View File

@ -0,0 +1,4 @@
--require test/setup.js
--no-exit
--bail
--timeout 10000

10
express-server/node_modules/pg-pool/test/setup.js generated vendored Normal file
View File

@ -0,0 +1,10 @@
const crash = reason => {
process.on(reason, err => {
console.error(reason, err.stack)
process.exit(-1)
})
}
crash('unhandledRejection')
crash('uncaughtError')
crash('warning')

44
express-server/node_modules/pg-pool/test/sizing.js generated vendored Normal file
View File

@ -0,0 +1,44 @@
const expect = require('expect.js')
const co = require('co')
const _ = require('lodash')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('pool size of 1', () => {
it('can create a single client and use it once', co.wrap(function * () {
const pool = new Pool({ max: 1 })
expect(pool.waitingCount).to.equal(0)
const client = yield pool.connect()
const res = yield client.query('SELECT $1::text as name', ['hi'])
expect(res.rows[0].name).to.equal('hi')
client.release()
pool.end()
}))
it('can create a single client and use it multiple times', co.wrap(function * () {
const pool = new Pool({ max: 1 })
expect(pool.waitingCount).to.equal(0)
const client = yield pool.connect()
const wait = pool.connect()
expect(pool.waitingCount).to.equal(1)
client.release()
const client2 = yield wait
expect(client).to.equal(client2)
client2.release()
return yield pool.end()
}))
it('can only send 1 query at a time', co.wrap(function * () {
const pool = new Pool({ max: 1 })
const queries = _.times(20, (i) => {
return pool.query('SELECT COUNT(*) as counts FROM pg_stat_activity')
})
const results = yield Promise.all(queries)
const counts = results.map(res => parseInt(res.rows[0].counts), 10)
expect(counts).to.eql(_.times(20, i => 1))
return yield pool.end()
}))
})

View File

@ -0,0 +1,19 @@
'use strict'
const Cursor = require('pg-cursor')
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('submittle', () => {
it('is returned from the query method', false, (done) => {
const pool = new Pool()
const cursor = pool.query(new Cursor('SELECT * from generate_series(0, 1000)'))
cursor.read((err, rows) => {
expect(err).to.be(undefined)
expect(!!rows).to.be.ok()
cursor.close(done)
})
})
})

0
express-server/node_modules/pg-pool/test/timeout.js generated vendored Normal file
View File

25
express-server/node_modules/pg-pool/test/verify.js generated vendored Normal file
View File

@ -0,0 +1,25 @@
'use strict'
const expect = require('expect.js')
const describe = require('mocha').describe
const it = require('mocha').it
const Pool = require('../')
describe('verify', () => {
it('verifies a client with a callback', false, (done) => {
const pool = new Pool({
verify: (client, cb) => {
client.release()
cb(new Error('nope'))
}
})
pool.connect((err, client) => {
expect(err).to.be.an(Error)
expect(err.message).to.be('nope')
pool.end()
done()
})
})
})