From 5d27cf24e2e87704a61deade07122a722b39ede6 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 7 Oct 2013 11:52:36 -0500 Subject: [PATCH 0001/1037] Initial commit --- .gitignore | 1 + index.js | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 20 +++++++++ test/index.js | 94 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 231 insertions(+) create mode 100644 .gitignore create mode 100644 index.js create mode 100644 package.json create mode 100644 test/index.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/index.js b/index.js new file mode 100644 index 000000000..8960a3523 --- /dev/null +++ b/index.js @@ -0,0 +1,116 @@ +var path = require('path') + +var resultPath = path.dirname(require.resolve('pg.js')) + '/lib/result' +var Result = require(resultPath) +var Client = require('pg.js').Client + +var Cursor = function(text, values) { + this.text = text + this.values = values + this._connection = null +} + +Cursor.prototype._connect = function(cb) { + if(this._connected) return setImmediate(cb); + this._connected = true + var self = this + var client = new Client() + client.connect(function(err) { + if(err) return cb(err); + + //remove all listeners from + //client's connection and discard the client + self.connection = client.connection + self.connection.removeAllListeners() + + var con = self.connection + + con.parse({ + text: self.text + }, true) + + con.bind({ + values: self.values + }, true) + + con.describe({ + type: 'P', + name: '' //use unamed portal + }, true) + + con.flush() + + var onError = function(err) { + cb(err) + con.end() + } + + con.once('error', onError) + + con.on('rowDescription', function(msg) { + self.rowDescription = msg + con.removeListener('error', onError) + cb(null, con) + }) + + var onRow = function(msg) { + var row = self.result.parseRow(msg.fields) + self.result.addRow(row) + } + + con.on('dataRow', onRow) + + con.once('readyForQuery', function() { + con.end() + }) + + con.once('commandComplete', function() { + self._complete = true + con.sync() + }) + }) +} + +Cursor.prototype._getRows = function(con, n, cb) { + if(this._done) { + return cb(null, [], false) + } + var msg = { + portal: '', + rows: n + } + con.execute(msg, true) + con.flush() + this.result = new Result() + this.result.addFields(this.rowDescription.fields) + + var self = this + + var onComplete = function() { + self._done = true + cb(null, self.result.rows, self.result) + } + con.once('commandComplete', onComplete) + + con.once('portalSuspended', function() { + cb(null, self.result.rows, self.result) + con.removeListener('commandComplete', onComplete) + }) +} + +Cursor.prototype.end = function(cb) { + this.connection.end() + this.connection.stream.once('end', cb) +} + +Cursor.prototype.read = function(rows, cb) { + var self = this + this._connect(function(err) { + if(err) return cb(err); + self._getRows(self.connection, rows, cb) + }) +} + +module.exports = function(query, params) { + return new Cursor(query, params) +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..993f57a0e --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "node-pg-cursor", + "version": "0.0.0", + "description": "", + "main": "index.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "BSD", + "devDependencies": { + "gonna": "0.0.0" + }, + "dependencies": { + "pg.js": "~2.7.0" + } +} diff --git a/test/index.js b/test/index.js new file mode 100644 index 000000000..4d45a85cc --- /dev/null +++ b/test/index.js @@ -0,0 +1,94 @@ +var assert = require('assert') +var pgCursor = require('../') +var gonna = require('gonna') + +var text = 'SELECT generate_series as num FROM generate_series(0, 5)' +var values = [] + +var test = function(name, fn, timeout) { + timeout = timeout || 1000 + var done = gonna(name, timeout, function(err) { + console.log(name) + assert.ifError(err) + }) + fn(done) +} + +test('fetch 6 when asking for 10', function(done) { + var cursor = pgCursor(text) + cursor.read(10, function(err, res) { + assert.ifError(err) + assert.equal(res.length, 6) + done() + }) +}) + +test('end before reading to end', function(done) { + var cursor = pgCursor(text) + cursor.read(3, function(err, res) { + assert.equal(res.length, 3) + cursor.end(done) + }) +}) + +test('callback with error', function(done) { + var cursor = pgCursor('select asdfasdf') + cursor.read(1, function(err) { + assert(err) + done() + }) +}) + + +test('read a partial chunk of data', function(done) { + var cursor = pgCursor(text) + cursor.read(2, function(err, res) { + assert.equal(res.length, 2) + cursor.read(3, function(err, res) { + assert.equal(res.length, 3) + cursor.read(1, function(err, res) { + assert.equal(res.length, 1) + cursor.read(1, function(err, res) { + assert.ifError(err) + assert.strictEqual(res.length, 0) + done() + }) + }) + }) + }) +}) + +test('read return length 0 past the end', function(done) { + var cursor = pgCursor(text) + cursor.read(2, function(err, res) { + cursor.read(100, function(err, res) { + assert.equal(res.length, 4) + cursor.read(100, function(err, res) { + assert.equal(res.length, 0) + done() + }) + }) + }) +}) + +test('read huge result', function(done) { + var text = 'SELECT generate_series as num FROM generate_series(0, 1000000)' + var values = [] + cursor = pgCursor(text, values); + var count = 0; + var more = function() { + cursor.read(1000, function(err, rows) { + if(err) return done(err); + if(!rows.length) { + assert.equal(count, 1000001) + return done() + } + count += rows.length; + if(count%100000 == 0) { + console.log(count) + } + setImmediate(more) + }) + } + more() +}, 100000) From fc875b0c1d4f5730a52ef538afce58b694690554 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 7 Oct 2013 11:54:23 -0500 Subject: [PATCH 0002/1037] Rename method --- test/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/index.js b/test/index.js index 4d45a85cc..5552b14c4 100644 --- a/test/index.js +++ b/test/index.js @@ -76,7 +76,7 @@ test('read huge result', function(done) { var values = [] cursor = pgCursor(text, values); var count = 0; - var more = function() { + var read = function() { cursor.read(1000, function(err, rows) { if(err) return done(err); if(!rows.length) { @@ -90,5 +90,5 @@ test('read huge result', function(done) { setImmediate(more) }) } - more() + read() }, 100000) From 31fd30d329bcc9d18214243858ebcf878ddcedc4 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 7 Oct 2013 11:54:58 -0500 Subject: [PATCH 0003/1037] Fix test --- test/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.js b/test/index.js index 5552b14c4..e6988c92e 100644 --- a/test/index.js +++ b/test/index.js @@ -87,7 +87,7 @@ test('read huge result', function(done) { if(count%100000 == 0) { console.log(count) } - setImmediate(more) + setImmediate(read) }) } read() From 8a3b3d416780a4dba7abfa212befc99a0aa55abb Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 7 Oct 2013 14:29:28 -0500 Subject: [PATCH 0004/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 993f57a0e..adb2dcd18 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-pg-cursor", - "version": "0.0.0", + "version": "0.0.1", "description": "", "main": "index.js", "directories": { From 722296f8d2cccfc58536b51699ec741f2124e654 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 21 Oct 2013 23:57:50 -0500 Subject: [PATCH 0005/1037] Initial commit --- .gitignore | 1 + Makefile | 5 ++ README.md | 71 ++++++++++++++++++++++++++++ index.js | 105 ++++++++++++++++++++++++++++++++++++++++++ package.json | 35 ++++++++++++++ test/concat.js | 26 +++++++++++ test/fast-reader.js | 29 ++++++++++++ test/pauses.js | 25 ++++++++++ test/stream-tester.js | 21 +++++++++ 9 files changed, 318 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 README.md create mode 100644 index.js create mode 100644 package.json create mode 100644 test/concat.js create mode 100644 test/fast-reader.js create mode 100644 test/pauses.js create mode 100644 test/stream-tester.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..fc9212a7c --- /dev/null +++ b/Makefile @@ -0,0 +1,5 @@ +SHELL := /bin/sh +.PHONY: test + +test: + find test/ -name "*.js" | xargs -n 1 node diff --git a/README.md b/README.md new file mode 100644 index 000000000..d16827a0c --- /dev/null +++ b/README.md @@ -0,0 +1,71 @@ +# pg-query-stream + +Receive result rows from [pg](https://github.com/brianc/node-postgres) as a readable (object) stream. + +This module __only works with the pure JavaScript client__. + +## installation + +```bash +$ npm install pg +$ npm install pg-query-stream +``` + +_requires pg>=2.8.1_ + +##### - or - + +```bash +$ npm install pg.js +$ npm install pg-query-stream +``` + +_requires pg.js>=2.8.1_ + +## use + +```js +var pg = require('pg') +var QueryStream = require('pg-query-stream') +var JSONStream = require('JSONStream') + +//pipe 1,000,000 rows to stdout without blowing up your memory usage +pg.connect(function(err, client, done) { + if(err) throw err; + var query = new QueryStream('SELECT * FROM generate_series(0, $1) num', [1000000]) + var stream = client.query(query) + stream.pipe(JSONStream.stringify()).pipe(process.stdout) +}) +``` + +The stream uses a cursor on the server so it efficiently keeps only a low number of rows in memory. + +This is especially useful when doing [ETL](http://en.wikipedia.org/wiki/Extract,_transform,_load) on a huge table. Using manual `limit` and `offset` queries to fake out async itteration through your data is cumbersom, and _way way way_ slower than using a cursor. + +## contribution + +I'm very open to contribution! Open a pull request with your code or idea and we'll talk about it. If it's not way insane we'll merge it in too: isn't open source awesome? + +## license + +The MIT License (MIT) + +Copyright (c) 2013 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. diff --git a/index.js b/index.js new file mode 100644 index 000000000..a8b204491 --- /dev/null +++ b/index.js @@ -0,0 +1,105 @@ +var assert = require('assert') +var Readable = require('stream').Readable +var Result = require('pg') + +var path = require('path') + +var pgdir = false +try { + pgdir = path.dirname(require.resolve('pg')) +} catch (e) { + pgdir = path.dirname(require.resolve('pg.js')) +} +if(!pgdir) { + throw new Error("Please install either `pg` or `pg.js` to use this module") +} +var Result = require(path.join(pgdir, 'result')) +var utils = require(path.join(pgdir, 'utils')) + +var QueryStream = module.exports = function(text, values, options) { + options = options || { + highWaterMark: 100, + batchSize: 100 + } + Readable.call(this, { + objectMode: true, + highWaterMark: 100 + }) + this.text = text + assert(this.text, 'text cannot be falsy') + this.values = (values || []).map(utils.prepareValue) + this.name = '' + this._result = new Result() + this.batchSize = 100 + this._idle = true +} + +require('util').inherits(QueryStream, Readable) + +QueryStream.prototype._read = function(n) { + this._getRows(n) +} + +QueryStream.prototype._getRows = function(count) { + var con = this.connection + if(!this._idle || !this.connection) return; + this._idle = false + con.execute({ + portal: '', + rows: count + }, true) + + con.flush() +} + +QueryStream.prototype.submit = function(con) { + //save reference to connection + this.connection = con + + var name = this.name + + con.parse({ + text: this.text, + name: name, + types: [] + }, true) + + con.bind({ + portal: '', + statement: name, + values: this.values, + binary: false + }, true) + + con.describe({ + type: 'P', + name: name + }, true) + + this._getRows(this.batchSize) + +} + +QueryStream.prototype.handleRowDescription = function(msg) { + this._result.addFields(msg.fields) +} + +QueryStream.prototype.handleDataRow = function(msg) { + var row = this._result.parseRow(msg.fields) + this._more = this.push(row) +} + +QueryStream.prototype.handlePortalSuspended = function(msg) { + this._idle = true + if(this._more) { + this._getRows(this.batchSize) + } +} + +QueryStream.prototype.handleCommandComplete = function(msg) { + this.connection.sync() +} + +QueryStream.prototype.handleReadyForQuery = function() { + this.push(null) +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..0a2b34731 --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "pg-query-stream", + "version": "0.0.0", + "description": "Postgres query result returned as readable stream", + "main": "index.js", + "scripts": { + "test": "node test" + }, + "repository": { + "type": "git", + "url": "git://github.com/brianc/node-pg-query-stream.git" + }, + "keywords": [ + "postgres", + "pg", + "query", + "stream" + ], + "author": "Brian M. Carlson", + "license": "BSD-2-Clause", + "bugs": { + "url": "https://github.com/brianc/node-pg-query-stream/issues" + }, + "devDependencies": { + "pg.js": "~2.8.0", + "gonna": "0.0.0", + "lodash": "~2.2.1", + "concat-stream": "~1.0.1", + "through": "~2.3.4", + "stream-tester": "0.0.5", + "stream-spec": "~0.3.5", + "jsonstream": "0.0.1", + "JSONStream": "~0.7.1" + } +} diff --git a/test/concat.js b/test/concat.js new file mode 100644 index 000000000..b97ea4c19 --- /dev/null +++ b/test/concat.js @@ -0,0 +1,26 @@ +var pg = require('pg') +var assert = require('assert') +var gonna = require('gonna') +var _ = require('lodash') +var concat = require('concat-stream') +var through = require('through') + +var QueryStream = require('../') + +var client = new pg.Client() + +var connected = gonna('connect', 100, function() { + var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) + var query = client.query(stream) + query.pipe(through(function(row) { + this.push(row.num) + })).pipe(concat(function(result) { + var total = result.reduce(function(prev, cur) { + return prev + cur + }) + assert.equal(total, 20100) + })) + stream.on('end', client.end.bind(client)) +}) + +client.connect(connected) diff --git a/test/fast-reader.js b/test/fast-reader.js new file mode 100644 index 000000000..629848fb6 --- /dev/null +++ b/test/fast-reader.js @@ -0,0 +1,29 @@ +var pg = require('pg') +var assert = require('assert') +var gonna = require('gonna') +var _ = require('lodash') + +var QueryStream = require('../') + +var client = new pg.Client() + +var connected = gonna('connect', 100, function() { + var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) + var query = client.query(stream) + var result = [] + stream.on('readable', function() { + var res = stream.read() + assert(res, 'should not return null on evented reader') + result.push(res.num) + }) + stream.on('end', client.end.bind(client)) + stream.on('end', function() { + var total = result.reduce(function(prev, cur) { + return prev + cur + }) + assert.equal(total, 20100) + }) + assert.strictEqual(query.read(2), null) +}) + +client.connect(connected) diff --git a/test/pauses.js b/test/pauses.js new file mode 100644 index 000000000..7c61c8e8f --- /dev/null +++ b/test/pauses.js @@ -0,0 +1,25 @@ +var pg = require('pg') +var assert = require('assert') +var gonna = require('gonna') +var _ = require('lodash') +var concat = require('concat-stream') +var through = require('through') +var tester = require('stream-tester') +var JSONStream = require('JSONStream') +var stream = require('stream') + +var QueryStream = require('../') + +var client = new pg.Client() + +var connected = gonna('connect', 100, function() { + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], {chunkSize: 2, highWaterMark: 2}) + var query = client.query(stream) + var pauser = tester.createPauseStream(0.1, 100) + query.pipe(JSONStream.stringify()).pipe(concat(function(json) { + JSON.parse(json) + client.end() + })) +}) + +client.connect(connected) diff --git a/test/stream-tester.js b/test/stream-tester.js new file mode 100644 index 000000000..6975247a5 --- /dev/null +++ b/test/stream-tester.js @@ -0,0 +1,21 @@ +var pg = require('pg') +var assert = require('assert') +var gonna = require('gonna') +var tester = require('stream-tester') + +var QueryStream = require('../') + +var client = new pg.Client() + +var connected = gonna('connect', 100, function() { + var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) + var spec = require('stream-spec') + var query = client.query(stream) + spec(query) + .readable() + .pausable({strict: true}) + .validateOnExit() + stream.on('end', client.end.bind(client)) +}) + +client.connect(connected) From 5400dfeffda8a1b647b346717583135dc0bba76b Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 22 Oct 2013 11:24:30 -0500 Subject: [PATCH 0006/1037] Remove bad code --- index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/index.js b/index.js index a8b204491..7822ce26a 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,5 @@ var assert = require('assert') var Readable = require('stream').Readable -var Result = require('pg') var path = require('path') From cc20d98cb02857317693cd7b371f5b55058573fd Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 22 Oct 2013 11:24:41 -0500 Subject: [PATCH 0007/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0a2b34731..bbcf9ab5c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "0.0.0", + "version": "0.1.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From 48687fc18283cc32d53882f5d52e6c9fbaccc1c3 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 22 Oct 2013 11:36:05 -0500 Subject: [PATCH 0008/1037] Fix relative load path for pg.js --- index.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 7822ce26a..d92e84025 100644 --- a/index.js +++ b/index.js @@ -8,9 +8,10 @@ try { pgdir = path.dirname(require.resolve('pg')) } catch (e) { pgdir = path.dirname(require.resolve('pg.js')) -} -if(!pgdir) { - throw new Error("Please install either `pg` or `pg.js` to use this module") + if(!pgdir) { + throw new Error("Please install either `pg` or `pg.js` to use this module") + } + pgdir = path.join(pgdir, 'lib') } var Result = require(path.join(pgdir, 'result')) var utils = require(path.join(pgdir, 'utils')) From aec85ce0d636cc070cfcdfa4991095dd3dfb12b9 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 22 Oct 2013 11:36:11 -0500 Subject: [PATCH 0009/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bbcf9ab5c..3ef254020 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "0.1.0", + "version": "0.1.1", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From 1b249e9ceb764c44e776b2f261fb726f0c06781b Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 22 Oct 2013 13:19:28 -0500 Subject: [PATCH 0010/1037] Add in proper error handling --- index.js | 5 +++++ test/error.js | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 test/error.js diff --git a/index.js b/index.js index d92e84025..45b26223f 100644 --- a/index.js +++ b/index.js @@ -103,3 +103,8 @@ QueryStream.prototype.handleCommandComplete = function(msg) { QueryStream.prototype.handleReadyForQuery = function() { this.push(null) } + +QueryStream.prototype.handleError = function(err) { + this.connection.sync() + this.emit('error', err) +} diff --git a/test/error.js b/test/error.js new file mode 100644 index 000000000..aa3da4901 --- /dev/null +++ b/test/error.js @@ -0,0 +1,24 @@ +var pg = require('pg') +var assert = require('assert') +var gonna = require('gonna') +var _ = require('lodash') +var concat = require('concat-stream') +var through = require('through') + +var QueryStream = require('../') + +var client = new pg.Client() + +var connected = gonna('connect', 100, function() { + var stream = new QueryStream('SELECT * FROM asdf num', []) + var query = client.query(stream) + query.on('error', gonna('emit error', 100, function(err) { + assert(err) + assert.equal(err.code, '42P01') + })) + var done = gonna('keep connetion alive', 100) + client.query('SELECT NOW()', done) +}) + +client.connect(connected) +client.on('drain', client.end.bind(client)) From 58881357a24afb17c107d9ca990994df90675be2 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 22 Oct 2013 13:19:48 -0500 Subject: [PATCH 0011/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ef254020..26a4ebdf7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "0.1.1", + "version": "0.1.2", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From 278c5ceb878c44bd0031740f6a124996e59dd8e8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 22 Oct 2013 13:20:46 -0500 Subject: [PATCH 0012/1037] Update npm test command --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 26a4ebdf7..d7c0af8df 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { - "test": "node test" + "test": "make test" }, "repository": { "type": "git", From 33be525dbb2ad6f2c701539d3dd17ce5baa0c165 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 23 Oct 2013 17:11:43 -0500 Subject: [PATCH 0013/1037] Add ability to configure highWaterMark and batchSize --- index.js | 9 +++------ test/config.js | 10 ++++++++++ test/instant.js | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 test/config.js create mode 100644 test/instant.js diff --git a/index.js b/index.js index 45b26223f..b29eab0c9 100644 --- a/index.js +++ b/index.js @@ -17,20 +17,17 @@ var Result = require(path.join(pgdir, 'result')) var utils = require(path.join(pgdir, 'utils')) var QueryStream = module.exports = function(text, values, options) { - options = options || { - highWaterMark: 100, - batchSize: 100 - } + options = options || { } Readable.call(this, { objectMode: true, - highWaterMark: 100 + highWaterMark: options.highWaterMark || 1000 }) this.text = text assert(this.text, 'text cannot be falsy') this.values = (values || []).map(utils.prepareValue) this.name = '' this._result = new Result() - this.batchSize = 100 + this.batchSize = options.batchSize || 100 this._idle = true } diff --git a/test/config.js b/test/config.js new file mode 100644 index 000000000..4ed5b1b93 --- /dev/null +++ b/test/config.js @@ -0,0 +1,10 @@ +var assert = require('assert') +var QueryStream = require('../') + +var stream = new QueryStream('SELECT NOW()', [], { + highWaterMark: 999, + batchSize: 88 +}) + +assert.equal(stream._readableState.highWaterMark, 999) +assert.equal(stream.batchSize, 88) diff --git a/test/instant.js b/test/instant.js new file mode 100644 index 000000000..1b245162b --- /dev/null +++ b/test/instant.js @@ -0,0 +1,17 @@ +var pg = require('pg') +var assert = require('assert') +var gonna = require('gonna') +var concat = require('concat-stream') + +var QueryStream = require('../') + +var client = new pg.Client() +var query = new QueryStream('SELECT pg_sleep(1)', []) +var stream = client.query(query) +var done = gonna('read results', 5000) +stream.pipe(concat(function(res) { + assert.equal(res.length, 1) + done() + client.end() +})) +client.connect() From 0ebd4c3bbb464b3de842f9209bca383f763c8147 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 23 Oct 2013 17:11:49 -0500 Subject: [PATCH 0014/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d7c0af8df..841a100b5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "0.1.2", + "version": "0.2.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From 40af7c2f4a74f044c7f2fc69fa17603114ae8fd0 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 8 Nov 2013 16:50:17 -0600 Subject: [PATCH 0015/1037] Update package.jsn --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index adb2dcd18..aac33aeee 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "node-pg-cursor", + "name": "pg-cursor", "version": "0.0.1", "description": "", "main": "index.js", @@ -7,10 +7,10 @@ "test": "test" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "node test/" }, - "author": "", - "license": "BSD", + "author": "Brian M. Carlson", + "license": "MIT", "devDependencies": { "gonna": "0.0.0" }, From 9e2f6224035a0b3abd0d3c60fe0586dfa5e0360f Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 8 Nov 2013 17:07:54 -0600 Subject: [PATCH 0016/1037] Port tests to use mocha --- package.json | 6 ++---- test/index.js | 24 ++++++++---------------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index aac33aeee..962c9e859 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,7 @@ "author": "Brian M. Carlson", "license": "MIT", "devDependencies": { - "gonna": "0.0.0" - }, - "dependencies": { - "pg.js": "~2.7.0" + "mocha": "https://github.com/visionmedia/mocha/tarball/master", + "pg.js": "~2.8.1" } } diff --git a/test/index.js b/test/index.js index e6988c92e..6f13a2ef9 100644 --- a/test/index.js +++ b/test/index.js @@ -5,16 +5,7 @@ var gonna = require('gonna') var text = 'SELECT generate_series as num FROM generate_series(0, 5)' var values = [] -var test = function(name, fn, timeout) { - timeout = timeout || 1000 - var done = gonna(name, timeout, function(err) { - console.log(name) - assert.ifError(err) - }) - fn(done) -} - -test('fetch 6 when asking for 10', function(done) { +it('fetch 6 when asking for 10', function(done) { var cursor = pgCursor(text) cursor.read(10, function(err, res) { assert.ifError(err) @@ -23,7 +14,7 @@ test('fetch 6 when asking for 10', function(done) { }) }) -test('end before reading to end', function(done) { +it('end before reading to end', function(done) { var cursor = pgCursor(text) cursor.read(3, function(err, res) { assert.equal(res.length, 3) @@ -31,7 +22,7 @@ test('end before reading to end', function(done) { }) }) -test('callback with error', function(done) { +it('callback with error', function(done) { var cursor = pgCursor('select asdfasdf') cursor.read(1, function(err) { assert(err) @@ -40,7 +31,7 @@ test('callback with error', function(done) { }) -test('read a partial chunk of data', function(done) { +it('read a partial chunk of data', function(done) { var cursor = pgCursor(text) cursor.read(2, function(err, res) { assert.equal(res.length, 2) @@ -58,7 +49,7 @@ test('read a partial chunk of data', function(done) { }) }) -test('read return length 0 past the end', function(done) { +it('read return length 0 past the end', function(done) { var cursor = pgCursor(text) cursor.read(2, function(err, res) { cursor.read(100, function(err, res) { @@ -71,7 +62,8 @@ test('read return length 0 past the end', function(done) { }) }) -test('read huge result', function(done) { +it('read huge result', function(done) { + this.timeout(10000) var text = 'SELECT generate_series as num FROM generate_series(0, 1000000)' var values = [] cursor = pgCursor(text, values); @@ -91,4 +83,4 @@ test('read huge result', function(done) { }) } read() -}, 100000) +}) From 2e33d4acc09d8a69dfcdc6a34f7f63b5f2aacf66 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 8 Nov 2013 17:08:55 -0600 Subject: [PATCH 0017/1037] Add default mocha options --- test/index.js | 2 +- test/mocha.opts | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 test/mocha.opts diff --git a/test/index.js b/test/index.js index 6f13a2ef9..a9d1efe4c 100644 --- a/test/index.js +++ b/test/index.js @@ -77,7 +77,7 @@ it('read huge result', function(done) { } count += rows.length; if(count%100000 == 0) { - console.log(count) + //console.log(count) } setImmediate(read) }) diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 000000000..8fd0f04e3 --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1,3 @@ +--no-exit +--bail +--reporter=spec From 31b2b1da6f102b70120df13c27b87b64a6480fe0 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 11 Nov 2013 23:20:04 -0600 Subject: [PATCH 0018/1037] All tests passing in isolation Still have weird race conditions & shutdown/error/resume conditions to tackle --- index.js | 171 ++++++++++++++++++++++++++------------------------ result.js | 12 ++++ test/index.js | 145 ++++++++++++++++++++++++------------------ 3 files changed, 185 insertions(+), 143 deletions(-) create mode 100644 result.js diff --git a/index.js b/index.js index 8960a3523..37c59ed31 100644 --- a/index.js +++ b/index.js @@ -1,116 +1,125 @@ -var path = require('path') - -var resultPath = path.dirname(require.resolve('pg.js')) + '/lib/result' -var Result = require(resultPath) -var Client = require('pg.js').Client +var Result = require('./result') var Cursor = function(text, values) { this.text = text this.values = values - this._connection = null + this.connection = null + this._queue = [] + this.state = 'initialized' + this._result = new Result() + this._cb = null + this._rows = null } -Cursor.prototype._connect = function(cb) { - if(this._connected) return setImmediate(cb); - this._connected = true - var self = this - var client = new Client() - client.connect(function(err) { - if(err) return cb(err); - - //remove all listeners from - //client's connection and discard the client - self.connection = client.connection - self.connection.removeAllListeners() +Cursor.prototype.submit = function(connection) { + this.connection = connection - var con = self.connection + var con = connection + var self = this - con.parse({ - text: self.text - }, true) + con.parse({ + text: this.text + }, true) - con.bind({ - values: self.values - }, true) + con.bind({ + values: this.values + }, true) - con.describe({ - type: 'P', - name: '' //use unamed portal - }, true) + con.describe({ + type: 'P', + name: '' //use unamed portal + }, true) - con.flush() + con.flush() +} - var onError = function(err) { - cb(err) - con.end() - } +Cursor.prototype.handleRowDescription = function(msg) { + this._result.addFields(msg.fields) + this.state = 'idle' + if(this._queue.length) { + this._getRows.apply(this, this._queue.shift()) + } +} - con.once('error', onError) +Cursor.prototype.handleDataRow = function(msg) { + var row = this._result.parseRow(msg.fields) + this._rows.push(row) +} - con.on('rowDescription', function(msg) { - self.rowDescription = msg - con.removeListener('error', onError) - cb(null, con) - }) +Cursor.prototype._sendRows = function() { + this.state = 'idle' + setImmediate(function() { + this._cb(null, this._rows) + this._rows = [] + }.bind(this)) +} - var onRow = function(msg) { - var row = self.result.parseRow(msg.fields) - self.result.addRow(row) - } +Cursor.prototype.handleCommandComplete = function() { + this._sendRows() + this.state = 'done' + this.connection.sync() +} - con.on('dataRow', onRow) +Cursor.prototype.handlePortalSuspended = function() { + this._sendRows() +} - con.once('readyForQuery', function() { - con.end() - }) +Cursor.prototype.handleReadyForQuery = function() { - con.once('commandComplete', function() { - self._complete = true - con.sync() - }) - }) } -Cursor.prototype._getRows = function(con, n, cb) { - if(this._done) { - return cb(null, [], false) +Cursor.prototype.handleError = function(msg) { + this.state = 'error' + this._error = msg + //satisfy any waiting callback + if(this._cb) { + this._cb(msg) } - var msg = { - portal: '', - rows: n + //dispatch error to all waiting callbacks + for(var i = 0; i < this._queue.length; i++) { + this._queue.pop()[1](msg) } - con.execute(msg, true) - con.flush() - this.result = new Result() - this.result.addFields(this.rowDescription.fields) - - var self = this +} - var onComplete = function() { - self._done = true - cb(null, self.result.rows, self.result) +Cursor.prototype._getRows = function(rows, cb) { + console.log('get', rows) + this.state = 'busy' + this._cb = cb + this._rows = [] + var msg = { + portal: '', + rows: rows } - con.once('commandComplete', onComplete) - - con.once('portalSuspended', function() { - cb(null, self.result.rows, self.result) - con.removeListener('commandComplete', onComplete) - }) + this.connection.execute(msg, true) + this.connection.flush() } Cursor.prototype.end = function(cb) { + if(this.statue != 'initialized') { + this.connection.sync() + } this.connection.end() this.connection.stream.once('end', cb) } Cursor.prototype.read = function(rows, cb) { + console.log('read', rows, this.state) var self = this - this._connect(function(err) { - if(err) return cb(err); - self._getRows(self.connection, rows, cb) - }) + if(this.state == 'idle') { + return this._getRows(rows, cb) + } + if(this.state == 'busy' || this.state == 'initialized') { + return this._queue.push([rows, cb]) + } + if(this.state == 'error') { + return cb(this._error) + } + if(this.state == 'done') { + return cb(null, []) + } + else { + throw new Error("Unknown state: " + this.state) + } } -module.exports = function(query, params) { - return new Cursor(query, params) -} +module.exports = Cursor diff --git a/result.js b/result.js new file mode 100644 index 000000000..3e11636bd --- /dev/null +++ b/result.js @@ -0,0 +1,12 @@ +var path = require('path') +var pgPath; +//support both pg & pg.js +//this will eventually go away when i break native bindings +//out into their own module +try { + pgPath = path.dirname(require.resolve('pg')) +} catch(e) { + pgPath = path.dirname(require.resolve('pg.js')) +} + +module.exports = require(path.join(pgPath, 'lib', 'result.js')) diff --git a/test/index.js b/test/index.js index a9d1efe4c..89fbf6ebb 100644 --- a/test/index.js +++ b/test/index.js @@ -1,86 +1,107 @@ var assert = require('assert') -var pgCursor = require('../') -var gonna = require('gonna') +var Cursor = require('../') +var pg = require('pg.js') var text = 'SELECT generate_series as num FROM generate_series(0, 5)' -var values = [] -it('fetch 6 when asking for 10', function(done) { - var cursor = pgCursor(text) - cursor.read(10, function(err, res) { - assert.ifError(err) - assert.equal(res.length, 6) - done() - }) -}) +describe('cursor', function() { -it('end before reading to end', function(done) { - var cursor = pgCursor(text) - cursor.read(3, function(err, res) { - assert.equal(res.length, 3) - cursor.end(done) + var client; + + var pgCursor = function(text, values) { + client.connect() + client.on('drain', client.end.bind(client)) + return client.query(new Cursor(text, values || [])) + } + + before(function() { + client = new pg.Client() }) -}) -it('callback with error', function(done) { - var cursor = pgCursor('select asdfasdf') - cursor.read(1, function(err) { - assert(err) - done() + + after(function() { + client.end() }) -}) + it('fetch 6 when asking for 10', function(done) { + var cursor = pgCursor(text) + cursor.read(10, function(err, res) { + assert.ifError(err) + assert.equal(res.length, 6) + done() + }) + }) -it('read a partial chunk of data', function(done) { - var cursor = pgCursor(text) - cursor.read(2, function(err, res) { - assert.equal(res.length, 2) + it('end before reading to end', function(done) { + var cursor = pgCursor(text) cursor.read(3, function(err, res) { + assert.ifError(err) assert.equal(res.length, 3) - cursor.read(1, function(err, res) { - assert.equal(res.length, 1) + cursor.end(done) + }) + }) + + it('callback with error', function(done) { + var cursor = pgCursor('select asdfasdf') + cursor.read(1, function(err) { + assert(err) + done() + }) + }) + + + it('read a partial chunk of data', function(done) { + var cursor = pgCursor(text) + cursor.read(2, function(err, res) { + assert.ifError(err) + assert.equal(res.length, 2) + cursor.read(3, function(err, res) { + assert.equal(res.length, 3) cursor.read(1, function(err, res) { - assert.ifError(err) - assert.strictEqual(res.length, 0) - done() + assert.equal(res.length, 1) + cursor.read(1, function(err, res) { + assert.ifError(err) + assert.strictEqual(res.length, 0) + done() + }) }) }) }) }) -}) -it('read return length 0 past the end', function(done) { - var cursor = pgCursor(text) - cursor.read(2, function(err, res) { - cursor.read(100, function(err, res) { - assert.equal(res.length, 4) + it('read return length 0 past the end', function(done) { + var cursor = pgCursor(text) + cursor.read(2, function(err, res) { cursor.read(100, function(err, res) { - assert.equal(res.length, 0) - done() + assert.equal(res.length, 4) + cursor.read(100, function(err, res) { + assert.equal(res.length, 0) + done() + }) }) }) }) -}) -it('read huge result', function(done) { - this.timeout(10000) - var text = 'SELECT generate_series as num FROM generate_series(0, 1000000)' - var values = [] - cursor = pgCursor(text, values); - var count = 0; - var read = function() { - cursor.read(1000, function(err, rows) { - if(err) return done(err); - if(!rows.length) { - assert.equal(count, 1000001) - return done() - } - count += rows.length; - if(count%100000 == 0) { - //console.log(count) - } - setImmediate(read) - }) - } - read() + it('read huge result', function(done) { + this.timeout(10000) + var text = 'SELECT generate_series as num FROM generate_series(0, 1000000)' + var values = [] + cursor = pgCursor(text, values); + var count = 0; + var read = function() { + cursor.read(1000, function(err, rows) { + if(err) return done(err); + if(!rows.length) { + assert.equal(count, 1000001) + return done() + } + count += rows.length; + if(count%100000 == 0) { + //console.log(count) + } + setImmediate(read) + }) + } + read() + }) }) From 9af987fa63b9260906b4c49a769bc601c6638aec Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 20 Nov 2013 22:30:52 -0600 Subject: [PATCH 0019/1037] Pass all tests --- index.js | 5 ++--- test/error-handling.js | 40 ++++++++++++++++++++++++++++++++++++++++ test/index.js | 40 +++++++++++++++++++--------------------- 3 files changed, 61 insertions(+), 24 deletions(-) create mode 100644 test/error-handling.js diff --git a/index.js b/index.js index 37c59ed31..9b14f0f00 100644 --- a/index.js +++ b/index.js @@ -65,7 +65,6 @@ Cursor.prototype.handlePortalSuspended = function() { } Cursor.prototype.handleReadyForQuery = function() { - } Cursor.prototype.handleError = function(msg) { @@ -79,10 +78,11 @@ Cursor.prototype.handleError = function(msg) { for(var i = 0; i < this._queue.length; i++) { this._queue.pop()[1](msg) } + //call sync to keep this connection from hanging + this.connection.sync() } Cursor.prototype._getRows = function(rows, cb) { - console.log('get', rows) this.state = 'busy' this._cb = cb this._rows = [] @@ -103,7 +103,6 @@ Cursor.prototype.end = function(cb) { } Cursor.prototype.read = function(rows, cb) { - console.log('read', rows, this.state) var self = this if(this.state == 'idle') { return this._getRows(rows, cb) diff --git a/test/error-handling.js b/test/error-handling.js new file mode 100644 index 000000000..044c96242 --- /dev/null +++ b/test/error-handling.js @@ -0,0 +1,40 @@ +var assert = require('assert') +var Cursor = require('../') +var pg = require('pg.js') + +var text = 'SELECT generate_series as num FROM generate_series(0, 4)' + +describe('error handling', function() { + it('can continue after error', function(done) { + var client = new pg.Client() + client.connect() + var cursor = client.query(new Cursor('asdfdffsdf')) + cursor.read(1, function(err) { + assert(err) + client.query('SELECT NOW()', function(err, res) { + assert.ifError(err) + client.end() + done() + }) + }) + }) +}) + +describe('proper cleanup', function() { + it('can issue multiple cursors on one client', function(done) { + var client = new pg.Client() + client.connect() + var cursor1 = client.query(new Cursor(text)) + cursor1.read(8, function(err, rows) { + assert.ifError(err) + assert.equal(rows.length, 5) + cursor2 = client.query(new Cursor(text)) + cursor2.read(8, function(err, rows) { + assert.ifError(err) + assert.equal(rows.length, 5) + client.end() + done() + }) + }) + }) +}) diff --git a/test/index.js b/test/index.js index 89fbf6ebb..6ff312604 100644 --- a/test/index.js +++ b/test/index.js @@ -6,25 +6,23 @@ var text = 'SELECT generate_series as num FROM generate_series(0, 5)' describe('cursor', function() { - var client; + beforeEach(function(done) { + var client = this.client = new pg.Client() + client.connect(done) - var pgCursor = function(text, values) { - client.connect() - client.on('drain', client.end.bind(client)) - return client.query(new Cursor(text, values || [])) - } - - before(function() { - client = new pg.Client() + this.pgCursor = function(text, values) { + client.on('drain', client.end.bind(client)) + return client.query(new Cursor(text, values || [])) + } }) - after(function() { - client.end() + afterEach(function() { + this.client.end() }) it('fetch 6 when asking for 10', function(done) { - var cursor = pgCursor(text) + var cursor = this.pgCursor(text) cursor.read(10, function(err, res) { assert.ifError(err) assert.equal(res.length, 6) @@ -33,7 +31,7 @@ describe('cursor', function() { }) it('end before reading to end', function(done) { - var cursor = pgCursor(text) + var cursor = this.pgCursor(text) cursor.read(3, function(err, res) { assert.ifError(err) assert.equal(res.length, 3) @@ -42,7 +40,7 @@ describe('cursor', function() { }) it('callback with error', function(done) { - var cursor = pgCursor('select asdfasdf') + var cursor = this.pgCursor('select asdfasdf') cursor.read(1, function(err) { assert(err) done() @@ -51,7 +49,7 @@ describe('cursor', function() { it('read a partial chunk of data', function(done) { - var cursor = pgCursor(text) + var cursor = this.pgCursor(text) cursor.read(2, function(err, res) { assert.ifError(err) assert.equal(res.length, 2) @@ -70,7 +68,7 @@ describe('cursor', function() { }) it('read return length 0 past the end', function(done) { - var cursor = pgCursor(text) + var cursor = this.pgCursor(text) cursor.read(2, function(err, res) { cursor.read(100, function(err, res) { assert.equal(res.length, 4) @@ -84,19 +82,19 @@ describe('cursor', function() { it('read huge result', function(done) { this.timeout(10000) - var text = 'SELECT generate_series as num FROM generate_series(0, 1000000)' + var text = 'SELECT generate_series as num FROM generate_series(0, 100000)' var values = [] - cursor = pgCursor(text, values); + cursor = this.pgCursor(text, values); var count = 0; var read = function() { - cursor.read(1000, function(err, rows) { + cursor.read(100, function(err, rows) { if(err) return done(err); if(!rows.length) { - assert.equal(count, 1000001) + assert.equal(count, 100001) return done() } count += rows.length; - if(count%100000 == 0) { + if(count%10000 == 0) { //console.log(count) } setImmediate(read) From a275adae525e49d3a3e5385bfeadc03e72f728c3 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 20 Nov 2013 22:49:08 -0600 Subject: [PATCH 0020/1037] Create README.md --- README.md | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..efcab0ec3 --- /dev/null +++ b/README.md @@ -0,0 +1,92 @@ +node-pg-cursor +============== + +Use a PostgreSQL result cursor from node with an easy to use API. + +### why? + +Sometimes you need to itterate through a table in chunks. It's extremely inefficient to use hand-crafted `LIMIT` and `OFFSET` queries to do this. +PostgreSQL provides built-in functionality to fetch a "cursor" to your results and page through the cursor. The page size is dynamic and async. + +### example + +```js +var Cursor = require('pg-cursor') +var pg = require('pg') + +pg.connect(function(err, client, done) { + + //imagine some_table has 30,000,000 results where prop > 100 + //lets create a query cursor to efficiently deal with the huge result set + var cursor = client.query(new Cursor('SELECT * FROM some_table WHERE prop > $1', [100]) + + //read the first 100 rows from this cursor + cursor.read(100, function(err, rows) { + if(err) { + //cursor error - release the client + //normally you'd do app-specific error handling here + return done(err) + } + + //when the cursor is exhausted and all rows have been returned + //all future calls to `cursor#read` will return an empty row array + //so if we received no rows, release the client and be done + if(!rows.length) return done() + + //do something with your rows + //when you're ready, read another chunk from + //your result + + + cursor.read(2000, function(err, rows) { + //I think you get the picture, yeah? + //if you dont...open an issue - I'd love to help you out! + }) + }) +}); +``` + +### api + +#### var Cursor = require('pg-cursor') + +#### constructor Cursor(string queryText, array queryParameters) + +Creates an instance of a query cursor. Pass this instance to node-postgres [`client#query`](https://github.com/brianc/node-postgres/wiki/Client#wiki-method-query-parameterized) + +#### cursor#read(int rowCount, function callback(Error err, Array rows) + +Read `rowCount` rows from the cursor instance. The `callback` will be called when the rows are available, loaded into memory, parsed, and converted to JavaScript types. + +If the cursor has read to the end of the result sets all subsequent calls to `cursor#read` will return a 0 length array of rows. I'm open to other ways to signal the end of a cursor, but this has worked out well for me so far. + +### install + +```sh +$ npm install pg-cursor +``` +___note___: this depends on _either_ `npm install pg` or `npm install pg.js`, but you __must__ be using the pure JavaScript client. This will __not work__ with the native bindings. + +### license + +The MIT License (MIT) + +Copyright (c) 2013 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. From dc92b1220e5f5e04d799b3960ac4ed5359d70f1a Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 20 Nov 2013 22:53:19 -0600 Subject: [PATCH 0021/1037] Update README.md --- README.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index efcab0ec3..5263d9895 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,9 @@ Use a PostgreSQL result cursor from node with an easy to use API. ### why? Sometimes you need to itterate through a table in chunks. It's extremely inefficient to use hand-crafted `LIMIT` and `OFFSET` queries to do this. -PostgreSQL provides built-in functionality to fetch a "cursor" to your results and page through the cursor. The page size is dynamic and async. +PostgreSQL provides built-in functionality to fetch a "cursor" to your results and page through the cursor efficiently fetching chunks of the results with full MVCC compliance. + +This actually ends up pairing very nicely with node's _asyncness_ and handling a lot of data. PostgreSQL is rad. ### example @@ -18,7 +20,7 @@ pg.connect(function(err, client, done) { //imagine some_table has 30,000,000 results where prop > 100 //lets create a query cursor to efficiently deal with the huge result set - var cursor = client.query(new Cursor('SELECT * FROM some_table WHERE prop > $1', [100]) + var cursor = client.query(new Cursor('SELECT * FROM some_table WHERE prop > $1', [100])) //read the first 100 rows from this cursor cursor.read(100, function(err, rows) { @@ -41,6 +43,9 @@ pg.connect(function(err, client, done) { cursor.read(2000, function(err, rows) { //I think you get the picture, yeah? //if you dont...open an issue - I'd love to help you out! + + //Also - you probably want to use some sort of async or promise library to deal with paging + //through your cursor results. node-pg-cursor makes no asumptions for you on that front. }) }) }); From e1117155ae41fcb393714fc0c9e638181c0049b5 Mon Sep 17 00:00:00 2001 From: Stephen Sugden Date: Wed, 25 Dec 2013 13:33:34 -0800 Subject: [PATCH 0022/1037] Emit 'close' events when query completes Consider a system where one component is scheduling tasks that yield streams, and passing them to (unknown) clients for consumption. It would be useful for the scheduler to know that the query underlying the stream is completed (so it can continue on to it's next task) without having to wait for the consumer to finish reading all results. --- index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/index.js b/index.js index b29eab0c9..fcc61d674 100644 --- a/index.js +++ b/index.js @@ -98,6 +98,7 @@ QueryStream.prototype.handleCommandComplete = function(msg) { } QueryStream.prototype.handleReadyForQuery = function() { + this.emit('close') this.push(null) } From 0df516c5498f5b857b85725629ad7c38d5d3c800 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 30 Jan 2014 23:07:03 -0600 Subject: [PATCH 0023/1037] Add cleanup to the example closes #2 --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index d16827a0c..597538ed5 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ pg.connect(function(err, client, done) { if(err) throw err; var query = new QueryStream('SELECT * FROM generate_series(0, $1) num', [1000000]) var stream = client.query(query) + //release the client when the stream is finished + stream.on('end', done) stream.pipe(JSONStream.stringify()).pipe(process.stdout) }) ``` From 87c3cf5e5eaacb341ec46136b7f4dfbd7d0b7798 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 17 Dec 2013 15:11:19 -0600 Subject: [PATCH 0024/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 962c9e859..f98453615 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "0.0.1", + "version": "0.1.0", "description": "", "main": "index.js", "directories": { From a3074e9d54b881f65939f6fd1cebf88ee2f06a60 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 26 Feb 2014 06:43:22 -0600 Subject: [PATCH 0025/1037] Bump mocha version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index f98453615..7c8bb4bfa 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "author": "Brian M. Carlson", "license": "MIT", "devDependencies": { - "mocha": "https://github.com/visionmedia/mocha/tarball/master", - "pg.js": "~2.8.1" + "pg.js": "~2.8.1", + "mocha": "~1.17.1" } } From 4925172530431562eae391d51973ded572bfd75f Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 26 Feb 2014 06:48:05 -0600 Subject: [PATCH 0026/1037] Fix require problem for `pg` module Closes #3 --- result.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/result.js b/result.js index 3e11636bd..45d36b0be 100644 --- a/result.js +++ b/result.js @@ -6,7 +6,7 @@ var pgPath; try { pgPath = path.dirname(require.resolve('pg')) } catch(e) { - pgPath = path.dirname(require.resolve('pg.js')) + pgPath = path.dirname(require.resolve('pg.js')) + '/lib' } -module.exports = require(path.join(pgPath, 'lib', 'result.js')) +module.exports = require(path.join(pgPath, 'result.js')) From cc9f08a042dc67674e374a2afc15e54fe2662bf3 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 26 Feb 2014 06:48:35 -0600 Subject: [PATCH 0027/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7c8bb4bfa..bda643f62 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "0.1.0", + "version": "0.1.1", "description": "", "main": "index.js", "directories": { From 290906294da66dc7bfa411160cd2cfde0813ca98 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 26 Feb 2014 07:10:06 -0600 Subject: [PATCH 0028/1037] Port tests to use mocha --- package.json | 3 ++- test/concat.js | 34 +++++++++++++++------------------- test/error.js | 32 ++++++++++++++------------------ test/fast-reader.js | 41 ++++++++++++++++++----------------------- test/helper.js | 17 +++++++++++++++++ test/instant.js | 22 ++++++++++------------ test/mocha.opts | 1 + test/pauses.js | 27 ++++++++++----------------- test/stream-tester.js | 21 ++++++++------------- 9 files changed, 95 insertions(+), 103 deletions(-) create mode 100644 test/helper.js create mode 100644 test/mocha.opts diff --git a/package.json b/package.json index 841a100b5..ec0819b5a 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "stream-tester": "0.0.5", "stream-spec": "~0.3.5", "jsonstream": "0.0.1", - "JSONStream": "~0.7.1" + "JSONStream": "~0.7.1", + "mocha": "~1.17.1" } } diff --git a/test/concat.js b/test/concat.js index b97ea4c19..0d3fa2c7d 100644 --- a/test/concat.js +++ b/test/concat.js @@ -1,26 +1,22 @@ -var pg = require('pg') var assert = require('assert') -var gonna = require('gonna') -var _ = require('lodash') var concat = require('concat-stream') var through = require('through') +var helper = require('./helper') var QueryStream = require('../') -var client = new pg.Client() - -var connected = gonna('connect', 100, function() { - var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) - var query = client.query(stream) - query.pipe(through(function(row) { - this.push(row.num) - })).pipe(concat(function(result) { - var total = result.reduce(function(prev, cur) { - return prev + cur - }) - assert.equal(total, 20100) - })) - stream.on('end', client.end.bind(client)) +helper(function(client) { + it('concats correctly', function(done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) + var query = client.query(stream) + query.pipe(through(function(row) { + this.push(row.num) + })).pipe(concat(function(result) { + var total = result.reduce(function(prev, cur) { + return prev + cur + }) + assert.equal(total, 20100) + })) + stream.on('end', done) + }) }) - -client.connect(connected) diff --git a/test/error.js b/test/error.js index aa3da4901..6d0b45b0f 100644 --- a/test/error.js +++ b/test/error.js @@ -1,24 +1,20 @@ -var pg = require('pg') var assert = require('assert') -var gonna = require('gonna') -var _ = require('lodash') -var concat = require('concat-stream') -var through = require('through') +var helper = require('./helper') var QueryStream = require('../') -var client = new pg.Client() +helper(function(client) { + it('receives error on stream', function(done) { + var stream = new QueryStream('SELECT * FROM asdf num', []) + var query = client.query(stream) + query.on('error', function(err) { + assert(err) + assert.equal(err.code, '42P01') + done() + }) + }) -var connected = gonna('connect', 100, function() { - var stream = new QueryStream('SELECT * FROM asdf num', []) - var query = client.query(stream) - query.on('error', gonna('emit error', 100, function(err) { - assert(err) - assert.equal(err.code, '42P01') - })) - var done = gonna('keep connetion alive', 100) - client.query('SELECT NOW()', done) + it('continues to function after stream', function(done) { + client.query('SELECT NOW()', done) + }) }) - -client.connect(connected) -client.on('drain', client.end.bind(client)) diff --git a/test/fast-reader.js b/test/fast-reader.js index 629848fb6..0bb395e86 100644 --- a/test/fast-reader.js +++ b/test/fast-reader.js @@ -1,29 +1,24 @@ -var pg = require('pg') var assert = require('assert') -var gonna = require('gonna') -var _ = require('lodash') - +var helper = require('./helper') var QueryStream = require('../') -var client = new pg.Client() - -var connected = gonna('connect', 100, function() { - var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) - var query = client.query(stream) - var result = [] - stream.on('readable', function() { - var res = stream.read() - assert(res, 'should not return null on evented reader') - result.push(res.num) - }) - stream.on('end', client.end.bind(client)) - stream.on('end', function() { - var total = result.reduce(function(prev, cur) { - return prev + cur +helper(function(client) { + it('works', function(done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) + var query = client.query(stream) + var result = [] + stream.on('readable', function() { + var res = stream.read() + assert(res, 'should not return null on evented reader') + result.push(res.num) }) - assert.equal(total, 20100) + stream.on('end', function() { + var total = result.reduce(function(prev, cur) { + return prev + cur + }) + assert.equal(total, 20100) + done() + }) + assert.strictEqual(query.read(2), null) }) - assert.strictEqual(query.read(2), null) }) - -client.connect(connected) diff --git a/test/helper.js b/test/helper.js new file mode 100644 index 000000000..6e7ea46b5 --- /dev/null +++ b/test/helper.js @@ -0,0 +1,17 @@ +var pg = require('pg') +module.exports = function(cb) { + describe('pg-query-stream', function() { + var client = new pg.Client() + + before(function(done) { + client.connect(done) + }) + + cb(client) + + after(function(done) { + client.end() + client.on('end', done) + }) + }) +} diff --git a/test/instant.js b/test/instant.js index 1b245162b..0cfc856ee 100644 --- a/test/instant.js +++ b/test/instant.js @@ -1,17 +1,15 @@ -var pg = require('pg') var assert = require('assert') -var gonna = require('gonna') var concat = require('concat-stream') var QueryStream = require('../') -var client = new pg.Client() -var query = new QueryStream('SELECT pg_sleep(1)', []) -var stream = client.query(query) -var done = gonna('read results', 5000) -stream.pipe(concat(function(res) { - assert.equal(res.length, 1) - done() - client.end() -})) -client.connect() +require('./helper')(function(client) { + it('instant', function(done) { + var query = new QueryStream('SELECT pg_sleep(1)', []) + var stream = client.query(query) + stream.pipe(concat(function(res) { + assert.equal(res.length, 1) + done() + })) + }) +}) diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 000000000..8dcb4d8d9 --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1 @@ +--no-exit diff --git a/test/pauses.js b/test/pauses.js index 7c61c8e8f..66e888360 100644 --- a/test/pauses.js +++ b/test/pauses.js @@ -1,25 +1,18 @@ -var pg = require('pg') var assert = require('assert') -var gonna = require('gonna') -var _ = require('lodash') var concat = require('concat-stream') -var through = require('through') var tester = require('stream-tester') var JSONStream = require('JSONStream') -var stream = require('stream') var QueryStream = require('../') -var client = new pg.Client() - -var connected = gonna('connect', 100, function() { - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], {chunkSize: 2, highWaterMark: 2}) - var query = client.query(stream) - var pauser = tester.createPauseStream(0.1, 100) - query.pipe(JSONStream.stringify()).pipe(concat(function(json) { - JSON.parse(json) - client.end() - })) +require('./helper')(function(client) { + it('pauses', function(done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], {chunkSize: 2, highWaterMark: 2}) + var query = client.query(stream) + var pauser = tester.createPauseStream(0.1, 100) + query.pipe(JSONStream.stringify()).pipe(concat(function(json) { + JSON.parse(json) + done() + })) + }) }) - -client.connect(connected) diff --git a/test/stream-tester.js b/test/stream-tester.js index 6975247a5..3e6f22074 100644 --- a/test/stream-tester.js +++ b/test/stream-tester.js @@ -1,21 +1,16 @@ -var pg = require('pg') -var assert = require('assert') -var gonna = require('gonna') var tester = require('stream-tester') +var spec = require('stream-spec') var QueryStream = require('../') -var client = new pg.Client() - -var connected = gonna('connect', 100, function() { - var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) - var spec = require('stream-spec') - var query = client.query(stream) - spec(query) +require('./helper')(function(client) { + it('passes stream spec', function(done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) + var query = client.query(stream) + spec(query) .readable() .pausable({strict: true}) .validateOnExit() - stream.on('end', client.end.bind(client)) + stream.on('end', done) + }) }) - -client.connect(connected) From f8f2a92897490f1d281d3f68edbcbad34dc6b3a4 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 26 Feb 2014 07:10:30 -0600 Subject: [PATCH 0029/1037] Remove Makefile --- Makefile | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 Makefile diff --git a/Makefile b/Makefile deleted file mode 100644 index fc9212a7c..000000000 --- a/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -SHELL := /bin/sh -.PHONY: test - -test: - find test/ -name "*.js" | xargs -n 1 node From b66be5e93496d6c288e6896be1fa76e8f6b6aeb0 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 26 Feb 2014 07:15:01 -0600 Subject: [PATCH 0030/1037] Add test for stream close & satisfy stream contract --- index.js | 5 ++++- test/close.js | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 test/close.js diff --git a/index.js b/index.js index fcc61d674..879bcc093 100644 --- a/index.js +++ b/index.js @@ -98,8 +98,11 @@ QueryStream.prototype.handleCommandComplete = function(msg) { } QueryStream.prototype.handleReadyForQuery = function() { - this.emit('close') this.push(null) + //ensure 'close' fires after end + setImmediate(function() { + this.emit('close') + }.bind(this)) } QueryStream.prototype.handleError = function(err) { diff --git a/test/close.js b/test/close.js new file mode 100644 index 000000000..fb812960d --- /dev/null +++ b/test/close.js @@ -0,0 +1,14 @@ +var assert = require('assert') +var concat = require('concat-stream') +var tester = require('stream-tester') +var JSONStream = require('JSONStream') + +var QueryStream = require('../') + +require('./helper')(function(client) { + it('emits close', function(done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], {chunkSize: 2, highWaterMark: 2}) + var query = client.query(stream) + query.on('close', done) + }) +}) From 122bcfb27b1b33dbcc86521737f7bd378ed3aae2 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 26 Feb 2014 07:16:00 -0600 Subject: [PATCH 0031/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ec0819b5a..cddd70246 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "0.2.0", + "version": "0.3.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From f1dbe7884cb1ae462f45f62ff3341d563c49ca03 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 26 Feb 2014 09:30:00 -0600 Subject: [PATCH 0032/1037] Normalize parameter values --- index.js | 5 +++-- package.json | 3 ++- result.js => pg.js | 3 ++- test/index.js | 16 +++++++++++++++- 4 files changed, 22 insertions(+), 5 deletions(-) rename result.js => pg.js (65%) diff --git a/index.js b/index.js index 9b14f0f00..6f30e11f2 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,9 @@ -var Result = require('./result') +var Result = require('./pg').Result +var prepare = require('./pg').prepareValue var Cursor = function(text, values) { this.text = text - this.values = values + this.values = values ? values.map(prepare) : null this.connection = null this._queue = [] this.state = 'initialized' diff --git a/package.json b/package.json index bda643f62..b027cf870 100644 --- a/package.json +++ b/package.json @@ -14,5 +14,6 @@ "devDependencies": { "pg.js": "~2.8.1", "mocha": "~1.17.1" - } + }, + "dependencies": {} } diff --git a/result.js b/pg.js similarity index 65% rename from result.js rename to pg.js index 45d36b0be..96cd7f9a5 100644 --- a/result.js +++ b/pg.js @@ -9,4 +9,5 @@ try { pgPath = path.dirname(require.resolve('pg.js')) + '/lib' } -module.exports = require(path.join(pgPath, 'result.js')) +module.exports.Result = require(path.join(pgPath, 'result.js')) +module.exports.prepareValue = require(path.join(pgPath, 'utils.js')).prepareValue diff --git a/test/index.js b/test/index.js index 6ff312604..77b60cd2c 100644 --- a/test/index.js +++ b/test/index.js @@ -84,7 +84,7 @@ describe('cursor', function() { this.timeout(10000) var text = 'SELECT generate_series as num FROM generate_series(0, 100000)' var values = [] - cursor = this.pgCursor(text, values); + var cursor = this.pgCursor(text, values); var count = 0; var read = function() { cursor.read(100, function(err, rows) { @@ -102,4 +102,18 @@ describe('cursor', function() { } read() }) + + it('normalizes parameter values', function(done) { + var text = 'SELECT $1::json me' + var values = [{name: 'brian'}] + var cursor = this.pgCursor(text, values); + cursor.read(1, function(err, rows) { + if(err) return done(err); + assert.equal(rows[0].me.name, 'brian') + cursor.read(1, function(err, rows) { + assert.equal(rows.length, 0) + done() + }) + }) + }) }) From b1b39bbd4fb2ae2cf0c8e2f138b36a704bb25fac Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 26 Feb 2014 09:30:09 -0600 Subject: [PATCH 0033/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b027cf870..6ce91cf2f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "0.1.1", + "version": "0.1.2", "description": "", "main": "index.js", "directories": { From 37de9c2ab0fb5ebbbaeac867dfa3b56669a29f0b Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 26 Feb 2014 09:38:16 -0600 Subject: [PATCH 0034/1037] Rebase code on top of pg-cursor --- index.js | 125 +++++++++++--------------------------------- package.json | 6 ++- test/close.js | 3 +- test/fast-reader.js | 5 +- test/helper.js | 2 +- test/pauses.js | 2 +- 6 files changed, 42 insertions(+), 101 deletions(-) diff --git a/index.js b/index.js index 879bcc093..f50f0af91 100644 --- a/index.js +++ b/index.js @@ -1,111 +1,46 @@ -var assert = require('assert') +var util = require('util') +var Cursor = require('pg-cursor') var Readable = require('stream').Readable -var path = require('path') - -var pgdir = false -try { - pgdir = path.dirname(require.resolve('pg')) -} catch (e) { - pgdir = path.dirname(require.resolve('pg.js')) - if(!pgdir) { - throw new Error("Please install either `pg` or `pg.js` to use this module") - } - pgdir = path.join(pgdir, 'lib') -} -var Result = require(path.join(pgdir, 'result')) -var utils = require(path.join(pgdir, 'utils')) - var QueryStream = module.exports = function(text, values, options) { options = options || { } + Cursor.call(this, text, values) Readable.call(this, { objectMode: true, highWaterMark: options.highWaterMark || 1000 }) - this.text = text - assert(this.text, 'text cannot be falsy') - this.values = (values || []).map(utils.prepareValue) - this.name = '' - this._result = new Result() this.batchSize = options.batchSize || 100 - this._idle = true -} - -require('util').inherits(QueryStream, Readable) - -QueryStream.prototype._read = function(n) { - this._getRows(n) -} - -QueryStream.prototype._getRows = function(count) { - var con = this.connection - if(!this._idle || !this.connection) return; - this._idle = false - con.execute({ - portal: '', - rows: count - }, true) - - con.flush() -} - -QueryStream.prototype.submit = function(con) { - //save reference to connection - this.connection = con - - var name = this.name - - con.parse({ - text: this.text, - name: name, - types: [] - }, true) - - con.bind({ - portal: '', - statement: name, - values: this.values, - binary: false - }, true) - - con.describe({ - type: 'P', - name: name - }, true) - - this._getRows(this.batchSize) - -} - -QueryStream.prototype.handleRowDescription = function(msg) { - this._result.addFields(msg.fields) + this._ready = false + //kick reader + this.read() } -QueryStream.prototype.handleDataRow = function(msg) { - var row = this._result.parseRow(msg.fields) - this._more = this.push(row) -} - -QueryStream.prototype.handlePortalSuspended = function(msg) { - this._idle = true - if(this._more) { - this._getRows(this.batchSize) +util.inherits(QueryStream, Readable) +for(var key in Cursor.prototype) { + if(key != 'read') { + QueryStream.prototype[key] = Cursor.prototype[key] } } -QueryStream.prototype.handleCommandComplete = function(msg) { - this.connection.sync() -} +QueryStream.prototype._fetch = Cursor.prototype.read -QueryStream.prototype.handleReadyForQuery = function() { - this.push(null) - //ensure 'close' fires after end - setImmediate(function() { - this.emit('close') - }.bind(this)) -} - -QueryStream.prototype.handleError = function(err) { - this.connection.sync() - this.emit('error', err) +QueryStream.prototype._read = function(n) { + if(this._reading) return false; + this._reading = true + var self = this + this._fetch(this.batchSize, function(err, rows) { + if(err) { + return self.emit('error', err) + } + if(!rows.length) { + setImmediate(function() { + self.push(null) + self.once('end', self.emit.bind(self, 'close')) + }) + } + self._reading = false + for(var i = 0; i < rows.length; i++) { + self.push(rows[i]) + } + }) } diff --git a/package.json b/package.json index cddd70246..1b13fba5d 100644 --- a/package.json +++ b/package.json @@ -23,14 +23,16 @@ }, "devDependencies": { "pg.js": "~2.8.0", - "gonna": "0.0.0", "lodash": "~2.2.1", "concat-stream": "~1.0.1", "through": "~2.3.4", "stream-tester": "0.0.5", "stream-spec": "~0.3.5", - "jsonstream": "0.0.1", + "jsonstream": "*", "JSONStream": "~0.7.1", "mocha": "~1.17.1" + }, + "dependencies": { + "pg-cursor": "~0.1.2" } } diff --git a/test/close.js b/test/close.js index fb812960d..6fa536c86 100644 --- a/test/close.js +++ b/test/close.js @@ -7,8 +7,9 @@ var QueryStream = require('../') require('./helper')(function(client) { it('emits close', function(done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], {chunkSize: 2, highWaterMark: 2}) + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], {batchSize: 2, highWaterMark: 2}) var query = client.query(stream) + query.pipe(concat(function() {})) query.on('close', done) }) }) diff --git a/test/fast-reader.js b/test/fast-reader.js index 0bb395e86..808abd444 100644 --- a/test/fast-reader.js +++ b/test/fast-reader.js @@ -7,10 +7,13 @@ helper(function(client) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) var result = [] + var count = 0 stream.on('readable', function() { var res = stream.read() assert(res, 'should not return null on evented reader') - result.push(res.num) + if(res) { + result.push(res.num) + } }) stream.on('end', function() { var total = result.reduce(function(prev, cur) { diff --git a/test/helper.js b/test/helper.js index 6e7ea46b5..cfc16ced3 100644 --- a/test/helper.js +++ b/test/helper.js @@ -1,4 +1,4 @@ -var pg = require('pg') +var pg = require('pg.js') module.exports = function(cb) { describe('pg-query-stream', function() { var client = new pg.Client() diff --git a/test/pauses.js b/test/pauses.js index 66e888360..ff54bf087 100644 --- a/test/pauses.js +++ b/test/pauses.js @@ -7,7 +7,7 @@ var QueryStream = require('../') require('./helper')(function(client) { it('pauses', function(done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], {chunkSize: 2, highWaterMark: 2}) + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], {batchSize: 2, highWaterMark: 2}) var query = client.query(stream) var pauser = tester.createPauseStream(0.1, 100) query.pipe(JSONStream.stringify()).pipe(concat(function(json) { From 0a7da37ab7e81bc12deb0aa75f6646910f72a937 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 26 Feb 2014 09:38:25 -0600 Subject: [PATCH 0035/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1b13fba5d..42a546a43 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "0.3.0", + "version": "0.4.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From 1a9fd7ff76606ebec36fc5db2972c12e891c8db7 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 21 Mar 2014 11:44:46 -0500 Subject: [PATCH 0036/1037] Do not callback with final empty array until readyForQuery is received Closes https://github.com/brianc/node-pg-query-stream/issues/3 --- index.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 6f30e11f2..71a4223fb 100644 --- a/index.js +++ b/index.js @@ -50,14 +50,19 @@ Cursor.prototype.handleDataRow = function(msg) { Cursor.prototype._sendRows = function() { this.state = 'idle' setImmediate(function() { - this._cb(null, this._rows) + var cb = this._cb + //remove callback before calling it + //because likely a new one will be added + //within the call to this callback + this._cb = null + if(cb) { + cb(null, this._rows) + } this._rows = [] }.bind(this)) } Cursor.prototype.handleCommandComplete = function() { - this._sendRows() - this.state = 'done' this.connection.sync() } @@ -66,6 +71,8 @@ Cursor.prototype.handlePortalSuspended = function() { } Cursor.prototype.handleReadyForQuery = function() { + this._sendRows() + this.state = 'done' } Cursor.prototype.handleError = function(msg) { From 37de20e8261838c829e0ad4912406423cbf7fd5c Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 21 Mar 2014 11:44:59 -0500 Subject: [PATCH 0037/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6ce91cf2f..a886f9032 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "0.1.2", + "version": "0.1.3", "description": "", "main": "index.js", "directories": { From 19611254762ac5337dcfe3dc4e8864460e68c1cd Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 21 Mar 2014 11:47:32 -0500 Subject: [PATCH 0038/1037] Update pg-cursor pg-cursor no longer returns the empty array 'done' signal to the callback until the cursor recieves a readyForQuery message. This means pg-query-stream will not emit 'close' or 'end' events until the server is __truly__ ready for the next query. This fixes some race-conditions where some queries are triggered off of the `end` event of the query-stream closes #3 --- package.json | 2 +- test/issue-3.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 test/issue-3.js diff --git a/package.json b/package.json index 42a546a43..2f50714ef 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,6 @@ "mocha": "~1.17.1" }, "dependencies": { - "pg-cursor": "~0.1.2" + "pg-cursor": "0.1.3" } } diff --git a/test/issue-3.js b/test/issue-3.js new file mode 100644 index 000000000..0c822c973 --- /dev/null +++ b/test/issue-3.js @@ -0,0 +1,32 @@ +var pg = require('pg.js') +var QueryStream = require('../') +describe('end semantics race condition', function() { + before(function(done) { + var client = new pg.Client() + client.connect() + client.on('drain', client.end.bind(client)) + client.on('end', done) + client.query('create table IF NOT EXISTS p(id serial primary key)') + client.query('create table IF NOT EXISTS c(id int primary key references p)') + }) + it('works', function(done) { + var client1 = new pg.Client() + client1.connect() + var client2 = new pg.Client() + client2.connect() + + var qr = new QueryStream("INSERT INTO p DEFAULT VALUES RETURNING id") + client1.query(qr) + var id = null + qr.on('data', function(row) { + id = row.id + }) + qr.on('end', function () { + client2.query("INSERT INTO c(id) VALUES ($1)", [id], function (err, rows) { + client1.end() + client2.end() + done(err) + }) + }) + }) +}) From 0f13c8068f30a78220e351d92ec14c243bbbfcd4 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 21 Mar 2014 11:47:40 -0500 Subject: [PATCH 0039/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2f50714ef..5def32deb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "0.4.0", + "version": "0.4.1", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From 87b52f9e516ec0d5b70554886d46cb40ddec0069 Mon Sep 17 00:00:00 2001 From: Tom Buchok Date: Wed, 9 Apr 2014 23:56:21 -0400 Subject: [PATCH 0040/1037] adds failing test - appears that timestamp queries emit a lot of `rows` with length == 0 - `self.once('end')` is added each of these times - assertion on listener count shows that more than 10 listeners are applied --- test/stream-tester-timestamp.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 test/stream-tester-timestamp.js diff --git a/test/stream-tester-timestamp.js b/test/stream-tester-timestamp.js new file mode 100644 index 000000000..227630a7b --- /dev/null +++ b/test/stream-tester-timestamp.js @@ -0,0 +1,29 @@ +var pg = require('pg.js') +var QueryStream = require('../') +var spec = require('stream-spec') +var assert = require('assert') + +require('./helper')(function(client) { + it('should not warn about max listeners', function(done) { + var sql = 'SELECT * FROM generate_series(\'1983-12-30 00:00\'::timestamp, \'2013-12-30 00:00\', \'1 years\')' + var result = [] + var stream = new QueryStream(sql, []) + var ended = false + var query = client.query(stream) + query. + on('end', function() { ended = true }) + spec(query) + .readable() + .pausable({strict: true}) + .validateOnExit() + ; + var checkListeners = function() { + assert(stream.listeners('end').length < 10) + if (!ended) + setImmediate(checkListeners) + else + done() + } + checkListeners() + }) +}) \ No newline at end of file From cab956ba5030b146ea2132954588023b062ed02e Mon Sep 17 00:00:00 2001 From: Tom Buchok Date: Wed, 9 Apr 2014 23:58:18 -0400 Subject: [PATCH 0041/1037] passes `stream-tester-timestamp` - moves 'end' event listener to constructor, only listen once - ensures all existing tests still green --- index.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index f50f0af91..89d3aa9bb 100644 --- a/index.js +++ b/index.js @@ -11,6 +11,9 @@ var QueryStream = module.exports = function(text, values, options) { }) this.batchSize = options.batchSize || 100 this._ready = false + this.once('end', function() { + setImmediate(function() { this.emit('close') }.bind(this)); + }) //kick reader this.read() } @@ -35,7 +38,6 @@ QueryStream.prototype._read = function(n) { if(!rows.length) { setImmediate(function() { self.push(null) - self.once('end', self.emit.bind(self, 'close')) }) } self._reading = false From 7593a44f79af2b11d15be75855531a4a5c4baecf Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 11 Apr 2014 11:01:43 -0500 Subject: [PATCH 0042/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5def32deb..889314786 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "0.4.1", + "version": "0.4.2", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From 41b7d7d4defa32a0843f5ab02ef9b96f79bb5587 Mon Sep 17 00:00:00 2001 From: Calvin Metcalf Date: Wed, 14 May 2014 09:51:56 -0400 Subject: [PATCH 0043/1037] fix up tests --- package.json | 2 +- test/close.js | 2 +- test/concat.js | 2 +- test/error.js | 2 +- test/fast-reader.js | 2 +- test/helper.js | 4 ++-- test/instant.js | 2 +- test/pauses.js | 2 +- test/stream-tester-timestamp.js | 2 +- test/stream-tester.js | 2 +- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 889314786..65c1f1247 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { - "test": "make test" + "test": "mocha test/*.js -R spec" }, "repository": { "type": "git", diff --git a/test/close.js b/test/close.js index 6fa536c86..6f319a75e 100644 --- a/test/close.js +++ b/test/close.js @@ -5,7 +5,7 @@ var JSONStream = require('JSONStream') var QueryStream = require('../') -require('./helper')(function(client) { +require('./helper')('close', function(client) { it('emits close', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], {batchSize: 2, highWaterMark: 2}) var query = client.query(stream) diff --git a/test/concat.js b/test/concat.js index 0d3fa2c7d..8e6bf5d97 100644 --- a/test/concat.js +++ b/test/concat.js @@ -5,7 +5,7 @@ var helper = require('./helper') var QueryStream = require('../') -helper(function(client) { +helper('concat', function(client) { it('concats correctly', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) diff --git a/test/error.js b/test/error.js index 6d0b45b0f..24eb2cd20 100644 --- a/test/error.js +++ b/test/error.js @@ -3,7 +3,7 @@ var helper = require('./helper') var QueryStream = require('../') -helper(function(client) { +helper('error', function(client) { it('receives error on stream', function(done) { var stream = new QueryStream('SELECT * FROM asdf num', []) var query = client.query(stream) diff --git a/test/fast-reader.js b/test/fast-reader.js index 808abd444..dd967631b 100644 --- a/test/fast-reader.js +++ b/test/fast-reader.js @@ -2,7 +2,7 @@ var assert = require('assert') var helper = require('./helper') var QueryStream = require('../') -helper(function(client) { +helper('fast reader', function(client) { it('works', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) diff --git a/test/helper.js b/test/helper.js index cfc16ced3..ce04d1271 100644 --- a/test/helper.js +++ b/test/helper.js @@ -1,6 +1,6 @@ var pg = require('pg.js') -module.exports = function(cb) { - describe('pg-query-stream', function() { +module.exports = function(name, cb) { + describe(name, function() { var client = new pg.Client() before(function(done) { diff --git a/test/instant.js b/test/instant.js index 0cfc856ee..dd36fbca8 100644 --- a/test/instant.js +++ b/test/instant.js @@ -3,7 +3,7 @@ var concat = require('concat-stream') var QueryStream = require('../') -require('./helper')(function(client) { +require('./helper')('instant', function(client) { it('instant', function(done) { var query = new QueryStream('SELECT pg_sleep(1)', []) var stream = client.query(query) diff --git a/test/pauses.js b/test/pauses.js index ff54bf087..181f3c29f 100644 --- a/test/pauses.js +++ b/test/pauses.js @@ -5,7 +5,7 @@ var JSONStream = require('JSONStream') var QueryStream = require('../') -require('./helper')(function(client) { +require('./helper')('pauses', function(client) { it('pauses', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], {batchSize: 2, highWaterMark: 2}) var query = client.query(stream) diff --git a/test/stream-tester-timestamp.js b/test/stream-tester-timestamp.js index 227630a7b..d62dd5669 100644 --- a/test/stream-tester-timestamp.js +++ b/test/stream-tester-timestamp.js @@ -3,7 +3,7 @@ var QueryStream = require('../') var spec = require('stream-spec') var assert = require('assert') -require('./helper')(function(client) { +require('./helper')('stream tester timestamp', function(client) { it('should not warn about max listeners', function(done) { var sql = 'SELECT * FROM generate_series(\'1983-12-30 00:00\'::timestamp, \'2013-12-30 00:00\', \'1 years\')' var result = [] diff --git a/test/stream-tester.js b/test/stream-tester.js index 3e6f22074..a00125f25 100644 --- a/test/stream-tester.js +++ b/test/stream-tester.js @@ -3,7 +3,7 @@ var spec = require('stream-spec') var QueryStream = require('../') -require('./helper')(function(client) { +require('./helper')('stream tester', function(client) { it('passes stream spec', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) From fec090972bacc2271fadadb9980a762ae5775197 Mon Sep 17 00:00:00 2001 From: Calvin Metcalf Date: Wed, 14 May 2014 10:41:10 -0400 Subject: [PATCH 0044/1037] clean ups --- index.js | 21 ++++++++++++--------- package.json | 4 ++-- test/error.js | 2 ++ 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index 89d3aa9bb..e346457b1 100644 --- a/index.js +++ b/index.js @@ -1,8 +1,9 @@ var util = require('util') var Cursor = require('pg-cursor') -var Readable = require('stream').Readable +var Readable = require('readable-stream').Readable var QueryStream = module.exports = function(text, values, options) { + var self = this; options = options || { } Cursor.call(this, text, values) Readable.call(this, { @@ -10,22 +11,23 @@ var QueryStream = module.exports = function(text, values, options) { highWaterMark: options.highWaterMark || 1000 }) this.batchSize = options.batchSize || 100 - this._ready = false this.once('end', function() { - setImmediate(function() { this.emit('close') }.bind(this)); - }) - //kick reader - this.read() + process.nextTick(function() { + self.emit('close') + }); + }) } util.inherits(QueryStream, Readable) for(var key in Cursor.prototype) { - if(key != 'read') { + if(key == 'read') { + QueryStream.prototype._fetch = Cursor.prototype.read + } else { QueryStream.prototype[key] = Cursor.prototype[key] } } -QueryStream.prototype._fetch = Cursor.prototype.read + QueryStream.prototype._read = function(n) { if(this._reading) return false; @@ -36,9 +38,10 @@ QueryStream.prototype._read = function(n) { return self.emit('error', err) } if(!rows.length) { - setImmediate(function() { + process.nextTick(function() { self.push(null) }) + return; } self._reading = false for(var i = 0; i < rows.length; i++) { diff --git a/package.json b/package.json index 65c1f1247..60c153777 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,6 @@ }, "devDependencies": { "pg.js": "~2.8.0", - "lodash": "~2.2.1", "concat-stream": "~1.0.1", "through": "~2.3.4", "stream-tester": "0.0.5", @@ -33,6 +32,7 @@ "mocha": "~1.17.1" }, "dependencies": { - "pg-cursor": "0.1.3" + "pg-cursor": "0.1.3", + "readable-stream": "^1.0.27-1" } } diff --git a/test/error.js b/test/error.js index 24eb2cd20..b3ef8f1eb 100644 --- a/test/error.js +++ b/test/error.js @@ -11,6 +11,8 @@ helper('error', function(client) { assert(err) assert.equal(err.code, '42P01') done() + }).on('data', function () { + //noop to kick of reading }) }) From f7b65723992002bfa69134e39e587569cf15e6b7 Mon Sep 17 00:00:00 2001 From: Stephen Sugden Date: Wed, 21 May 2014 21:54:27 +0200 Subject: [PATCH 0045/1037] fix typo --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 71a4223fb..5ea42cf11 100644 --- a/index.js +++ b/index.js @@ -103,7 +103,7 @@ Cursor.prototype._getRows = function(rows, cb) { } Cursor.prototype.end = function(cb) { - if(this.statue != 'initialized') { + if(this.state != 'initialized') { this.connection.sync() } this.connection.end() From 9cc3e527da5fb8c2a2cfeb1880f4db77aacf7160 Mon Sep 17 00:00:00 2001 From: Stephen Sugden Date: Wed, 21 May 2014 22:42:35 +0200 Subject: [PATCH 0046/1037] add failing test for noData queries --- test/no-data-handling.js | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 test/no-data-handling.js diff --git a/test/no-data-handling.js b/test/no-data-handling.js new file mode 100644 index 000000000..9bcbef837 --- /dev/null +++ b/test/no-data-handling.js @@ -0,0 +1,25 @@ +var assert = require('assert') +var pg = require('pg.js'); +var Cursor = require('../'); + +describe('queries with no data', function () { + beforeEach(function(done) { + var client = this.client = new pg.Client() + client.connect(done) + }) + + + afterEach(function() { + this.client.end() + }) + + it('handles queries that return no data', function (done) { + var cursor = new Cursor('CREATE TEMPORARY TABLE whatwhat (thing int)') + this.client.query(cursor) + cursor.read(100, function (err, rows) { + assert.ifError(err) + assert.equal(rows.length, 0) + done() + }) + }); +}); From 5084624e8d5be0439fb77e6d89aaebd1530a5f40 Mon Sep 17 00:00:00 2001 From: Stephen Sugden Date: Wed, 21 May 2014 22:42:54 +0200 Subject: [PATCH 0047/1037] fix test command in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a886f9032..5485318d1 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "test": "test" }, "scripts": { - "test": "node test/" + "test": "mocha test/" }, "author": "Brian M. Carlson", "license": "MIT", From 8283fd9b22d8ab480b9e8c8b9d38cacbca223232 Mon Sep 17 00:00:00 2001 From: Stephen Sugden Date: Wed, 21 May 2014 22:44:51 +0200 Subject: [PATCH 0048/1037] add support for queries that don't return a row description --- index.js | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/index.js b/index.js index 5ea42cf11..2d8e088b5 100644 --- a/index.js +++ b/index.js @@ -32,16 +32,30 @@ Cursor.prototype.submit = function(connection) { }, true) con.flush() + + con.once('noData', ifNoData) + con.once('rowDescription', function () { + con.removeListener('noData', ifNoData); + }); + + function ifNoData () { + self.state = 'idle' + self._shiftQueue(); + } } -Cursor.prototype.handleRowDescription = function(msg) { - this._result.addFields(msg.fields) - this.state = 'idle' +Cursor.prototype._shiftQueue = function () { if(this._queue.length) { this._getRows.apply(this, this._queue.shift()) } } +Cursor.prototype.handleRowDescription = function(msg) { + this._result.addFields(msg.fields) + this.state = 'idle' + this._shiftQueue(); +} + Cursor.prototype.handleDataRow = function(msg) { var row = this._result.parseRow(msg.fields) this._rows.push(row) From b9fd38df15759aa89ea780f1b45652a08ef51626 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 22 May 2014 11:17:03 -0400 Subject: [PATCH 0049/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5485318d1..e3c41869b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "0.1.3", + "version": "0.2.0", "description": "", "main": "index.js", "directories": { From e242b94e6cadd9b5a7d8c20bd23280f78cffdec9 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 22 May 2014 11:20:53 -0400 Subject: [PATCH 0050/1037] Update version of pg-cursor --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 889314786..6545baaa4 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "url": "https://github.com/brianc/node-pg-query-stream/issues" }, "devDependencies": { - "pg.js": "~2.8.0", + "pg.js": "*", "lodash": "~2.2.1", "concat-stream": "~1.0.1", "through": "~2.3.4", @@ -33,6 +33,6 @@ "mocha": "~1.17.1" }, "dependencies": { - "pg-cursor": "0.1.3" + "pg-cursor": "0.2.0" } } From 99fe666956f4125c1225b6224476ce304c3d02fb Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 22 May 2014 11:22:31 -0400 Subject: [PATCH 0051/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6545baaa4..2b9fe736d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "0.4.2", + "version": "0.5.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From adf86b89f6b22c48e8c779c74efd361fde3f1c91 Mon Sep 17 00:00:00 2001 From: Calvin Metcalf Date: Thu, 22 May 2014 12:54:14 -0400 Subject: [PATCH 0052/1037] deps --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 5e2351c00..ffbbfdf79 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,6 @@ "through": "~2.3.4", "stream-tester": "0.0.5", "stream-spec": "~0.3.5", - "jsonstream": "*", "JSONStream": "~0.7.1", "mocha": "~1.17.1" }, From df63cbbab7d31da39f366d010aafab4cd34af13f Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 22 May 2014 16:59:23 -0400 Subject: [PATCH 0053/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ffbbfdf79..1ac30f4cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "0.5.0", + "version": "0.6.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From 88aafd73fa02c35b7469bb6e38f6bef59d03825e Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Sat, 5 Jul 2014 16:22:20 -0700 Subject: [PATCH 0054/1037] Initial commit --- .gitignore | 25 +++++++++++++++++++++++++ LICENSE | 21 +++++++++++++++++++++ README.md | 4 ++++ 3 files changed, 50 insertions(+) create mode 100644 .gitignore create mode 100644 LICENSE create mode 100644 README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..da23d0d4b --- /dev/null +++ b/.gitignore @@ -0,0 +1,25 @@ +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# Deployed apps should consider commenting this line out: +# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git +node_modules diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..b068a6cb2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Iced Development + +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. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 000000000..46afa27de --- /dev/null +++ b/README.md @@ -0,0 +1,4 @@ +pg-connection-string +==================== + +Functions for dealing with a PostgresSQL connection string From 92c1fede8e7e3582b7040557cf2cb30705f59ad6 Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Sat, 5 Jul 2014 16:43:58 -0700 Subject: [PATCH 0055/1037] initial commit --- .travis.yml | 3 ++ README.md | 14 ++++++++ index.js | 54 +++++++++++++++++++++++++++++++ package.json | 29 +++++++++++++++++ test/parse.js | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 189 insertions(+) create mode 100644 .travis.yml create mode 100644 index.js create mode 100644 package.json create mode 100644 test/parse.js diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..244b7e88e --- /dev/null +++ b/.travis.yml @@ -0,0 +1,3 @@ +language: node_js +node_js: + - '0.10' diff --git a/README.md b/README.md index 46afa27de..49862702b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,18 @@ pg-connection-string ==================== +[![Build Status](https://travis-ci.org/iceddev/pg-connection-string.svg?branch=master)](https://travis-ci.org/iceddev/pg-connection-string) + Functions for dealing with a PostgresSQL connection string + +`parse` method taken from [node-postgres](https://github.com/brianc/node-postgres.git) +Copyright (c) 2010-2014 Brian Carlson (brian.m.carlson@gmail.com) +MIT License + +## Usage + +```js +var parse = require('pg-connection-string').parse; + +var config = parse('postgres://someuser:somepassword@somehost:381/sometable') +``` diff --git a/index.js b/index.js new file mode 100644 index 000000000..6c8fb68dc --- /dev/null +++ b/index.js @@ -0,0 +1,54 @@ +'use strict'; + +var url = require('url'); + +//Parse method copied from https://github.com/brianc/node-postgres +//Copyright (c) 2010-2014 Brian Carlson (brian.m.carlson@gmail.com) +//MIT License + +//parses a connection string +function parse(str) { + var config; + //unix socket + if(str.charAt(0) === '/') { + config = str.split(' '); + return { host: config[0], database: config[1] }; + } + // url parse expects spaces encoded as %20 + if(/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) { + str = encodeURI(str).replace(/\%25(\d\d)/g, "%$1"); + } + var result = url.parse(str, true); + config = {}; + + if (result.query.application_name) { + config.application_name = result.query.application_name; + } + if (result.query.fallback_application_name) { + config.fallback_application_name = result.query.fallback_application_name; + } + + if(result.protocol == 'socket:') { + config.host = decodeURI(result.pathname); + config.database = result.query.db; + config.client_encoding = result.query.encoding; + return config; + } + config.host = result.hostname; + config.database = result.pathname ? decodeURI(result.pathname.slice(1)) : null; + var auth = (result.auth || ':').split(':'); + config.user = auth[0]; + config.password = auth[1]; + config.port = result.port; + + var ssl = result.query.ssl; + if (ssl === 'true' || ssl === '1') { + config.ssl = true; + } + + return config; +} + +module.exports = { + parse: parse +}; diff --git a/package.json b/package.json new file mode 100644 index 000000000..56f535dd2 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "pg-connection-string", + "version": "0.1.0", + "description": "Functions for dealing with a PostgresSQL connection string", + "main": "index.js", + "scripts": { + "test": "tap ./test" + }, + "repository": { + "type": "git", + "url": "https://github.com/iceddev/pg-connection-string" + }, + "keywords": [ + "pg", + "connection", + "string", + "parse" + ], + "author": "Blaine Bublitz (http://iceddev.com/)", + "license": "MIT", + "bugs": { + "url": "https://github.com/iceddev/pg-connection-string/issues" + }, + "homepage": "https://github.com/iceddev/pg-connection-string", + "dependencies": {}, + "devDependencies": { + "tap": "^0.4.11" + } +} diff --git a/test/parse.js b/test/parse.js new file mode 100644 index 000000000..1b9b203c9 --- /dev/null +++ b/test/parse.js @@ -0,0 +1,89 @@ +'use strict'; + +var test = require('tap').test; + +var parse = require('../').parse; + +test('using connection string in client constructor', function(t){ + var subject = parse('postgres://brian:pw@boom:381/lala'); + t.equal(subject.user,'brian'); + t.equal(subject.password, 'pw'); + t.equal(subject.host, 'boom'); + t.equal(subject.port, '381'); + t.equal(subject.database, 'lala'); + t.end(); +}); + +test('escape spaces if present', function(t){ + var subject = parse('postgres://localhost/post gres'); + t.equal(subject.database, 'post gres'); + t.end(); +}); + +test('do not double escape spaces', function(t){ + var subject = parse('postgres://localhost/post%20gres'); + t.equal(subject.database, 'post gres'); + t.end(); +}); + +test('initializing with unix domain socket', function(t){ + var subject = parse('/var/run/'); + t.equal(subject.host, '/var/run/'); + t.end(); +}); + +test('initializing with unix domain socket and a specific database, the simple way', function(t){ + var subject = parse('/var/run/ mydb'); + t.equal(subject.host, '/var/run/'); + t.equal(subject.database, 'mydb'); + t.end(); +}); + +test('initializing with unix domain socket, the health way', function(t){ + var subject = parse('socket:/some path/?db=my[db]&encoding=utf8'); + t.equal(subject.host, '/some path/'); + t.equal(subject.database, 'my[db]', 'must to be escaped and unescaped trough "my%5Bdb%5D"'); + t.equal(subject.client_encoding, 'utf8'); + t.end(); +}); + +test('initializing with unix domain socket, the escaped health way', function(t){ + var subject = parse('socket:/some%20path/?db=my%2Bdb&encoding=utf8'); + t.equal(subject.host, '/some path/'); + t.equal(subject.database, 'my+db'); + t.equal(subject.client_encoding, 'utf8'); + t.end(); +}); + +test('password contains < and/or > characters', function(t){ + var sourceConfig = { + user:'brian', + password: 'helloe', + port: 5432, + host: 'localhost', + database: 'postgres' + }; + var connectionString = 'postgres://' + sourceConfig.user + ':' + sourceConfig.password + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database; + var subject = parse(connectionString); + t.equal(subject.password, sourceConfig.password); + t.end(); +}); + +test('username or password contains weird characters', function(t){ + var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000'; + var subject = parse(strang); + t.equal(subject.user, 'my f%irst name'); + t.equal(subject.password, 'is&%awesome!'); + t.equal(subject.host, 'localhost'); + t.end(); +}); + +test('url is properly encoded', function(t){ + var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl'; + var subject = parse(encoded); + t.equal(subject.user, 'bi%na%%ry '); + t.equal(subject.password, 's@f#'); + t.equal(subject.host, 'localhost'); + t.equal(subject.database, ' u%20rl'); + t.end(); +}); From df2a24c55550d48afe9d6b57dff7b7c027ba124e Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Sun, 6 Jul 2014 16:33:53 -0700 Subject: [PATCH 0056/1037] attach port always - ref brianc/node-postgres#604 --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 6c8fb68dc..afb369960 100644 --- a/index.js +++ b/index.js @@ -28,6 +28,7 @@ function parse(str) { config.fallback_application_name = result.query.fallback_application_name; } + config.port = result.port; if(result.protocol == 'socket:') { config.host = decodeURI(result.pathname); config.database = result.query.db; @@ -39,7 +40,6 @@ function parse(str) { var auth = (result.auth || ':').split(':'); config.user = auth[0]; config.password = auth[1]; - config.port = result.port; var ssl = result.query.ssl; if (ssl === 'true' || ssl === '1') { From cb9bee1bc9d65366d516fd2808726f285c9ad72f Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Sun, 6 Jul 2014 16:34:14 -0700 Subject: [PATCH 0057/1037] 0.1.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 56f535dd2..2cb8d962e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "0.1.0", + "version": "0.1.1", "description": "Functions for dealing with a PostgresSQL connection string", "main": "index.js", "scripts": { From ba511f7803dd159447ca7801177dd9008b9958b3 Mon Sep 17 00:00:00 2001 From: "matthew.blasius" Date: Fri, 12 Sep 2014 11:21:33 -0400 Subject: [PATCH 0058/1037] Support usage of relative urls to set database on the default host --- index.js | 10 +++++++++- test/parse.js | 23 +++++++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index afb369960..b041a2081 100644 --- a/index.js +++ b/index.js @@ -36,7 +36,15 @@ function parse(str) { return config; } config.host = result.hostname; - config.database = result.pathname ? decodeURI(result.pathname.slice(1)) : null; + + // result.pathname is not always guaranteed to have a '/' prefix (e.g. relative urls) + // only strip the slash if it is present. + var pathname = result.pathname; + if (pathname && pathname.charAt(0) === '/') { + pathname = result.pathname.slice(1) || null; + } + config.database = pathname && decodeURI(pathname); + var auth = (result.auth || ':').split(':'); config.user = auth[0]; config.password = auth[1]; diff --git a/test/parse.js b/test/parse.js index 1b9b203c9..892694290 100644 --- a/test/parse.js +++ b/test/parse.js @@ -87,3 +87,26 @@ test('url is properly encoded', function(t){ t.equal(subject.database, ' u%20rl'); t.end(); }); + +test('relative url sets database', function(t){ + var relative = 'different_db_on_default_host'; + var subject = parse(relative); + t.equal(subject.database, 'different_db_on_default_host'); + t.end(); +}); + +test('no pathname returns null database', function (t) { + var subject = parse('pg://myhost'); + t.equal(subject.host, 'myhost'); + t.type(subject.database, 'null'); + + t.end(); +}); + +test('pathname of "/" returns null database', function (t) { + var subject = parse('pg://myhost/'); + t.equal(subject.host, 'myhost'); + t.type(subject.database, 'null'); + + t.end(); +}); From 245abd6daf838d6d2e0424debcfffc2e8b3e3508 Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Sat, 13 Sep 2014 09:20:28 -0700 Subject: [PATCH 0059/1037] 0.1.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2cb8d962e..ebac6ca4e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "0.1.1", + "version": "0.1.2", "description": "Functions for dealing with a PostgresSQL connection string", "main": "index.js", "scripts": { From 19a2d26fc189cab1676a7a20b22f5085512e63e1 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 24 Sep 2014 23:42:51 -0400 Subject: [PATCH 0060/1037] Add client#close Closes #6 --- README.md | 5 +++++ index.js | 11 +++++++++++ package.json | 2 +- test/close.js | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 test/close.js diff --git a/README.md b/README.md index 5263d9895..16adc25f2 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,11 @@ Read `rowCount` rows from the cursor instance. The `callback` will be called wh If the cursor has read to the end of the result sets all subsequent calls to `cursor#read` will return a 0 length array of rows. I'm open to other ways to signal the end of a cursor, but this has worked out well for me so far. + +#### cursor#close(function callback(Error err)) + +Closes the backend portal before itterating through the entire result set. Useful when you want to 'abort' out of a read early but continue to use the same client for other queries after the cursor is finished. + ### install ```sh diff --git a/index.js b/index.js index 2d8e088b5..457d7f6c6 100644 --- a/index.js +++ b/index.js @@ -124,6 +124,17 @@ Cursor.prototype.end = function(cb) { this.connection.stream.once('end', cb) } +Cursor.prototype.close = function(cb) { + this.connection.close({type: 'P'}) + this.connection.sync() + this.state = 'done' + if(cb) { + this.connection.once('closeComplete', function() { + cb() + }) + } +} + Cursor.prototype.read = function(rows, cb) { var self = this if(this.state == 'idle') { diff --git a/package.json b/package.json index e3c41869b..c8c71d4b6 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "author": "Brian M. Carlson", "license": "MIT", "devDependencies": { - "pg.js": "~2.8.1", + "pg.js": "~3.4.4", "mocha": "~1.17.1" }, "dependencies": {} diff --git a/test/close.js b/test/close.js new file mode 100644 index 000000000..5f4f5bd98 --- /dev/null +++ b/test/close.js @@ -0,0 +1,35 @@ +var assert = require('assert') +var Cursor = require('../') +var pg = require('pg.js') + +var text = 'SELECT generate_series as num FROM generate_series(0, 50)' +describe('close', function() { + beforeEach(function(done) { + var client = this.client = new pg.Client() + client.connect(done) + client.on('drain', client.end.bind(client)) + }) + + it('closes cursor early', function(done) { + var cursor = new Cursor(text) + this.client.query(cursor) + this.client.query('SELECT NOW()', done) + cursor.read(25, function(err, res) { + assert.ifError(err) + cursor.close() + }) + }) + + it('works with callback style', function(done) { + var cursor = new Cursor(text) + var client = this.client + client.query(cursor) + cursor.read(25, function(err, res) { + assert.ifError(err) + cursor.close(function(err) { + assert.ifError(err) + client.query('SELECT NOW()', done) + }) + }) + }) +}) From 40f361fd8e0e16d82724f5207bd30cc9c7ae8418 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 24 Sep 2014 23:43:15 -0400 Subject: [PATCH 0061/1037] Add boilerplate files --- .travis.yml | 6 ++++++ Makefile | 14 ++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 .travis.yml create mode 100644 Makefile diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..061e3d15a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - "0.10" + - "0.11" +env: + - PGUSER=postgres diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..d7ec83d54 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +.PHONY: 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 From 8d395ff8c0005b86f4f3e3c5fde32b13cba4a3fa Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 24 Sep 2014 23:43:25 -0400 Subject: [PATCH 0062/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c8c71d4b6..8c26d80ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "0.2.0", + "version": "1.0.0", "description": "", "main": "index.js", "directories": { From fbdd033d6c90cf5f9c2f6f258bc77a2184345f20 Mon Sep 17 00:00:00 2001 From: Ivan Sorokin Date: Fri, 26 Sep 2014 15:59:57 +0300 Subject: [PATCH 0063/1037] Add supporting password with colon --- index.js | 2 +- test/parse.js | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index b041a2081..ac2fd64c1 100644 --- a/index.js +++ b/index.js @@ -47,7 +47,7 @@ function parse(str) { var auth = (result.auth || ':').split(':'); config.user = auth[0]; - config.password = auth[1]; + config.password = auth.splice(1).join(':'); var ssl = result.query.ssl; if (ssl === 'true' || ssl === '1') { diff --git a/test/parse.js b/test/parse.js index 892694290..c1494c31e 100644 --- a/test/parse.js +++ b/test/parse.js @@ -69,6 +69,20 @@ test('password contains < and/or > characters', function(t){ t.end(); }); +test('password contains colons', function(t){ + var sourceConfig = { + user:'brian', + password: 'hello:pass:world', + port: 5432, + host: 'localhost', + database: 'postgres' + }; + var connectionString = 'postgres://' + sourceConfig.user + ':' + sourceConfig.password + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database; + var subject = parse(connectionString); + t.equal(subject.password, sourceConfig.password); + t.end(); +}); + test('username or password contains weird characters', function(t){ var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000'; var subject = parse(strang); From 4c151b9403420c1c9a9682facef1fcdbb9b79b3b Mon Sep 17 00:00:00 2001 From: Blaine Bublitz Date: Fri, 26 Sep 2014 14:22:46 -0700 Subject: [PATCH 0064/1037] 0.1.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ebac6ca4e..c6d4512d9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "0.1.2", + "version": "0.1.3", "description": "Functions for dealing with a PostgresSQL connection string", "main": "index.js", "scripts": { From 6ab80d3995711435f63613bdfd5f241f0d94f823 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 30 Oct 2014 18:38:44 -0400 Subject: [PATCH 0065/1037] Add close method & supporting tests --- index.js | 28 +++++++++++++++++++++------- package.json | 2 +- test/close.js | 22 +++++++++++++++++++++- test/slow-reader.js | 29 +++++++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 test/slow-reader.js diff --git a/index.js b/index.js index e346457b1..a5fc2da3d 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,9 @@ var Cursor = require('pg-cursor') var Readable = require('readable-stream').Readable var QueryStream = module.exports = function(text, values, options) { - var self = this; + var self = this + this._reading = false + this._closing = false options = options || { } Cursor.call(this, text, values) Readable.call(this, { @@ -13,12 +15,15 @@ var QueryStream = module.exports = function(text, values, options) { this.batchSize = options.batchSize || 100 this.once('end', function() { process.nextTick(function() { - self.emit('close') - }); - }) + self.emit('close') + }) + }) } util.inherits(QueryStream, Readable) + +//copy cursor prototype to QueryStream +//so we can handle all the events emitted by the connection for(var key in Cursor.prototype) { if(key == 'read') { QueryStream.prototype._fetch = Cursor.prototype.read @@ -27,10 +32,19 @@ for(var key in Cursor.prototype) { } } - +QueryStream.prototype.close = function() { + this._closing = true + var self = this + Cursor.prototype.close.call(this, function(err) { + if(err) return self.emit('error', err) + process.nextTick(function() { + self.push(null) + }) + }) +} QueryStream.prototype._read = function(n) { - if(this._reading) return false; + if(this._reading || this._closing) return false this._reading = true var self = this this._fetch(this.batchSize, function(err, rows) { @@ -41,7 +55,7 @@ QueryStream.prototype._read = function(n) { process.nextTick(function() { self.push(null) }) - return; + return } self._reading = false for(var i = 0; i < rows.length; i++) { diff --git a/package.json b/package.json index 1ac30f4cb..1f9d0744f 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "mocha": "~1.17.1" }, "dependencies": { - "pg-cursor": "0.2.0", + "pg-cursor": "1.0.0", "readable-stream": "^1.0.27-1" } } diff --git a/test/close.js b/test/close.js index 6f319a75e..d41fa621f 100644 --- a/test/close.js +++ b/test/close.js @@ -4,8 +4,9 @@ var tester = require('stream-tester') var JSONStream = require('JSONStream') var QueryStream = require('../') +var helper = require('./helper') -require('./helper')('close', function(client) { +helper('close', function(client) { it('emits close', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], {batchSize: 2, highWaterMark: 2}) var query = client.query(stream) @@ -13,3 +14,22 @@ require('./helper')('close', function(client) { query.on('close', done) }) }) + +helper('early close', function(client) { + it('can be closed early', function(done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [20000], {batchSize: 2, highWaterMark: 2}) + var query = client.query(stream) + var readCount = 0 + query.on('readable', function() { + readCount++ + query.read() + }) + query.once('readable', function() { + query.close() + }) + query.on('close', function() { + assert(readCount < 10, 'should not have read more than 10 rows') + done() + }) + }) +}) diff --git a/test/slow-reader.js b/test/slow-reader.js new file mode 100644 index 000000000..b9675a368 --- /dev/null +++ b/test/slow-reader.js @@ -0,0 +1,29 @@ +var assert = require('assert') +var helper = require('./helper') +var QueryStream = require('../') +var concat = require('concat-stream') + +var Transform = require('stream').Transform + +var mapper = new Transform({objectMode: true}) + +mapper._transform = function(obj, enc, cb) { + this.push(obj) + setTimeout(cb, 5) +} + +helper('slow reader', function(client) { + it('works', function(done) { + this.timeout(50000) + var stream = new QueryStream('SELECT * FROM generate_series(0, 201) num', [], {highWaterMark: 100, batchSize: 50}) + stream.on('end', function() { + //console.log('stream end') + }) + var query = client.query(stream) + var result = [] + var count = 0 + stream.pipe(mapper).pipe(concat(function(res) { + done() + })) + }) +}) From 1dd2d3a9388f1eb542da2a761541b32aacee09c7 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 3 Nov 2014 10:44:19 -0500 Subject: [PATCH 0066/1037] Add infrastructure files --- .travis.yml | 6 ++++++ Makefile | 14 ++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 .travis.yml create mode 100644 Makefile diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..061e3d15a --- /dev/null +++ b/.travis.yml @@ -0,0 +1,6 @@ +language: node_js +node_js: + - "0.10" + - "0.11" +env: + - PGUSER=postgres diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..d7ec83d54 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +.PHONY: 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 From 02ff00a374f3dd53a51c70124650771bed36278b Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 3 Nov 2014 10:44:26 -0500 Subject: [PATCH 0067/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1f9d0744f..ebfc21f1d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "0.6.0", + "version": "0.7.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From aa61055029051bb227a66b4feddf0357cb5e83f2 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 3 Nov 2014 10:46:25 -0500 Subject: [PATCH 0068/1037] Update README.md Add travis badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 597538ed5..37601a8f1 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # pg-query-stream +[![Build Status](https://travis-ci.org/brianc/node-pg-query-stream.svg)](https://travis-ci.org/brianc/node-pg-query-stream) + Receive result rows from [pg](https://github.com/brianc/node-postgres) as a readable (object) stream. This module __only works with the pure JavaScript client__. From b38d092fa6184482e51c1b28c9f661133b08d1f7 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 3 Nov 2014 12:34:16 -0500 Subject: [PATCH 0069/1037] Update travis file --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 061e3d15a..87a477347 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,5 +2,8 @@ language: node_js node_js: - "0.10" - "0.11" +before_script: + - psql -c 'create database travis_ci_test;' -U postgres env: - PGUSER=postgres + - PGDATABASE=travis_ci_test From e9d1872c707740ca75660aa3d129c4fb4b6d4e38 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 3 Nov 2014 12:52:04 -0500 Subject: [PATCH 0070/1037] Test new travis config --- .travis.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 87a477347..e3ce3b1c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,5 @@ language: node_js node_js: - "0.10" - "0.11" -before_script: - - psql -c 'create database travis_ci_test;' -U postgres env: - - PGUSER=postgres - - PGDATABASE=travis_ci_test + - PGUSER=postgres PGDATABASE=postgres From 56ebc6a65698153d80d99ae034c1c90d612d6925 Mon Sep 17 00:00:00 2001 From: Desmond Brand Date: Wed, 18 Mar 2015 00:40:22 -0700 Subject: [PATCH 0071/1037] Fix typo: itterate -> iterate --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 16adc25f2..1cddfbfdc 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ Use a PostgreSQL result cursor from node with an easy to use API. ### why? -Sometimes you need to itterate through a table in chunks. It's extremely inefficient to use hand-crafted `LIMIT` and `OFFSET` queries to do this. +Sometimes you need to iterate through a table in chunks. It's extremely inefficient to use hand-crafted `LIMIT` and `OFFSET` queries to do this. PostgreSQL provides built-in functionality to fetch a "cursor" to your results and page through the cursor efficiently fetching chunks of the results with full MVCC compliance. This actually ends up pairing very nicely with node's _asyncness_ and handling a lot of data. PostgreSQL is rad. From c612dfabd58071e9896b1e9ba0b5e5bcbb0c2f6b Mon Sep 17 00:00:00 2001 From: Mike He Date: Tue, 13 Oct 2015 09:19:26 +1100 Subject: [PATCH 0072/1037] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 49862702b..ddf9bfcb3 100644 --- a/README.md +++ b/README.md @@ -14,5 +14,5 @@ MIT License ```js var parse = require('pg-connection-string').parse; -var config = parse('postgres://someuser:somepassword@somehost:381/sometable') +var config = parse('postgres://someuser:somepassword@somehost:381/somedatabase') ``` From 68819dffdac44d7248477ff4e6961a244fce2325 Mon Sep 17 00:00:00 2001 From: "matthew.blasius" Date: Thu, 5 Nov 2015 14:09:50 -0500 Subject: [PATCH 0073/1037] Avoid race when stream closed while fetching --- index.js | 3 +++ test/close.js | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/index.js b/index.js index a5fc2da3d..4be25f1be 100644 --- a/index.js +++ b/index.js @@ -51,6 +51,9 @@ QueryStream.prototype._read = function(n) { if(err) { return self.emit('error', err) } + + if (self._closing) { return; } + if(!rows.length) { process.nextTick(function() { self.push(null) diff --git a/test/close.js b/test/close.js index d41fa621f..35af30b50 100644 --- a/test/close.js +++ b/test/close.js @@ -33,3 +33,50 @@ helper('early close', function(client) { }) }) }) + + +helper('should not throw errors after early close', function(client) { + it('can be closed early without error', function(done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, 2000) num'); + var query = client.query(stream); + var fetchCount = 0; + var errorCount = 0; + + + function waitForErrors() { + + setTimeout(function () { + assert(errorCount === 0, 'should not throw a ton of errors'); + done(); + }, 10); + } + + // hack internal _fetch function to force query.close immediately after _fetch is called (simulating the race condition) + // race condition: if close is called immediately after _fetch is called, but before results are returned, errors are thrown + // when the fetch results are pushed to the readable stream after its already closed. + query._fetch = (function (_fetch) { + return function () { + + // wait for the second fetch. closing immediately after the first fetch throws an entirely different error :( + if (fetchCount++ === 0) { + return _fetch.apply(this, arguments); + } + + var results = _fetch.apply(this, arguments); + + query.close(); + waitForErrors(); + + query._fetch = _fetch; // we're done with our hack, so restore the original _fetch function. + + return results; + } + }(query._fetch)); + + query.on('error', function () { errorCount++; }); + + query.on('readable', function () { + query.read(); + }); + }); +}); From d1ac31c105ebcaa07735745dd43cb40d29b432e1 Mon Sep 17 00:00:00 2001 From: "matthew.blasius" Date: Thu, 5 Nov 2015 16:47:53 -0500 Subject: [PATCH 0074/1037] Support a close callback when closing the stream --- index.js | 3 ++- test/close.js | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 4be25f1be..e19650925 100644 --- a/index.js +++ b/index.js @@ -32,10 +32,11 @@ for(var key in Cursor.prototype) { } } -QueryStream.prototype.close = function() { +QueryStream.prototype.close = function(cb) { this._closing = true var self = this Cursor.prototype.close.call(this, function(err) { + if (cb) { cb(err); } if(err) return self.emit('error', err) process.nextTick(function() { self.push(null) diff --git a/test/close.js b/test/close.js index 35af30b50..c0a300961 100644 --- a/test/close.js +++ b/test/close.js @@ -34,7 +34,6 @@ helper('early close', function(client) { }) }) - helper('should not throw errors after early close', function(client) { it('can be closed early without error', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 2000) num'); @@ -80,3 +79,22 @@ helper('should not throw errors after early close', function(client) { }); }); }); + +helper('close callback', function (client) { + it('notifies an optional callback when the conneciton is closed', function (done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [10], {batchSize: 2, highWaterMark: 2}); + var query = client.query(stream); + query.once('readable', function() { // only reading once + query.read(); + }); + query.once('readable', function() { + query.close(function () { + // nothing to assert. This test will time out if the callback does not work. + done(); + }); + }); + query.on('close', function () { + assert(false, "close event should not fire"); // no close event because we did not read to the end of the stream. + }); + }); +}); From 27bba8de04f0a7eac5b5e7600d1d2ba0de91cc7b Mon Sep 17 00:00:00 2001 From: brianc Date: Fri, 13 Nov 2015 10:33:39 -0600 Subject: [PATCH 0075/1037] Conform to readable stream spec One of the tests was failing because it was testing that when a stream became readable it never returned a `null` datum on call to `stream.read()`. In fact, when a readable stream drains it should & does return `null` for calls to `stream.read()` as described [here](https://nodejs.org/api/stream.html#stream_event_readable) I updated the test to account for this, and they pass now. --- package.json | 2 +- test/fast-reader.js | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ebfc21f1d..7fca43b66 100644 --- a/package.json +++ b/package.json @@ -32,6 +32,6 @@ }, "dependencies": { "pg-cursor": "1.0.0", - "readable-stream": "^1.0.27-1" + "readable-stream": "^2.0.4" } } diff --git a/test/fast-reader.js b/test/fast-reader.js index dd967631b..a99326d73 100644 --- a/test/fast-reader.js +++ b/test/fast-reader.js @@ -10,7 +10,13 @@ helper('fast reader', function(client) { var count = 0 stream.on('readable', function() { var res = stream.read() - assert(res, 'should not return null on evented reader') + if (result.length !== 201) { + assert(res, 'should not return null on evented reader') + } else { + //a readable stream will emit a null datum when it finishes being readable + //https://nodejs.org/api/stream.html#stream_event_readable + assert.equal(res, null) + } if(res) { result.push(res.num) } From 9aca077f3e47e75a6b78e5bc02b144bfefdedd80 Mon Sep 17 00:00:00 2001 From: brianc Date: Fri, 13 Nov 2015 10:39:28 -0600 Subject: [PATCH 0076/1037] Add more versions of node to the travis matrix --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e3ce3b1c6..95eb599ef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,7 @@ language: node_js node_js: - "0.10" - - "0.11" + - "0.12" + - "4.2" env: - PGUSER=postgres PGDATABASE=postgres From df8acf0aaa1e75113e7682b3cf6c2010f9e68f42 Mon Sep 17 00:00:00 2001 From: brianc Date: Fri, 13 Nov 2015 10:40:12 -0600 Subject: [PATCH 0077/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7fca43b66..02f78231e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "0.7.0", + "version": "1.0.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From 802616b0286c9a70053b6c5ab4e0446e98ad7e07 Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 13 Nov 2015 10:53:02 -0600 Subject: [PATCH 0078/1037] Update README.md Remove outdated information about pg.js --- README.md | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 37601a8f1..4e49d8f24 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,6 @@ Receive result rows from [pg](https://github.com/brianc/node-postgres) as a readable (object) stream. -This module __only works with the pure JavaScript client__. ## installation @@ -15,14 +14,6 @@ $ npm install pg-query-stream _requires pg>=2.8.1_ -##### - or - - -```bash -$ npm install pg.js -$ npm install pg-query-stream -``` - -_requires pg.js>=2.8.1_ ## use @@ -46,6 +37,8 @@ The stream uses a cursor on the server so it efficiently keeps only a low number This is especially useful when doing [ETL](http://en.wikipedia.org/wiki/Extract,_transform,_load) on a huge table. Using manual `limit` and `offset` queries to fake out async itteration through your data is cumbersom, and _way way way_ slower than using a cursor. +_note: this module only works with the JavaScript client, and does not work with the native bindings. libpq doesn't expose the protocol at a level where a cursor can be manipulated directly_ + ## contribution I'm very open to contribution! Open a pull request with your code or idea and we'll talk about it. If it's not way insane we'll merge it in too: isn't open source awesome? From cdf06edd14d7b4b1df4c7e3cf438e8d9eeeaf271 Mon Sep 17 00:00:00 2001 From: Moti Zilberman Date: Wed, 30 Dec 2015 15:16:38 +0200 Subject: [PATCH 0079/1037] Copy all but special-cased params from URL query string to config --- index.js | 19 +++++++++------ test/parse.js | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index ac2fd64c1..b2863ddef 100644 --- a/index.js +++ b/index.js @@ -21,13 +21,6 @@ function parse(str) { var result = url.parse(str, true); config = {}; - if (result.query.application_name) { - config.application_name = result.query.application_name; - } - if (result.query.fallback_application_name) { - config.fallback_application_name = result.query.fallback_application_name; - } - config.port = result.port; if(result.protocol == 'socket:') { config.host = decodeURI(result.pathname); @@ -54,6 +47,18 @@ function parse(str) { config.ssl = true; } + ['db', 'database', 'encoding', 'client_encoding', 'host', 'port', 'user', 'password', 'ssl'] + .forEach(function(key) { + delete result.query[key]; + }); + + Object.getOwnPropertyNames(result.query).forEach(function(key) { + var value = result.query[key]; + if (Array.isArray(value)) + value = value[value.length-1]; + config[key] = value; + }); + return config; } diff --git a/test/parse.js b/test/parse.js index c1494c31e..bd1171ba7 100644 --- a/test/parse.js +++ b/test/parse.js @@ -124,3 +124,67 @@ test('pathname of "/" returns null database', function (t) { t.end(); }); + +test('configuration parameter application_name', function(t){ + var connectionString = 'pg:///?application_name=TheApp'; + var subject = parse(connectionString); + t.equal(subject.application_name, 'TheApp'); + t.end(); +}); + +test('configuration parameter fallback_application_name', function(t){ + var connectionString = 'pg:///?fallback_application_name=TheAppFallback'; + var subject = parse(connectionString); + t.equal(subject.fallback_application_name, 'TheAppFallback'); + t.end(); +}); + +test('configuration parameter fallback_application_name', function(t){ + var connectionString = 'pg:///?fallback_application_name=TheAppFallback'; + var subject = parse(connectionString); + t.equal(subject.fallback_application_name, 'TheAppFallback'); + t.end(); +}); + +test('configuration parameter ssl=true', function(t){ + var connectionString = 'pg:///?ssl=true'; + var subject = parse(connectionString); + t.equal(subject.ssl, true); + t.end(); +}); + +test('configuration parameter ssl=1', function(t){ + var connectionString = 'pg:///?ssl=1'; + var subject = parse(connectionString); + t.equal(subject.ssl, true); + t.end(); +}); + +test('configuration parameter keepalives', function(t){ + var connectionString = 'pg:///?keepalives=1'; + var subject = parse(connectionString); + t.equal(subject.keepalives, '1'); + t.end(); +}); + +test('unknown configuration parameter is passed into client', function(t){ + var connectionString = 'pg:///?ThereIsNoSuchPostgresParameter=1234'; + var subject = parse(connectionString); + t.equal(subject.ThereIsNoSuchPostgresParameter, '1234'); + t.end(); +}); + +test('do not override a config field with value from query string', function(t){ + var subject = parse('socket:/some path/?db=my[db]&encoding=utf8&client_encoding=bogus'); + t.equal(subject.host, '/some path/'); + t.equal(subject.database, 'my[db]', 'must to be escaped and unescaped trough "my%5Bdb%5D"'); + t.equal(subject.client_encoding, 'utf8'); + t.end(); +}); + +test('return last value of repeated parameter', function(t){ + var connectionString = 'pg:///?keepalives=1&keepalives=0'; + var subject = parse(connectionString); + t.equal(subject.keepalives, '0'); + t.end(); +}); \ No newline at end of file From c0d39055f2b5bc2fb6bf2b46c7f80980846fe73a Mon Sep 17 00:00:00 2001 From: brianc Date: Tue, 7 Jun 2016 19:16:19 -0500 Subject: [PATCH 0080/1037] Initial commit --- .gitignore | 1 + index.js | 118 ++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 40 ++++++++++++++++ test/index.js | 111 +++++++++++++++++++++++++++++++++++++++++++++ test/mocha.opts | 2 + 5 files changed, 272 insertions(+) create mode 100644 .gitignore create mode 100644 index.js create mode 100644 package.json create mode 100644 test/index.js create mode 100644 test/mocha.opts diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/index.js b/index.js new file mode 100644 index 000000000..7c102d8a6 --- /dev/null +++ b/index.js @@ -0,0 +1,118 @@ +var genericPool = require('generic-pool') +var util = require('util') +var EventEmitter = require('events').EventEmitter +var debug = require('debug') + +var Pool = module.exports = function(options) { + EventEmitter.call(this) + this.options = options || {} + this.log = this.options.log || debug('pg:pool') + this.Client = this.options.Client || require('pg').Client + this.Promise = this.options.Promise || Promise + + this.options.max = this.options.max || this.options.poolSize || 10 + this.options.create = this.options.create || this._create.bind(this) + this.options.destroy = this.options.destroy || this._destroy.bind(this) + this.pool = new genericPool.Pool(this.options) +} + +util.inherits(Pool, EventEmitter) + +Pool.prototype._destroy = function(client) { + if (client._destroying) return + client._destroying = true + client.end() +} + +Pool.prototype._create = function(cb) { + this.log('connecting new client') + var client = new this.Client(this.options) + + client.on('error', function(e) { + this.log('connected client error:', e) + this.pool.destroy(client) + e.client = client + this.emit('error', e) + }.bind(this)) + + client.connect(function(err) { + this.log('client connected') + if (err) { + this.log('client connection error:', e) + cb(err) + } + + client.queryAsync = function(text, values) { + return new this.Promise((resolve, reject) => { + client.query(text, values, function(err, res) { + err ? reject(err) : resolve(res) + }) + }) + }.bind(this) + + cb(err, err ? null : client) + }.bind(this)) +} + +Pool.prototype.connect = function(cb) { + return new this.Promise(function(resolve, reject) { + this.log('acquire client begin') + this.pool.acquire(function(err, client) { + if (err) { + this.log('acquire client. error:', err) + if (cb) { + cb(err, null, function() { }) + } + return reject(err) + } + + this.log('acquire client') + + client.release = function(err) { + if (err) { + this.log('release client. error:', err) + this.pool.destroy(client) + } + this.log('release client') + delete client.release + this.pool.release(client) + }.bind(this) + + if (cb) { + cb(null, client, client.release) + } + + return resolve(client) + }.bind(this)) + }.bind(this)) +} + +Pool.prototype.take = Pool.prototype.connect + +Pool.prototype.query = function(text, values) { + return this.take().then(function(client) { + return client.queryAsync(text, values) + .then(function(res) { + client.release() + return res + }).catch(function(error) { + client.release(error) + throw error + }) + }) +} + +Pool.prototype.end = function(cb) { + this.log('draining pool') + return new this.Promise(function(resolve, reject) { + this.pool.drain(function() { + this.log('pool drained, calling destroy all now') + this.pool.destroyAllNow(function() { + if(cb) { + cb() + } + resolve() + }) + }.bind(this)) + }.bind(this)) +} diff --git a/package.json b/package.json new file mode 100644 index 000000000..7d8b8f098 --- /dev/null +++ b/package.json @@ -0,0 +1,40 @@ +{ + "name": "pg-pool", + "version": "0.0.1", + "description": "Connection pool for node-postgres", + "main": "index.js", + "directories": { + "test": "test" + }, + "scripts": { + "test": "node_modules/.bin/mocha" + }, + "repository": { + "type": "git", + "url": "git://github.com/brianc/node-pg-pool.git" + }, + "keywords": [ + "pg", + "postgres", + "pool", + "database" + ], + "author": "Brian M. Carlson", + "license": "MIT", + "bugs": { + "url": "https://github.com/brianc/node-pg-pool/issues" + }, + "homepage": "https://github.com/brianc/node-pg-pool#readme", + "devDependencies": { + "bluebird": "3.4.0", + "co": "4.6.0", + "expect.js": "0.3.1", + "lodash": "4.13.1", + "mocha": "^2.3.3", + "pg": "4.5.6" + }, + "dependencies": { + "debug": "^2.2.0", + "generic-pool": "2.4.2" + } +} diff --git a/test/index.js b/test/index.js new file mode 100644 index 000000000..4ea43cd08 --- /dev/null +++ b/test/index.js @@ -0,0 +1,111 @@ +var expect = require('expect.js') +var Client = require('pg').Client +var co = require('co') +var Promise = require('bluebird') +var _ = require('lodash') + +var 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() + expect(client.binary).to.eql(true) + pool.end(done) + }) + }) + + it('removes client if it errors in background', function(done) { + const pool = new Pool() + pool.connect(function(err, client, release) { + release() + 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) + }) + }) + }) + }) + + describe('with promises', function() { + it('connects and disconnects', co.wrap(function*() { + var pool = new Pool() + var client = yield pool.connect() + expect(pool.pool.availableObjectsCount()).to.be(0) + var res = yield client.queryAsync('select $1::text as name', ['hi']) + expect(res.rows).to.eql([{ name: 'hi' }]) + client.release() + expect(pool.pool.getPoolSize()).to.be(1) + expect(pool.pool.availableObjectsCount()).to.be(1) + return yield pool.end() + })) + + it('properly pools clients', co.wrap(function*() { + var pool = new Pool({ poolSize: 9 }) + var count = 0 + while (count < 30) { + count++ + pool.connect().then(function(client) { + client.queryAsync('select $1::text as name', ['hi']).then(function(res) { + client.release() + }) + }) + } + yield Promise.delay(100) + expect(pool.pool.getPoolSize()).to.be(9) + return yield pool.end() + })) + + it('supports just running queries', co.wrap(function*() { + var pool = new Pool({ poolSize: 9 }) + var count = 0 + var queries = _.times(30).map(function() { + return pool.query('SELECT $1::text as name', ['hi']) + }) + console.log('executing') + yield queries + expect(pool.pool.getPoolSize()).to.be(9) + expect(pool.pool.availableObjectsCount()).to.be(9) + return yield pool.end() + })) + + it('recovers from all errors', co.wrap(function*() { + var pool = new Pool({ poolSize: 9 }) + var count = 0 + + while(count++ < 30) { + try { + yield pool.query('SELECT lksjdfd') + } catch(e) { + } + } + var res = yield pool.query('SELECT $1::text as name', ['hi']) + expect(res.rows).to.eql([{ name: 'hi' }]) + return yield pool.end() + })) + }) +}) diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 000000000..46e8e69d9 --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1,2 @@ +--no-exit +--bail From ad73407aad29d1fcc7cf9adb0ca3c0c33523f312 Mon Sep 17 00:00:00 2001 From: brianc Date: Tue, 7 Jun 2016 19:37:07 -0500 Subject: [PATCH 0081/1037] Initial commit --- .gitignore | 1 + Makefile | 14 +++++++++++++ index.js | 46 +++++++++++++++++++++---------------------- package.json | 8 +++++--- test/index.js | 54 +++++++++++++++++++++++++-------------------------- 5 files changed, 70 insertions(+), 53 deletions(-) create mode 100644 Makefile diff --git a/.gitignore b/.gitignore index 3c3629e64..93f136199 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +npm-debug.log diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..8a7631426 --- /dev/null +++ b/Makefile @@ -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 diff --git a/index.js b/index.js index 7c102d8a6..a21e2c0dc 100644 --- a/index.js +++ b/index.js @@ -3,11 +3,11 @@ var util = require('util') var EventEmitter = require('events').EventEmitter var debug = require('debug') -var Pool = module.exports = function(options) { +var Pool = module.exports = function (options, Client) { EventEmitter.call(this) this.options = options || {} this.log = this.options.log || debug('pg:pool') - this.Client = this.options.Client || require('pg').Client + this.Client = this.options.Client || Client || require('pg').Client this.Promise = this.options.Promise || Promise this.options.max = this.options.max || this.options.poolSize || 10 @@ -18,33 +18,33 @@ var Pool = module.exports = function(options) { util.inherits(Pool, EventEmitter) -Pool.prototype._destroy = function(client) { +Pool.prototype._destroy = function (client) { if (client._destroying) return client._destroying = true client.end() } -Pool.prototype._create = function(cb) { +Pool.prototype._create = function (cb) { this.log('connecting new client') var client = new this.Client(this.options) - client.on('error', function(e) { + client.on('error', function (e) { this.log('connected client error:', e) this.pool.destroy(client) e.client = client this.emit('error', e) }.bind(this)) - client.connect(function(err) { + client.connect(function (err) { this.log('client connected') if (err) { - this.log('client connection error:', e) + this.log('client connection error:', err) cb(err) } - client.queryAsync = function(text, values) { + client.queryAsync = function (text, values) { return new this.Promise((resolve, reject) => { - client.query(text, values, function(err, res) { + client.query(text, values, function (err, res) { err ? reject(err) : resolve(res) }) }) @@ -54,21 +54,21 @@ Pool.prototype._create = function(cb) { }.bind(this)) } -Pool.prototype.connect = function(cb) { - return new this.Promise(function(resolve, reject) { +Pool.prototype.connect = function (cb) { + return new this.Promise(function (resolve, reject) { this.log('acquire client begin') - this.pool.acquire(function(err, client) { + this.pool.acquire(function (err, client) { if (err) { this.log('acquire client. error:', err) if (cb) { - cb(err, null, function() { }) + cb(err, null, function () {}) } return reject(err) } this.log('acquire client') - client.release = function(err) { + client.release = function (err) { if (err) { this.log('release client. error:', err) this.pool.destroy(client) @@ -89,26 +89,26 @@ Pool.prototype.connect = function(cb) { Pool.prototype.take = Pool.prototype.connect -Pool.prototype.query = function(text, values) { - return this.take().then(function(client) { +Pool.prototype.query = function (text, values) { + return this.take().then(function (client) { return client.queryAsync(text, values) - .then(function(res) { + .then(function (res) { client.release() return res - }).catch(function(error) { + }).catch(function (error) { client.release(error) throw error }) }) } -Pool.prototype.end = function(cb) { +Pool.prototype.end = function (cb) { this.log('draining pool') - return new this.Promise(function(resolve, reject) { - this.pool.drain(function() { + return new this.Promise(function (resolve, reject) { + this.pool.drain(function () { this.log('pool drained, calling destroy all now') - this.pool.destroyAllNow(function() { - if(cb) { + this.pool.destroyAllNow(function () { + if (cb) { cb() } resolve() diff --git a/package.json b/package.json index 7d8b8f098..1c5f6ed48 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,13 @@ { "name": "pg-pool", - "version": "0.0.1", + "version": "1.0.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { "test": "test" }, "scripts": { - "test": "node_modules/.bin/mocha" + "test": "node_modules/.bin/standard && node_modules/.bin/mocha" }, "repository": { "type": "git", @@ -31,7 +31,9 @@ "expect.js": "0.3.1", "lodash": "4.13.1", "mocha": "^2.3.3", - "pg": "4.5.6" + "pg": "4.5.6", + "standard": "7.1.2", + "standard-format": "2.2.1" }, "dependencies": { "debug": "^2.2.0", diff --git a/test/index.js b/test/index.js index 4ea43cd08..bc547cc81 100644 --- a/test/index.js +++ b/test/index.js @@ -1,19 +1,20 @@ var expect = require('expect.js') -var Client = require('pg').Client var co = require('co') var Promise = require('bluebird') var _ = require('lodash') -var Pool = require('../') +var describe = require('mocha').describe +var it = require('mocha').it -describe('pool', function() { +var Pool = require('../') - describe('with callbacks', function() { - it('works totally unconfigured', function(done) { +describe('pool', function () { + describe('with callbacks', function () { + it('works totally unconfigured', function (done) { const pool = new Pool() - pool.connect(function(err, client, release) { + pool.connect(function (err, client, release) { if (err) return done(err) - client.query('SELECT NOW()', function(err, res) { + client.query('SELECT NOW()', function (err, res) { release() if (err) return done(err) expect(res.rows).to.have.length(1) @@ -22,37 +23,39 @@ describe('pool', function() { }) }) - it('passes props to clients', function(done) { + it('passes props to clients', function (done) { const pool = new Pool({ binary: true }) - pool.connect(function(err, client, release) { + pool.connect(function (err, client, release) { release() + if (err) return done(err) expect(client.binary).to.eql(true) pool.end(done) }) }) - it('removes client if it errors in background', function(done) { + it('removes client if it errors in background', function (done) { const pool = new Pool() - pool.connect(function(err, client, release) { + pool.connect(function (err, client, release) { release() + if (err) return done(err) client.testString = 'foo' - setTimeout(function() { + setTimeout(function () { client.emit('error', new Error('on purpose')) }, 10) }) - pool.on('error', function(err) { + 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() { + err.client.connection.stream.on('end', function () { pool.end(done) }) }) }) }) - describe('with promises', function() { - it('connects and disconnects', co.wrap(function*() { + describe('with promises', function () { + it('connects and disconnects', co.wrap(function * () { var pool = new Pool() var client = yield pool.connect() expect(pool.pool.availableObjectsCount()).to.be(0) @@ -64,13 +67,13 @@ describe('pool', function() { return yield pool.end() })) - it('properly pools clients', co.wrap(function*() { + it('properly pools clients', co.wrap(function * () { var pool = new Pool({ poolSize: 9 }) var count = 0 while (count < 30) { count++ - pool.connect().then(function(client) { - client.queryAsync('select $1::text as name', ['hi']).then(function(res) { + pool.connect().then(function (client) { + client.queryAsync('select $1::text as name', ['hi']).then(function (res) { client.release() }) }) @@ -80,28 +83,25 @@ describe('pool', function() { return yield pool.end() })) - it('supports just running queries', co.wrap(function*() { + it('supports just running queries', co.wrap(function * () { var pool = new Pool({ poolSize: 9 }) - var count = 0 - var queries = _.times(30).map(function() { + var queries = _.times(30).map(function () { return pool.query('SELECT $1::text as name', ['hi']) }) - console.log('executing') yield queries expect(pool.pool.getPoolSize()).to.be(9) expect(pool.pool.availableObjectsCount()).to.be(9) return yield pool.end() })) - it('recovers from all errors', co.wrap(function*() { + it('recovers from all errors', co.wrap(function * () { var pool = new Pool({ poolSize: 9 }) var count = 0 - while(count++ < 30) { + while (count++ < 30) { try { yield pool.query('SELECT lksjdfd') - } catch(e) { - } + } catch (e) {} } var res = yield pool.query('SELECT $1::text as name', ['hi']) expect(res.rows).to.eql([{ name: 'hi' }]) From 2aa207eea64d4bf9840dcdc9e6145c3585514dc2 Mon Sep 17 00:00:00 2001 From: brianc Date: Fri, 10 Jun 2016 16:58:23 -0500 Subject: [PATCH 0082/1037] Update test semantics --- test/index.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/test/index.js b/test/index.js index bc547cc81..a26f46568 100644 --- a/test/index.js +++ b/test/index.js @@ -70,15 +70,11 @@ describe('pool', function () { it('properly pools clients', co.wrap(function * () { var pool = new Pool({ poolSize: 9 }) var count = 0 - while (count < 30) { - count++ - pool.connect().then(function (client) { - client.queryAsync('select $1::text as name', ['hi']).then(function (res) { - client.release() - }) - }) - } - yield Promise.delay(100) + yield _.times(30).map(function * () { + var client = yield pool.connect() + var result = yield client.queryAsync('select $1::text as name', ['hi']) + client.release() + }) expect(pool.pool.getPoolSize()).to.be(9) return yield pool.end() })) From 1decf9693afe3ceb205a5dc4a2e9919d12030c80 Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 10 Jun 2016 17:16:14 -0500 Subject: [PATCH 0083/1037] Create README.md --- README.md | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 000000000..a6ef5ca10 --- /dev/null +++ b/README.md @@ -0,0 +1,100 @@ +# node-pg-pool +A connection pool for node-postgres + +## install +```sh +npm i pg-pool pg +``` + +## use + +to use pg-pool you must first create an instance of a pool + +```js +//by default the pool uses the same +//configuration as whatever `pg` version you have installed +const 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 +const 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 +}) + +//you can supply a custom client constructor +//if you want to use the native postgres client +const NativeClient = require('pg').native.Client +const nativePool = new Pool({ Client: NativeClient }) + +//you can even pool pg-native clients directly +const PgNativeClient = require('pg-native') +const pgNativePool = new Pool({ Client: PgNativeClient }) +``` + +pg-pool supports a fully promise-based api for acquiring clients + +```js +const 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) + }) +}) +``` + +pg-pool supports the traditional callback api for acquiring a client that node-postgres has shipped with internally for years: + +```js +const 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) + }) +}) +``` + +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 +const pool = new Pool() +const client = await pool.connect() +console.log(await client.query('select now()')) +client.release() +await pool.end() +``` + +## tests + +To run tests clone the repo, `npm i` in the working dir, and then run `npm test` + +## 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. From da6a2b0b0cce3b644755c1112943671472fc26a1 Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 10 Jun 2016 17:17:35 -0500 Subject: [PATCH 0084/1037] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a6ef5ca10..e0e9a9bd8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# node-pg-pool +# pg-pool A connection pool for node-postgres ## install From 5c88bd696513169aa640f33c061f2d3d84d01ec5 Mon Sep 17 00:00:00 2001 From: brianc Date: Fri, 10 Jun 2016 17:40:42 -0500 Subject: [PATCH 0085/1037] Update readme --- README.md | 36 ++++++++++++++++++++++++++++++++++-- index.js | 2 ++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e0e9a9bd8..84fdae74b 100644 --- a/README.md +++ b/README.md @@ -56,13 +56,39 @@ pool.connect().then(client => { }) ``` -pg-pool supports the traditional callback api for acquiring a client that node-postgres has shipped with internally for years: +this ends up looking much nicer if you're using [co](https://github.com/tj/co) or async/await: + +```js +const pool = new Pool() +const client = await pool.connect() +try { + const result = await client.query('select $1::text as name', ['brianc']) + console.log('hello from', result.rows[0]) +} finally { + client.release() +} +``` + +because its so common to just run a query and return the client to the pool afterward pg-pool has this built-in: + +```js +const pool = new Pool() +const time = await pool.query('SELECT NOW()') +const name = await pool.query('select $1::text as name', ['brianc']) +console.log(name.rows[0].name, 'says hello at', time.rows[0].name) +``` +__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. + +pg-pool still and will always support the traditional callback api for acquiring a client that node-postgres has shipped with internally for years: ```js const 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) { @@ -73,6 +99,8 @@ pool.connect((err, client, done) => { }) ``` +That means you can drop pg-pool into your app and 99% of the cases you wont even notice a difference. In fact, very soon I will be using pg-pool internally within node-postgres itself! + 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: @@ -88,6 +116,10 @@ await pool.end() 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. Don't forget to follow me on twitter at [@briancarlson](https://twitter.com/briancarlson) - I generally announce any noteworthy updates there. + ## license The MIT License (MIT) diff --git a/index.js b/index.js index a21e2c0dc..1586947ab 100644 --- a/index.js +++ b/index.js @@ -42,6 +42,8 @@ Pool.prototype._create = function (cb) { cb(err) } + var query = client.query; + client.queryAsync = function (text, values) { return new this.Promise((resolve, reject) => { client.query(text, values, function (err, res) { From d73538550cba65f681ca73690ef97d1b1acd6865 Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 10 Jun 2016 17:44:48 -0500 Subject: [PATCH 0086/1037] Update README.md --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 84fdae74b..18a4b524c 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ npm i pg-pool pg ## use +### create + to use pg-pool you must first create an instance of a pool ```js @@ -40,6 +42,8 @@ const PgNativeClient = require('pg-native') const pgNativePool = new Pool({ Client: PgNativeClient }) ``` +### acquire clients with a promise + pg-pool supports a fully promise-based api for acquiring clients ```js @@ -56,6 +60,8 @@ pool.connect().then(client => { }) ``` +### 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 @@ -69,6 +75,8 @@ try { } ``` +### 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 @@ -82,7 +90,9 @@ have some other edge case like [streaming rows](https://github.com/brianc/node-p 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. -pg-pool still and will always support the traditional callback api for acquiring a client that node-postgres has shipped with internally for years: +### 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 internally for years: ```js const pool = new Pool() @@ -101,6 +111,8 @@ pool.connect((err, client, done) => { That means you can drop pg-pool into your app and 99% of the cases you wont even notice a difference. In fact, very soon I will be using pg-pool internally within node-postgres itself! +### 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: From d42770ae2ca4229d3ac5da0fbb2a5a9709a51537 Mon Sep 17 00:00:00 2001 From: John Fawcett Date: Fri, 10 Jun 2016 21:25:56 -0500 Subject: [PATCH 0087/1037] Demonstrate that pg-pool exports Pool constructor --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 18a4b524c..edcb79d3b 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ npm i pg-pool pg to use pg-pool you must first create an instance of a pool ```js +const Pool = require('pg-pool') + //by default the pool uses the same //configuration as whatever `pg` version you have installed const pool = new Pool() From cb21c2a2e7d6a3bd6d3244c7d09ab97f43ac4728 Mon Sep 17 00:00:00 2001 From: brianc Date: Fri, 10 Jun 2016 22:52:07 -0500 Subject: [PATCH 0088/1037] Better compatibility with pg --- index.js | 28 ++++++++-------------------- package.json | 2 +- test/index.js | 6 ++---- 3 files changed, 11 insertions(+), 25 deletions(-) diff --git a/index.js b/index.js index 1586947ab..b477e2253 100644 --- a/index.js +++ b/index.js @@ -41,17 +41,6 @@ Pool.prototype._create = function (cb) { this.log('client connection error:', err) cb(err) } - - var query = client.query; - - client.queryAsync = function (text, values) { - return new this.Promise((resolve, reject) => { - client.query(text, values, function (err, res) { - err ? reject(err) : resolve(res) - }) - }) - }.bind(this) - cb(err, err ? null : client) }.bind(this)) } @@ -92,16 +81,15 @@ Pool.prototype.connect = function (cb) { Pool.prototype.take = Pool.prototype.connect Pool.prototype.query = function (text, values) { - return this.take().then(function (client) { - return client.queryAsync(text, values) - .then(function (res) { - client.release() - return res - }).catch(function (error) { - client.release(error) - throw error + return new this.Promise(function (resolve, reject) { + this.connect(function (err, client, done) { + if (err) return reject(err) + client.query(text, values, function (err, res) { + done(err) + err ? reject(err) : resolve(res) }) - }) + }) + }.bind(this)) } Pool.prototype.end = function (cb) { diff --git a/package.json b/package.json index 1c5f6ed48..fd31c79b0 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "expect.js": "0.3.1", "lodash": "4.13.1", "mocha": "^2.3.3", - "pg": "4.5.6", + "pg": "5.1.0", "standard": "7.1.2", "standard-format": "2.2.1" }, diff --git a/test/index.js b/test/index.js index a26f46568..364d62f28 100644 --- a/test/index.js +++ b/test/index.js @@ -1,6 +1,5 @@ var expect = require('expect.js') var co = require('co') -var Promise = require('bluebird') var _ = require('lodash') var describe = require('mocha').describe @@ -59,7 +58,7 @@ describe('pool', function () { var pool = new Pool() var client = yield pool.connect() expect(pool.pool.availableObjectsCount()).to.be(0) - var res = yield client.queryAsync('select $1::text as name', ['hi']) + var res = yield client.query('select $1::text as name', ['hi']) expect(res.rows).to.eql([{ name: 'hi' }]) client.release() expect(pool.pool.getPoolSize()).to.be(1) @@ -69,10 +68,9 @@ describe('pool', function () { it('properly pools clients', co.wrap(function * () { var pool = new Pool({ poolSize: 9 }) - var count = 0 yield _.times(30).map(function * () { var client = yield pool.connect() - var result = yield client.queryAsync('select $1::text as name', ['hi']) + yield client.query('select $1::text as name', ['hi']) client.release() }) expect(pool.pool.getPoolSize()).to.be(9) From e38cfe078c8db3208a323fed279b002aaee2b6df Mon Sep 17 00:00:00 2001 From: brianc Date: Fri, 10 Jun 2016 22:52:21 -0500 Subject: [PATCH 0089/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fd31c79b0..0f12e96f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.0.0", + "version": "1.0.1", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From a6f641eb2cf45638a3152b7d84b9f99325aa7df2 Mon Sep 17 00:00:00 2001 From: Lee Symes Date: Tue, 21 Jun 2016 12:56:12 +1200 Subject: [PATCH 0090/1037] Only release client once on an error. (#3) Prevent `generic-pool` error when releasing a client with an error. Fixes #2 --- index.js | 9 +++++---- test/index.js | 13 ++++++++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index b477e2253..67cfc19f5 100644 --- a/index.js +++ b/index.js @@ -60,13 +60,14 @@ Pool.prototype.connect = function (cb) { this.log('acquire client') client.release = function (err) { + delete client.release if (err) { - this.log('release client. error:', err) + this.log('destroy client. error:', err) this.pool.destroy(client) + } else { + this.log('release client') + this.pool.release(client) } - this.log('release client') - delete client.release - this.pool.release(client) }.bind(this) if (cb) { diff --git a/test/index.js b/test/index.js index 364d62f28..e03c5f231 100644 --- a/test/index.js +++ b/test/index.js @@ -89,7 +89,18 @@ describe('pool', function () { })) it('recovers from all errors', co.wrap(function * () { - var pool = new Pool({ poolSize: 9 }) + var pool = new Pool({ + poolSize: 9, + log: function (str, level) { + // Custom logging function to ensure we are not causing errors or warnings + // inside the `generic-pool` library. + if (level === 'error' || level === 'warn') { + expect().fail('An error or warning was logged from the generic pool library.\n' + + 'Level: ' + level + '\n' + + 'Message: ' + str + '\n') + } + } + }) var count = 0 while (count++ < 30) { From d09cf3b9c33d00b1f059c974ac127f0a4fd051cb Mon Sep 17 00:00:00 2001 From: brianc Date: Mon, 20 Jun 2016 19:57:44 -0500 Subject: [PATCH 0091/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0f12e96f7..a3d554c47 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.0.1", + "version": "1.0.2", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From ef8530aeb7d4e0ee155d3652c11cc1e2e4d74657 Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 21 Jun 2016 22:38:31 -0500 Subject: [PATCH 0092/1037] Update README.md --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index edcb79d3b..9ad5e20d4 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,20 @@ client.release() await pool.end() ``` +### 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 expor 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. + ## tests To run tests clone the repo, `npm i` in the working dir, and then run `npm test` From d21ed42fc6f634704e2edc21410840cca52dfd07 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 22 Jun 2016 10:03:14 -0500 Subject: [PATCH 0093/1037] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ad5e20d4..61a26180c 100644 --- a/README.md +++ b/README.md @@ -138,7 +138,7 @@ PGPORT=5432 PGSSLMODE=require ``` -Usually I will export these into my local environment via a `.env` file with environment settings or expor 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. +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. ## tests From cc20f8b747ecb85b19496750494e58eb495d4ceb Mon Sep 17 00:00:00 2001 From: ikokostya Date: Thu, 23 Jun 2016 00:34:17 +0300 Subject: [PATCH 0094/1037] Clone options in Pool constructor (fixes #4) (#5) --- index.js | 3 ++- package.json | 3 ++- test/index.js | 11 +++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 67cfc19f5..6e5fdbbd4 100644 --- a/index.js +++ b/index.js @@ -2,10 +2,11 @@ var genericPool = require('generic-pool') var util = require('util') var EventEmitter = require('events').EventEmitter var debug = require('debug') +var objectAssign = require('object-assign') var Pool = module.exports = function (options, Client) { EventEmitter.call(this) - this.options = options || {} + this.options = objectAssign({}, options) this.log = this.options.log || debug('pg:pool') this.Client = this.options.Client || Client || require('pg').Client this.Promise = this.options.Promise || Promise diff --git a/package.json b/package.json index a3d554c47..7ddc16eac 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ }, "dependencies": { "debug": "^2.2.0", - "generic-pool": "2.4.2" + "generic-pool": "2.4.2", + "object-assign": "4.1.0" } } diff --git a/test/index.js b/test/index.js index e03c5f231..956f15ccd 100644 --- a/test/index.js +++ b/test/index.js @@ -51,6 +51,17 @@ describe('pool', function () { }) }) }) + + it('should not change given options', function (done) { + var options = { max: 10 } + var 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) + }) + }) }) describe('with promises', function () { From 276b50d69f24651270a6103c3c5e33242cc8a451 Mon Sep 17 00:00:00 2001 From: brianc Date: Wed, 22 Jun 2016 17:17:11 -0500 Subject: [PATCH 0095/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7ddc16eac..34ece77cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.0.2", + "version": "1.0.3", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From 7ef08fd8611641057c1a6115a8ffac712d133b4b Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 22 Jun 2016 23:29:09 -0500 Subject: [PATCH 0096/1037] Remove dependency on debug (#6) Accept a `log: (message, other...) => { }` parameter as a config option, but by default use a no-op function instead of debug. --- index.js | 3 +-- package.json | 1 - test/logging.js | 20 ++++++++++++++++++++ 3 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 test/logging.js diff --git a/index.js b/index.js index 6e5fdbbd4..687e410fc 100644 --- a/index.js +++ b/index.js @@ -1,13 +1,12 @@ var genericPool = require('generic-pool') var util = require('util') var EventEmitter = require('events').EventEmitter -var debug = require('debug') var objectAssign = require('object-assign') var Pool = module.exports = function (options, Client) { EventEmitter.call(this) this.options = objectAssign({}, options) - this.log = this.options.log || debug('pg:pool') + this.log = this.options.log || function () { } this.Client = this.options.Client || Client || require('pg').Client this.Promise = this.options.Promise || Promise diff --git a/package.json b/package.json index 34ece77cb..d298b8134 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "standard-format": "2.2.1" }, "dependencies": { - "debug": "^2.2.0", "generic-pool": "2.4.2", "object-assign": "4.1.0" } diff --git a/test/logging.js b/test/logging.js new file mode 100644 index 000000000..e03fa5195 --- /dev/null +++ b/test/logging.js @@ -0,0 +1,20 @@ +var expect = require('expect.js') +var co = require('co') + +var describe = require('mocha').describe +var it = require('mocha').it + +var Pool = require('../') + +describe('logging', function () { + it('logs to supplied log function if given', co.wrap(function * () { + var messages = [] + var log = function (msg) { + messages.push(msg) + } + var pool = new Pool({ log: log }) + yield pool.query('SELECT NOW()') + expect(messages.length).to.be.greaterThan(0) + return pool.end() + })) +}) From 63caf7cd4c2255537b063274a1142b9a52148a4b Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 22 Jun 2016 23:29:35 -0500 Subject: [PATCH 0097/1037] Add 'connect' event to pool (#7) * Have pool emit 'connect' callback with client * Ensure pool emits client on connect event --- index.js | 2 ++ test/events.js | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 test/events.js diff --git a/index.js b/index.js index 687e410fc..ee09dc81d 100644 --- a/index.js +++ b/index.js @@ -14,6 +14,7 @@ var Pool = module.exports = function (options, Client) { this.options.create = this.options.create || this._create.bind(this) this.options.destroy = this.options.destroy || this._destroy.bind(this) this.pool = new genericPool.Pool(this.options) + this.onCreate = this.options.onCreate } util.inherits(Pool, EventEmitter) @@ -37,6 +38,7 @@ Pool.prototype._create = function (cb) { client.connect(function (err) { this.log('client connected') + this.emit('connect', client) if (err) { this.log('client connection error:', err) cb(err) diff --git a/test/events.js b/test/events.js new file mode 100644 index 000000000..3b7225b75 --- /dev/null +++ b/test/events.js @@ -0,0 +1,24 @@ +var expect = require('expect.js') + +var describe = require('mocha').describe +var it = require('mocha').it + +var Pool = require('../') + +describe('events', function () { + it('emits connect before callback', function (done) { + var pool = new Pool() + var 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() + }) + }) +}) From d2775fc02354c1ca31e91fe1342e7f1a820599d2 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 22 Jun 2016 23:55:17 -0500 Subject: [PATCH 0098/1037] Add travis.yml file (#9) * Add travis.yml file * Remove test on pg@9.5 since travis does not support it --- .travis.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..12f9f47a6 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,13 @@ +language: node_js + +matrix: + include: + - node_js: "4" + addons: + postgresql: "9.1" + - node_js: "5" + addons: + postgresql: "9.4" + - node_js: "6" + addons: + postgresql: "9.4" From 8c058a300a2b46c0214f2a27d15b20a8bf0b360f Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 23 Jun 2016 00:09:50 -0500 Subject: [PATCH 0099/1037] Update README.md --- README.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/README.md b/README.md index 61a26180c..9a18e91f6 100644 --- a/README.md +++ b/README.md @@ -126,6 +126,54 @@ client.release() await pool.end() ``` +### 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 +var pg = require('pg') +var pool = new pg.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 +var pg = require('pg') +var pool = new pg.Pool() + +var count = 0 + +pool.on('connect', client => { + client.count = count++ +}) + +pool.connect() + .then(client => { + client.query('SELECT $1::int AS "clientCount', [client.count]) + .then(res => console.log(res.rows[0].clientCount)) // outputs 0 + })) + +`` + +This allows you to do custom bootstrapping and manipulation of clients after they have been successfully connected to the PostgreSQL backend, but before any queries have been issued. + ### environment variables pg-pool & node-postgres support some of the same environment variables as `psql` supports. The most common are: From c95036c362f75f7bf0ef0c75e45b8c37eb7bab31 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 23 Jun 2016 00:21:01 -0500 Subject: [PATCH 0100/1037] Update README.md Add travis badge --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9a18e91f6..1b6c8a0cf 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ # 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 From 955d6ba79747d954f203879885a133d80a3e8cda Mon Sep 17 00:00:00 2001 From: brianc Date: Thu, 23 Jun 2016 00:21:16 -0500 Subject: [PATCH 0101/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d298b8134..9e74dc503 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.0.3", + "version": "1.1.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From cc40403de9760b92c599fefc27ff079c03598f6f Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 23 Jun 2016 00:22:07 -0500 Subject: [PATCH 0102/1037] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1b6c8a0cf..895140dc0 100644 --- a/README.md +++ b/README.md @@ -172,7 +172,7 @@ pool.connect() .then(res => console.log(res.rows[0].clientCount)) // outputs 0 })) -`` +``` This allows you to do custom bootstrapping and manipulation of clients after they have been successfully connected to the PostgreSQL backend, but before any queries have been issued. From 4758ea660e44f34259a9828a4fd6bbd958cdac17 Mon Sep 17 00:00:00 2001 From: brianc Date: Thu, 23 Jun 2016 14:34:41 -0500 Subject: [PATCH 0103/1037] Update documentation --- README.md | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 895140dc0..dbb5b1f79 100644 --- a/README.md +++ b/README.md @@ -69,14 +69,28 @@ pool.connect().then(client => { this ends up looking much nicer if you're using [co](https://github.com/tj/co) or async/await: ```js -const pool = new Pool() -const client = await pool.connect() -try { - const result = await client.query('select $1::text as name', ['brianc']) - console.log('hello from', result.rows[0]) -} finally { - client.release() -} +// with async/await +(async () => { + const pool = new Pool() + const client = await pool.connect() + try { + const 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 * () { + const client = yield pool.connect() + try { + const 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 @@ -89,6 +103,7 @@ const time = await pool.query('SELECT NOW()') const name = await pool.query('select $1::text as name', ['brianc']) console.log(name.rows[0].name, 'says hello at', time.rows[0].name) ``` + __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 @@ -96,7 +111,7 @@ 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 internally for years: +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 const pool = new Pool() @@ -113,8 +128,6 @@ pool.connect((err, client, done) => { }) ``` -That means you can drop pg-pool into your app and 99% of the cases you wont even notice a difference. In fact, very soon I will be using pg-pool internally within node-postgres itself! - ### 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 @@ -142,7 +155,7 @@ Example: var pg = require('pg') var pool = new pg.Pool() -// attach an error handler to the pool for when a connected, idle client +// 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') @@ -166,11 +179,15 @@ pool.on('connect', client => { client.count = count++ }) -pool.connect() +pool + .connect() .then(client => { - client.query('SELECT $1::int AS "clientCount', [client.count]) + 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()) ``` @@ -196,7 +213,7 @@ 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. Don't forget to follow me on twitter at [@briancarlson](https://twitter.com/briancarlson) - I generally announce any noteworthy updates there. +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 From 8b45ea1e7d9d73f971245ebb063c684bf36f9486 Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 24 Jun 2016 10:48:23 -0500 Subject: [PATCH 0104/1037] Update README.md Add a section with instructions on where to instantiate your pool --- README.md | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/README.md b/README.md index dbb5b1f79..51381c856 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,34 @@ 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: + +``` +// 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 +const 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 + const aPool = new pg.Pool() + return aPool.connect() +} +``` + ### events Every instance of a `Pool` is an event emitter. These instances emit the following events: From ce59164ba1bc4932594be7f4cae5ab52d4576f2d Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 24 Jun 2016 11:35:16 -0500 Subject: [PATCH 0105/1037] Add callback interface to pool#query (#11) * Add callback interface to pool#query * Fix linting errors --- index.js | 5 ++++- test/index.js | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index ee09dc81d..042d697b5 100644 --- a/index.js +++ b/index.js @@ -83,13 +83,16 @@ Pool.prototype.connect = function (cb) { Pool.prototype.take = Pool.prototype.connect -Pool.prototype.query = function (text, values) { +Pool.prototype.query = function (text, values, cb) { return new this.Promise(function (resolve, reject) { this.connect(function (err, client, done) { if (err) return reject(err) client.query(text, values, function (err, res) { done(err) err ? reject(err) : resolve(res) + if (cb) { + cb(err, res) + } }) }) }.bind(this)) diff --git a/test/index.js b/test/index.js index 956f15ccd..a7772b61d 100644 --- a/test/index.js +++ b/test/index.js @@ -32,6 +32,16 @@ describe('pool', function () { }) }) + 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('removes client if it errors in background', function (done) { const pool = new Pool() pool.connect(function (err, client, release) { From f47bc5f23b5b4d68f0c2d7eaa2904998615c38d3 Mon Sep 17 00:00:00 2001 From: brianc Date: Fri, 24 Jun 2016 11:35:11 -0500 Subject: [PATCH 0106/1037] Update documentation --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 51381c856..4b494efcf 100644 --- a/README.md +++ b/README.md @@ -104,6 +104,15 @@ const 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 +const 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 From 2d446d49533b1f31cadf76210b3d56c72f83a10f Mon Sep 17 00:00:00 2001 From: brianc Date: Fri, 24 Jun 2016 11:36:36 -0500 Subject: [PATCH 0107/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9e74dc503..afc1cd6d0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.1.0", + "version": "1.2.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From aa1f10b0c04bbd3e04851c3ea8501414e634bdc1 Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 24 Jun 2016 11:52:32 -0500 Subject: [PATCH 0108/1037] Add support for pool#query without params (#12) --- index.js | 4 ++++ test/index.js | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/index.js b/index.js index 042d697b5..9f4bbf2bd 100644 --- a/index.js +++ b/index.js @@ -84,6 +84,10 @@ Pool.prototype.connect = function (cb) { Pool.prototype.take = Pool.prototype.connect Pool.prototype.query = function (text, values, cb) { + if (typeof values === 'function') { + cb = values + values = undefined + } return new this.Promise(function (resolve, reject) { this.connect(function (err, client, done) { if (err) return reject(err) diff --git a/test/index.js b/test/index.js index a7772b61d..ce4f5ef84 100644 --- a/test/index.js +++ b/test/index.js @@ -32,6 +32,16 @@ describe('pool', function () { }) }) + 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) { From baa5800a70381c9eb3b75accb426b0b02414ae42 Mon Sep 17 00:00:00 2001 From: brianc Date: Fri, 24 Jun 2016 09:53:46 -0700 Subject: [PATCH 0109/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index afc1cd6d0..ed226ad9d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.2.0", + "version": "1.2.1", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From d316ef55243c472e37a3084bb99657ac2774a274 Mon Sep 17 00:00:00 2001 From: Peter W Date: Sun, 26 Jun 2016 04:21:40 +1000 Subject: [PATCH 0110/1037] Fix example code for connect event (#14) --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4b494efcf..a6482659a 100644 --- a/README.md +++ b/README.md @@ -207,8 +207,8 @@ Fired whenever the pool creates a __new__ `pg.Client` instance and successfully Example: ```js -var pg = require('pg') -var pool = new pg.Pool() +const Pool = require('pg-pool') +const pool = new Pool() var count = 0 @@ -220,10 +220,10 @@ pool .connect() .then(client => { return client - .query('SELECT $1::int AS "clientCount', [client.count]) + .query('SELECT $1::int AS "clientCount"', [client.count]) .then(res => console.log(res.rows[0].clientCount)) // outputs 0 .then(() => client) - })) + }) .then(client => client.release()) ``` From ce173f8c280d1d2aaf2f1a1f6fb356d3f667325f Mon Sep 17 00:00:00 2001 From: Peter W Date: Mon, 27 Jun 2016 14:39:36 +1000 Subject: [PATCH 0111/1037] Fix error event doc in README (#15) - making error event example code start by acquiring `pool` in the same way it is done in the example at the top for `create` --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a6482659a..7bf558f6a 100644 --- a/README.md +++ b/README.md @@ -189,8 +189,8 @@ Emitted whenever an idle client in the pool encounters an error. This is common Example: ```js -var pg = require('pg') -var pool = new pg.Pool() +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 From d653234a0c504941a3046f86632bfe42c3ad921a Mon Sep 17 00:00:00 2001 From: Brian C Date: Sun, 26 Jun 2016 22:00:16 -0700 Subject: [PATCH 0112/1037] Add acquire event (#16) * Add acquire event Add acquire event which fires every time a client is acquired from the pool. * Update README.md --- README.md | 67 +++++++++++++++++++++++++++++++++----------------- index.js | 1 + test/events.js | 21 ++++++++++++++++ 3 files changed, 66 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 7bf558f6a..4a4fa02e4 100644 --- a/README.md +++ b/README.md @@ -15,17 +15,17 @@ npm i pg-pool pg to use pg-pool you must first create an instance of a pool ```js -const Pool = require('pg-pool') +var Pool = require('pg-pool') //by default the pool uses the same //configuration as whatever `pg` version you have installed -const pool = new Pool() +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 -const pool2 = new Pool({ +var pool2 = new Pool({ database: 'postgres', user: 'brianc', password: 'secret!', @@ -38,12 +38,12 @@ const pool2 = new Pool({ //you can supply a custom client constructor //if you want to use the native postgres client -const NativeClient = require('pg').native.Client -const nativePool = new Pool({ Client: NativeClient }) +var NativeClient = require('pg').native.Client +var nativePool = new Pool({ Client: NativeClient }) //you can even pool pg-native clients directly -const PgNativeClient = require('pg-native') -const pgNativePool = new Pool({ Client: PgNativeClient }) +var PgNativeClient = require('pg-native') +var pgNativePool = new Pool({ Client: PgNativeClient }) ``` ### acquire clients with a promise @@ -51,7 +51,7 @@ const pgNativePool = new Pool({ Client: PgNativeClient }) pg-pool supports a fully promise-based api for acquiring clients ```js -const pool = new Pool() +var pool = new Pool() pool.connect().then(client => { client.query('select $1::text as name', ['pg-pool']).then(res => { client.release() @@ -71,10 +71,10 @@ this ends up looking much nicer if you're using [co](https://github.com/tj/co) o ```js // with async/await (async () => { - const pool = new Pool() - const client = await pool.connect() + var pool = new Pool() + var client = await pool.connect() try { - const result = await client.query('select $1::text as name', ['brianc']) + var result = await client.query('select $1::text as name', ['brianc']) console.log('hello from', result.rows[0]) } finally { client.release() @@ -83,9 +83,9 @@ this ends up looking much nicer if you're using [co](https://github.com/tj/co) o // with co co(function * () { - const client = yield pool.connect() + var client = yield pool.connect() try { - const result = yield client.query('select $1::text as name', ['brianc']) + var result = yield client.query('select $1::text as name', ['brianc']) console.log('hello from', result.rows[0]) } finally { client.release() @@ -98,16 +98,16 @@ co(function * () { because its so common to just run a query and return the client to the pool afterward pg-pool has this built-in: ```js -const pool = new Pool() -const time = await pool.query('SELECT NOW()') -const name = await pool.query('select $1::text as name', ['brianc']) +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 -const pool = new Pool() +var pool = new Pool() pool.query('SELECT $1::text as name', ['brianc'], function (err, res) { console.log(res.rows[0].name) // brianc }) @@ -123,7 +123,7 @@ clients back to the pool after the query is done. 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 -const pool = new Pool() +var pool = new Pool() pool.connect((err, client, done) => { if (err) return done(err) @@ -143,8 +143,8 @@ When you are finished with the pool if all the clients are idle the pool will cl will shutdown gracefully. If you don't want to wait for the timeout you can end the pool as follows: ```js -const pool = new Pool() -const client = await pool.connect() +var pool = new Pool() +var client = await pool.connect() console.log(await client.query('select now()')) client.release() await pool.end() @@ -159,7 +159,7 @@ The pool should be a __long-lived object__ in your application. Generally you'l // correct usage: create the pool and let it live // 'globally' here, controlling access to it through exported methods -const pool = new pg.Pool() +var pool = new pg.Pool() // this is the right way to export the query method module.exports.query = (text, values) => { @@ -173,7 +173,7 @@ module.exports.connect = () => { // 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 - const aPool = new pg.Pool() + var aPool = new pg.Pool() return aPool.connect() } ``` @@ -228,7 +228,28 @@ pool ``` -This allows you to do custom bootstrapping and manipulation of clients after they have been successfully connected to the PostgreSQL backend, but before any queries have been issued. +#### 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) { + console.log('acquired', (++acquireCount), 'clients') +}) + +for (var i = 0; i < 200; i++) { + pool.query('SELECT NOW()') +} + +``` ### environment variables diff --git a/index.js b/index.js index 9f4bbf2bd..1fe22a141 100644 --- a/index.js +++ b/index.js @@ -60,6 +60,7 @@ Pool.prototype.connect = function (cb) { } this.log('acquire client') + this.emit('acquire', client) client.release = function (err) { delete client.release diff --git a/test/events.js b/test/events.js index 3b7225b75..671d1218c 100644 --- a/test/events.js +++ b/test/events.js @@ -21,4 +21,25 @@ describe('events', function () { done() }) }) + + it('emits acquire every time a client is acquired', function (done) { + var pool = new Pool() + var acquireCount = 0 + pool.on('acquire', function (client) { + expect(client).to.be.ok() + acquireCount++ + }) + for (var i = 0; i < 10; i++) { + pool.connect(function (err, client, release) { + err ? done(err) : release() + release() + if (err) return done(err) + }) + pool.query('SELECT now()') + } + setTimeout(function () { + expect(acquireCount).to.be(20) + pool.end(done) + }, 40) + }) }) From d1c70ec9c1c8ec44a1ffccd99c5c57a9e96e3ef0 Mon Sep 17 00:00:00 2001 From: brianc Date: Sun, 26 Jun 2016 22:02:49 -0700 Subject: [PATCH 0113/1037] Update documentation --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4a4fa02e4..d904d76b1 100644 --- a/README.md +++ b/README.md @@ -242,13 +242,23 @@ var pool = new Pool() var acquireCount = 0 pool.on('acquire', function (client) { - console.log('acquired', (++acquireCount), 'clients') + 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 From 22a76ddd1dc910975914cd29e8c4efc8d7cbdeb1 Mon Sep 17 00:00:00 2001 From: brianc Date: Sun, 26 Jun 2016 22:05:46 -0700 Subject: [PATCH 0114/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ed226ad9d..eebf42ca8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.2.1", + "version": "1.3.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From 74b6891b20fa7e6abe2e47c9f87d732a817769f9 Mon Sep 17 00:00:00 2001 From: Rick Bergfalk Date: Tue, 28 Jun 2016 16:47:50 -0500 Subject: [PATCH 0115/1037] handle empty query --- index.js | 6 ++++++ package.json | 2 +- test/close.js | 2 +- test/error-handling.js | 2 +- test/index.js | 2 +- test/no-data-handling.js | 13 ++++++++++++- 6 files changed, 22 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 457d7f6c6..70a90f571 100644 --- a/index.js +++ b/index.js @@ -89,6 +89,12 @@ Cursor.prototype.handleReadyForQuery = function() { this.state = 'done' } +Cursor.prototype.handleEmptyQuery = function(con) { + if (con.sync) { + con.sync() + } +}; + Cursor.prototype.handleError = function(msg) { this.state = 'error' this._error = msg diff --git a/package.json b/package.json index 8c26d80ec..1096dee9b 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "author": "Brian M. Carlson", "license": "MIT", "devDependencies": { - "pg.js": "~3.4.4", + "pg": "~6.0.0", "mocha": "~1.17.1" }, "dependencies": {} diff --git a/test/close.js b/test/close.js index 5f4f5bd98..df61319e3 100644 --- a/test/close.js +++ b/test/close.js @@ -1,6 +1,6 @@ var assert = require('assert') var Cursor = require('../') -var pg = require('pg.js') +var pg = require('pg') var text = 'SELECT generate_series as num FROM generate_series(0, 50)' describe('close', function() { diff --git a/test/error-handling.js b/test/error-handling.js index 044c96242..fedee4b13 100644 --- a/test/error-handling.js +++ b/test/error-handling.js @@ -1,6 +1,6 @@ var assert = require('assert') var Cursor = require('../') -var pg = require('pg.js') +var pg = require('pg') var text = 'SELECT generate_series as num FROM generate_series(0, 4)' diff --git a/test/index.js b/test/index.js index 77b60cd2c..8f04ccc21 100644 --- a/test/index.js +++ b/test/index.js @@ -1,6 +1,6 @@ var assert = require('assert') var Cursor = require('../') -var pg = require('pg.js') +var pg = require('pg') var text = 'SELECT generate_series as num FROM generate_series(0, 5)' diff --git a/test/no-data-handling.js b/test/no-data-handling.js index 9bcbef837..969df2d4b 100644 --- a/test/no-data-handling.js +++ b/test/no-data-handling.js @@ -1,5 +1,5 @@ var assert = require('assert') -var pg = require('pg.js'); +var pg = require('pg'); var Cursor = require('../'); describe('queries with no data', function () { @@ -22,4 +22,15 @@ describe('queries with no data', function () { done() }) }); + + it('handles empty query', function (done) { + var cursor = new Cursor('-- this is a comment') + cursor = this.client.query(cursor) + cursor.read(100, function (err, rows) { + assert.ifError(err) + assert.equal(rows.length, 0) + done() + }) + }) + }); From 4f6208521b19aa271cd1a1c4a127649e11a38f03 Mon Sep 17 00:00:00 2001 From: brianc Date: Tue, 28 Jun 2016 17:44:02 -0700 Subject: [PATCH 0116/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1096dee9b..c6c4e0761 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "1.0.0", + "version": "1.0.1", "description": "", "main": "index.js", "directories": { From ef1b15e13aae78a8928d37f7aad89bd86e921189 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 30 Jun 2016 15:22:49 -0700 Subject: [PATCH 0117/1037] Update README.md Add note on "bring your own promise" --- README.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/README.md b/README.md index d904d76b1..1616d77a5 100644 --- a/README.md +++ b/README.md @@ -275,6 +275,27 @@ 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` From 9ab7aff029aa9c879e3e04197935074f032b6b1c Mon Sep 17 00:00:00 2001 From: Brian C Date: Sun, 3 Jul 2016 18:17:34 -0500 Subject: [PATCH 0118/1037] Update code to run on >=0.10.0 (#17) * Replace const with var * Update code to run on 0.10.x + * Lint --- .travis.yml | 6 +++ index.js | 1 + package.json | 3 +- test/index.js | 118 ++++++++++++++++++++++++++---------------------- test/logging.js | 12 ++--- 5 files changed, 79 insertions(+), 61 deletions(-) diff --git a/.travis.yml b/.travis.yml index 12f9f47a6..8a1126aa0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,12 @@ language: node_js matrix: include: + - node_js: "0.10" + addons: + postgresql: "9.1" + - node_js: "0.12" + addons: + postgresql: "9.1" - node_js: "4" addons: postgresql: "9.1" diff --git a/index.js b/index.js index 1fe22a141..f126306e1 100644 --- a/index.js +++ b/index.js @@ -89,6 +89,7 @@ Pool.prototype.query = function (text, values, cb) { cb = values values = undefined } + return new this.Promise(function (resolve, reject) { this.connect(function (err, client, done) { if (err) return reject(err) diff --git a/package.json b/package.json index eebf42ca8..b4daf484a 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,7 @@ }, "homepage": "https://github.com/brianc/node-pg-pool#readme", "devDependencies": { - "bluebird": "3.4.0", - "co": "4.6.0", + "bluebird": "3.4.1", "expect.js": "0.3.1", "lodash": "4.13.1", "mocha": "^2.3.3", diff --git a/test/index.js b/test/index.js index ce4f5ef84..a7103af6f 100644 --- a/test/index.js +++ b/test/index.js @@ -1,16 +1,20 @@ var expect = require('expect.js') -var co = require('co') var _ = require('lodash') var describe = require('mocha').describe var it = require('mocha').it +var Promise = require('bluebird') var Pool = require('../') +if (typeof global.Promise === 'undefined') { + global.Promise = Promise +} + describe('pool', function () { describe('with callbacks', function () { it('works totally unconfigured', function (done) { - const pool = new Pool() + var pool = new Pool() pool.connect(function (err, client, release) { if (err) return done(err) client.query('SELECT NOW()', function (err, res) { @@ -23,7 +27,7 @@ describe('pool', function () { }) it('passes props to clients', function (done) { - const pool = new Pool({ binary: true }) + var pool = new Pool({ binary: true }) pool.connect(function (err, client, release) { release() if (err) return done(err) @@ -33,7 +37,7 @@ describe('pool', function () { }) it('can run a query with a callback without parameters', function (done) { - const pool = new Pool() + var pool = new Pool() pool.query('SELECT 1 as num', function (err, res) { expect(res.rows[0]).to.eql({ num: 1 }) pool.end(function () { @@ -43,7 +47,7 @@ describe('pool', function () { }) it('can run a query with a callback', function (done) { - const pool = new Pool() + var 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 () { @@ -53,7 +57,7 @@ describe('pool', function () { }) it('removes client if it errors in background', function (done) { - const pool = new Pool() + var pool = new Pool() pool.connect(function (err, client, release) { release() if (err) return done(err) @@ -85,63 +89,71 @@ describe('pool', function () { }) describe('with promises', function () { - it('connects and disconnects', co.wrap(function * () { + it('connects and disconnects', function () { var pool = new Pool() - var client = yield pool.connect() - expect(pool.pool.availableObjectsCount()).to.be(0) - var res = yield client.query('select $1::text as name', ['hi']) - expect(res.rows).to.eql([{ name: 'hi' }]) - client.release() - expect(pool.pool.getPoolSize()).to.be(1) - expect(pool.pool.availableObjectsCount()).to.be(1) - return yield pool.end() - })) + return pool.connect().then(function (client) { + expect(pool.pool.availableObjectsCount()).to.be(0) + return client.query('select $1::text as name', ['hi']).then(function (res) { + expect(res.rows).to.eql([{ name: 'hi' }]) + client.release() + expect(pool.pool.getPoolSize()).to.be(1) + expect(pool.pool.availableObjectsCount()).to.be(1) + return pool.end() + }) + }) + }) - it('properly pools clients', co.wrap(function * () { + it('properly pools clients', function () { var pool = new Pool({ poolSize: 9 }) - yield _.times(30).map(function * () { - var client = yield pool.connect() - yield client.query('select $1::text as name', ['hi']) - client.release() + return Promise.map(_.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 + }) + }) + }).then(function (res) { + expect(res).to.have.length(30) + expect(pool.pool.getPoolSize()).to.be(9) + return pool.end() }) - expect(pool.pool.getPoolSize()).to.be(9) - return yield pool.end() - })) + }) - it('supports just running queries', co.wrap(function * () { + it('supports just running queries', function () { var pool = new Pool({ poolSize: 9 }) - var queries = _.times(30).map(function () { + return Promise.map(_.times(30), function () { return pool.query('SELECT $1::text as name', ['hi']) + }).then(function (queries) { + expect(queries).to.have.length(30) + expect(pool.pool.getPoolSize()).to.be(9) + expect(pool.pool.availableObjectsCount()).to.be(9) + return pool.end() }) - yield queries - expect(pool.pool.getPoolSize()).to.be(9) - expect(pool.pool.availableObjectsCount()).to.be(9) - return yield pool.end() - })) + }) + + it('recovers from all errors', function () { + var pool = new Pool() - it('recovers from all errors', co.wrap(function * () { - var pool = new Pool({ - poolSize: 9, - log: function (str, level) { - // Custom logging function to ensure we are not causing errors or warnings - // inside the `generic-pool` library. - if (level === 'error' || level === 'warn') { - expect().fail('An error or warning was logged from the generic pool library.\n' + - 'Level: ' + level + '\n' + - 'Message: ' + str + '\n') - } - } + var errors = [] + return Promise.mapSeries(_.times(30), function () { + return pool.query('SELECT asldkfjasldkf') + .catch(function (e) { + errors.push(e) + }) + }).then(function () { + return pool.query('SELECT $1::text as name', ['hi']).then(function (res) { + expect(errors).to.have.length(30) + expect(res.rows).to.eql([{ name: 'hi' }]) + return pool.end() + }) }) - var count = 0 + }) + }) +}) - while (count++ < 30) { - try { - yield pool.query('SELECT lksjdfd') - } catch (e) {} - } - var res = yield pool.query('SELECT $1::text as name', ['hi']) - expect(res.rows).to.eql([{ name: 'hi' }]) - return yield pool.end() - })) +process.on('unhandledRejection', function (e) { + console.error(e.message, e.stack) + setImmediate(function () { + throw e }) }) diff --git a/test/logging.js b/test/logging.js index e03fa5195..47389a5aa 100644 --- a/test/logging.js +++ b/test/logging.js @@ -1,5 +1,4 @@ var expect = require('expect.js') -var co = require('co') var describe = require('mocha').describe var it = require('mocha').it @@ -7,14 +6,15 @@ var it = require('mocha').it var Pool = require('../') describe('logging', function () { - it('logs to supplied log function if given', co.wrap(function * () { + it('logs to supplied log function if given', function () { var messages = [] var log = function (msg) { messages.push(msg) } var pool = new Pool({ log: log }) - yield pool.query('SELECT NOW()') - expect(messages.length).to.be.greaterThan(0) - return pool.end() - })) + return pool.query('SELECT NOW()').then(function () { + expect(messages.length).to.be.greaterThan(0) + return pool.end() + }) + }) }) From 8c42c4172bc6ea4de78c540b19e219d37a30b984 Mon Sep 17 00:00:00 2001 From: brianc Date: Sun, 3 Jul 2016 16:17:55 -0700 Subject: [PATCH 0119/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b4daf484a..d7772d046 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.3.0", + "version": "1.3.1", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From e2d77719e7c63521b52b46397c000ec4ffa933df Mon Sep 17 00:00:00 2001 From: Timothy Haley Date: Mon, 18 Jul 2016 16:54:57 -0400 Subject: [PATCH 0120/1037] Url parsing example (#19) * Added URL parsing example * Typos and cleanup * Last typo --- README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/README.md b/README.md index 1616d77a5..f0dfe2b7a 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,40 @@ 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 = 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 From 1d89029ba7f4eb45bb82c2e4263def6ce3c5728c Mon Sep 17 00:00:00 2001 From: Risto Novik Date: Tue, 26 Jul 2016 18:18:14 +0300 Subject: [PATCH 0121/1037] Added missing new keyword to Heroku example. (#21) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f0dfe2b7a..39711ab3c 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ const config = { ssl: true }; -const pool = Pool(config); +const pool = new Pool(config); /* Transforms, 'progres://DBuser:secret@DBHost:#####/myDB', into From 51fb7db8fad8bc83f95121d06af72752513aea61 Mon Sep 17 00:00:00 2001 From: Cody Greene Date: Fri, 5 Aug 2016 14:21:51 -0700 Subject: [PATCH 0122/1037] Support function-like construction (plus test) (#23) * Support function-like construction Remove the necessity of using `new` in front of the `Pool`, i.e. allow it to be used as a regular function. This is following https://github.com/brianc/node-postgres/issues/1077 * add Pool factory test --- index.js | 3 +++ test/index.js | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/index.js b/index.js index f126306e1..6f622bac0 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,9 @@ var EventEmitter = require('events').EventEmitter var objectAssign = require('object-assign') var Pool = module.exports = function (options, Client) { + if (!(this instanceof Pool)) { + return new Pool(options, Client) + } EventEmitter.call(this) this.options = objectAssign({}, options) this.log = this.options.log || function () { } diff --git a/test/index.js b/test/index.js index a7103af6f..e4616a436 100644 --- a/test/index.js +++ b/test/index.js @@ -12,6 +12,12 @@ if (typeof global.Promise === 'undefined') { } describe('pool', function () { + it('can be used as a factory function', function () { + var pool = Pool() + expect(pool instanceof Pool).to.be.ok() + expect(typeof pool.connect).to.be('function') + }) + describe('with callbacks', function () { it('works totally unconfigured', function (done) { var pool = new Pool() From eca2ea0ede3431b6f92ed09122638b7b792a8029 Mon Sep 17 00:00:00 2001 From: Cody Greene Date: Fri, 5 Aug 2016 14:22:50 -0700 Subject: [PATCH 0123/1037] emit "connect" event only on success and avoid double callback (#22) * fail: "connect" event only on success Double callback invocation will also cause this to fail. * avoid double callback: _create If `client.connect` returns an error, then the callback for `Pool#_create` is only invoked once. Also the `connect` event is only emitted on a successful connection, the client is otherwise rather useless. * legacy compat; don't use Object.assign * legacy compat; events.EventEmitter --- index.js | 7 ++++--- test/events.js | 30 ++++++++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 6f622bac0..80279db2d 100644 --- a/index.js +++ b/index.js @@ -40,13 +40,14 @@ Pool.prototype._create = function (cb) { }.bind(this)) client.connect(function (err) { - this.log('client connected') - this.emit('connect', client) if (err) { this.log('client connection error:', err) cb(err) + } else { + this.log('client connected') + this.emit('connect', client) + cb(null, client) } - cb(err, err ? null : client) }.bind(this)) } diff --git a/test/events.js b/test/events.js index 671d1218c..bcb523f03 100644 --- a/test/events.js +++ b/test/events.js @@ -1,8 +1,8 @@ var expect = require('expect.js') - +var EventEmitter = require('events').EventEmitter var describe = require('mocha').describe var it = require('mocha').it - +var objectAssign = require('object-assign') var Pool = require('../') describe('events', function () { @@ -22,6 +22,24 @@ describe('events', function () { }) }) + it('emits "connect" only with a successful connection', function (done) { + var pool = new Pool({ + // This client will always fail to connect + Client: mockClient({ + connect: function (cb) { + process.nextTick(function () { cb(new Error('bad news')) }) + } + }) + }) + pool.on('connect', function () { + throw new Error('should never get here') + }) + pool._create(function (err) { + if (err) done() + else done(new Error('expected failure')) + }) + }) + it('emits acquire every time a client is acquired', function (done) { var pool = new Pool() var acquireCount = 0 @@ -43,3 +61,11 @@ describe('events', function () { }, 40) }) }) + +function mockClient (methods) { + return function () { + var client = new EventEmitter() + objectAssign(client, methods) + return client + } +} From 9964208fe8ab996782cd5ee4f4bd2f334e8cbd16 Mon Sep 17 00:00:00 2001 From: brianc Date: Fri, 5 Aug 2016 16:23:05 -0500 Subject: [PATCH 0124/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d7772d046..2f9926bf9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.3.1", + "version": "1.4.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From afce7ed6e377f619860a6ea7b4e9416693002836 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 26 Aug 2016 09:05:46 -0500 Subject: [PATCH 0125/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2f9926bf9..e373fb0e8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.4.0", + "version": "1.4.1", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From f2221a404022949e79587670eaf51b3f0596a4a8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 26 Aug 2016 09:07:54 -0500 Subject: [PATCH 0126/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e373fb0e8..f4ad72fe6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.4.1", + "version": "1.4.2", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From b091cc0d057d1a146333ee6d5e5e8ca376ef9f2b Mon Sep 17 00:00:00 2001 From: jphaas Date: Fri, 26 Aug 2016 10:08:15 -0400 Subject: [PATCH 0127/1037] Bug fix: Pool.query now calls cb if connect() fails (#25) * Pool.query calls cb if connect() fails Old behavior was that if connect called back with an error, the promise would get rejected but the cb function would never get called. * Test that Pool.query passes connection errors to callback * Fixes to standardjs compliance --- index.js | 7 ++++++- test/index.js | 11 +++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 80279db2d..10d8dd014 100644 --- a/index.js +++ b/index.js @@ -96,7 +96,12 @@ Pool.prototype.query = function (text, values, cb) { return new this.Promise(function (resolve, reject) { this.connect(function (err, client, done) { - if (err) return reject(err) + if (err) { + if (cb) { + cb(err) + } + return reject(err) + } client.query(text, values, function (err, res) { done(err) err ? reject(err) : resolve(res) diff --git a/test/index.js b/test/index.js index e4616a436..d7752fcec 100644 --- a/test/index.js +++ b/test/index.js @@ -62,6 +62,17 @@ describe('pool', function () { }) }) + it('passes connection errors to callback', function (done) { + var pool = new Pool({host: 'no-postgres-server-here.com'}) + pool.query('SELECT $1::text as name', ['brianc'], function (err, res) { + expect(res).to.be(undefined) + expect(err).to.be.an(Error) + pool.end(function (err) { + done(err) + }) + }) + }) + it('removes client if it errors in background', function (done) { var pool = new Pool() pool.connect(function (err, client, release) { From cf28f9357fa476b11a9257df8fbd1d7c8f939fbd Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 26 Aug 2016 09:11:18 -0500 Subject: [PATCH 0128/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f4ad72fe6..8c1cd7fa3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.4.2", + "version": "1.4.3", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From 6a7edabc22e36db7386c97ee93f08f957364f37d Mon Sep 17 00:00:00 2001 From: Yanlong Wang Date: Wed, 14 Sep 2016 10:26:03 +0800 Subject: [PATCH 0129/1037] When connection fail, emit the error. (#28) * When connection fail, emit the error. If client connect failed, emit the connection error rather than swallowing it. * Add test for connection error. --- index.js | 1 + test/events.js | 26 ++++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 10d8dd014..f62f667db 100644 --- a/index.js +++ b/index.js @@ -43,6 +43,7 @@ Pool.prototype._create = function (cb) { if (err) { this.log('client connection error:', err) cb(err) + this.emit('error', err) } else { this.log('client connected') this.emit('connect', client) diff --git a/test/events.js b/test/events.js index bcb523f03..5045cc2c2 100644 --- a/test/events.js +++ b/test/events.js @@ -22,7 +22,7 @@ describe('events', function () { }) }) - it('emits "connect" only with a successful connection', function (done) { + it('emits "error" with a failed connection', function (done) { var pool = new Pool({ // This client will always fail to connect Client: mockClient({ @@ -34,7 +34,29 @@ describe('events', function () { pool.on('connect', function () { throw new Error('should never get here') }) - pool._create(function (err) { + pool.on('error', function (err) { + if (err) done() + else done(new Error('expected failure')) + }) + pool.connect() + }) + + it('callback err with a failed connection', function (done) { + var pool = new Pool({ + // This client will always fail to connect + Client: mockClient({ + connect: function (cb) { + process.nextTick(function () { cb(new Error('bad news')) }) + } + }) + }) + pool.on('connect', function () { + throw new Error('should never get here') + }) + pool.on('error', function (err) { + if (!err) done(new Error('expected failure')) + }) + pool.connect(function (err) { if (err) done() else done(new Error('expected failure')) }) From fbdfc15b89caa0f45e782bf173bf95f63d3a472c Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Sep 2016 21:29:56 -0500 Subject: [PATCH 0130/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8c1cd7fa3..f8d7e63c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.4.3", + "version": "1.5.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From fd802a385c25ad588350845485ab13e40ccf9752 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Sun, 4 Dec 2016 15:20:24 -0800 Subject: [PATCH 0131/1037] =?UTF-8?q?Don=E2=80=99t=20create=20promises=20w?= =?UTF-8?q?hen=20callbacks=20are=20provided=20(#31)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Revert "When connection fail, emit the error. (#28)" This reverts commit 6a7edabc22e36db7386c97ee93f08f957364f37d. The callback passed to `Pool.prototype.connect` should be responsible for handling connection errors. The `error` event is documented to be: > Emitted whenever an idle client in the pool encounters an error. This isn’t the case of an idle client in the pool; it never makes it into the pool. It also breaks tests on pg’s master because of nonspecific dependencies. * Don’t create promises when callbacks are provided It’s incorrect to do so. One consequence is that a rejected promise will be unhandled, which is currently annoying, but also dangerous in the future: > DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. The way callbacks are used currently also causes #24 (hiding of errors thrown synchronously from the callback). One fix for that would be to call them asynchronously from inside the `new Promise()` executor: process.nextTick(cb, error); I don’t think it’s worth implementing, though, since it would still be backwards-incompatible – just less obvious about it. Also fixes a bug where the `Pool.prototype.connect` callback would be called twice if there was an error. * Use Node-0.10-compatible `process.nextTick` --- index.js | 54 ++++++++++++++++++++++++++++++++------------------ test/events.js | 26 ++---------------------- test/index.js | 26 ++++++++++++++++++++++++ 3 files changed, 63 insertions(+), 43 deletions(-) diff --git a/index.js b/index.js index f62f667db..d3551868e 100644 --- a/index.js +++ b/index.js @@ -22,6 +22,32 @@ var Pool = module.exports = function (options, Client) { util.inherits(Pool, EventEmitter) +Pool.prototype._promise = function (cb, executor) { + if (!cb) { + return new this.Promise(executor) + } + + function resolved (value) { + process.nextTick(function () { + cb(null, value) + }) + } + + function rejected (error) { + process.nextTick(function () { + cb(error) + }) + } + + executor(resolved, rejected) +} + +Pool.prototype._promiseNoCallback = function (callback, executor) { + return callback + ? executor() + : new this.Promise(executor) +} + Pool.prototype._destroy = function (client) { if (client._destroying) return client._destroying = true @@ -43,7 +69,6 @@ Pool.prototype._create = function (cb) { if (err) { this.log('client connection error:', err) cb(err) - this.emit('error', err) } else { this.log('client connected') this.emit('connect', client) @@ -53,15 +78,17 @@ Pool.prototype._create = function (cb) { } Pool.prototype.connect = function (cb) { - return new this.Promise(function (resolve, reject) { + return this._promiseNoCallback(cb, function (resolve, reject) { this.log('acquire client begin') this.pool.acquire(function (err, client) { if (err) { this.log('acquire client. error:', err) if (cb) { cb(err, null, function () {}) + } else { + reject(err) } - return reject(err) + return } this.log('acquire client') @@ -80,9 +107,9 @@ Pool.prototype.connect = function (cb) { if (cb) { cb(null, client, client.release) + } else { + resolve(client) } - - return resolve(client) }.bind(this)) }.bind(this)) } @@ -95,20 +122,14 @@ Pool.prototype.query = function (text, values, cb) { values = undefined } - return new this.Promise(function (resolve, reject) { + return this._promise(cb, function (resolve, reject) { this.connect(function (err, client, done) { if (err) { - if (cb) { - cb(err) - } return reject(err) } client.query(text, values, function (err, res) { done(err) err ? reject(err) : resolve(res) - if (cb) { - cb(err, res) - } }) }) }.bind(this)) @@ -116,15 +137,10 @@ Pool.prototype.query = function (text, values, cb) { Pool.prototype.end = function (cb) { this.log('draining pool') - return new this.Promise(function (resolve, reject) { + return this._promise(cb, function (resolve, reject) { this.pool.drain(function () { this.log('pool drained, calling destroy all now') - this.pool.destroyAllNow(function () { - if (cb) { - cb() - } - resolve() - }) + this.pool.destroyAllNow(resolve) }.bind(this)) }.bind(this)) } diff --git a/test/events.js b/test/events.js index 5045cc2c2..bcb523f03 100644 --- a/test/events.js +++ b/test/events.js @@ -22,7 +22,7 @@ describe('events', function () { }) }) - it('emits "error" with a failed connection', function (done) { + it('emits "connect" only with a successful connection', function (done) { var pool = new Pool({ // This client will always fail to connect Client: mockClient({ @@ -34,29 +34,7 @@ describe('events', function () { pool.on('connect', function () { throw new Error('should never get here') }) - pool.on('error', function (err) { - if (err) done() - else done(new Error('expected failure')) - }) - pool.connect() - }) - - it('callback err with a failed connection', function (done) { - var pool = new Pool({ - // This client will always fail to connect - Client: mockClient({ - connect: function (cb) { - process.nextTick(function () { cb(new Error('bad news')) }) - } - }) - }) - pool.on('connect', function () { - throw new Error('should never get here') - }) - pool.on('error', function (err) { - if (!err) done(new Error('expected failure')) - }) - pool.connect(function (err) { + pool._create(function (err) { if (err) done() else done(new Error('expected failure')) }) diff --git a/test/index.js b/test/index.js index d7752fcec..5f6d0ad5e 100644 --- a/test/index.js +++ b/test/index.js @@ -103,6 +103,32 @@ describe('pool', function () { pool.end(done) }) }) + + it('does not create promises when connecting', function (done) { + var pool = new Pool() + var 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) { + var pool = new Pool() + var 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) { + var pool = new Pool() + var returnValue = pool.end(done) + expect(returnValue).to.be(undefined) + }) }) describe('with promises', function () { From ab70f579234cb51f7508cb18d09ff6d4e6944948 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Sun, 4 Dec 2016 17:27:10 -0600 Subject: [PATCH 0132/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f8d7e63c8..0e01513cb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.5.0", + "version": "1.6.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From af84d5cd4bde99981ebef291fcf7da3d446722da Mon Sep 17 00:00:00 2001 From: Cris Vergara Date: Mon, 5 Dec 2016 17:18:25 -0500 Subject: [PATCH 0133/1037] Fix require for webpack compatibility --- pg.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/pg.js b/pg.js index 96cd7f9a5..c6be9ba61 100644 --- a/pg.js +++ b/pg.js @@ -1,13 +1,10 @@ -var path = require('path') -var pgPath; //support both pg & pg.js //this will eventually go away when i break native bindings //out into their own module try { - pgPath = path.dirname(require.resolve('pg')) + module.exports.Result = require('pg/lib/result.js') + module.exports.prepareValue = require('pg/lib/utils.js').prepareValue } catch(e) { - pgPath = path.dirname(require.resolve('pg.js')) + '/lib' + module.exports.Result = require('pg.js/lib/result.js') + module.exports.prepareValue = require('pg.js/lib/utils.js').prepareValue } - -module.exports.Result = require(path.join(pgPath, 'result.js')) -module.exports.prepareValue = require(path.join(pgPath, 'utils.js')).prepareValue From 27bee1d0bcc105c6dabea68b197cd25030acda0d Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Sat, 10 Dec 2016 15:16:51 -0800 Subject: [PATCH 0134/1037] Fix CI (#1179) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use container-based CI * Remove unnecessary CI configuration * Use Node 6/PostgreSQL 9.6 as default test … rather than testing 0.10 twice with unspecified PostgreSQL. * Use `precise` for PostgreSQL 9.1 According to https://docs.travis-ci.com/user/database-setup/, 9.1 isn’t supported on trusty. * Fix Node 0.10 and 0.12 CI builds These binaries appear to have been built using g++ with flags that clang doesn’t support. Or something. --- .travis.yml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index 78d7f6742..74f1e4c0c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,35 +1,35 @@ language: node_js -sudo: required +sudo: false dist: trusty before_script: - node script/create-test-tables.js pg://postgres@127.0.0.1:5432/postgres env: - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres +node_js: "6" addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-4.8 + postgresql: "9.6" matrix: include: - node_js: "0.10" addons: - postgresql: "9.5" + postgresql: "9.6" + env: [] - node_js: "0.12" addons: - postgresql: "9.5" + postgresql: "9.6" + env: [] - node_js: "4" addons: - postgresql: "9.5" + postgresql: "9.6" - node_js: "5" addons: - postgresql: "9.5" + postgresql: "9.6" - node_js: "6" addons: postgresql: "9.1" + dist: precise - node_js: "6" addons: postgresql: "9.2" @@ -41,4 +41,4 @@ matrix: postgresql: "9.4" - node_js: "6" addons: - postgresql: "9.5" + postgresql: "9.5" From 5d821c3acb5a2e72e3353f295b07568d521b0f57 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Sat, 10 Dec 2016 15:28:48 -0800 Subject: [PATCH 0135/1037] Use more correct escaping for array elements (#1177) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s not JSON. --- lib/utils.js | 14 +++++++++--- test/integration/client/array-tests.js | 30 ++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index b70be5b36..017aa5cd5 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -8,6 +8,14 @@ var defaults = require('./defaults'); +function escapeElement(elementRepresentation) { + var escaped = elementRepresentation + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"'); + + return '"' + escaped + '"'; +} + // convert a JS array to a postgres array literal // uses comma separator so won't work for types like box that use // a different array separator. @@ -25,7 +33,7 @@ function arrayString(val) { } else { - result = result + JSON.stringify(prepareValue(val[i])); + result += escapeElement(prepareValue(val[i])); } } result = result + '}'; @@ -104,7 +112,7 @@ function dateToString(date) { } function dateToStringUTC(date) { - + var ret = pad(date.getUTCFullYear(), 4) + '-' + pad(date.getUTCMonth() + 1, 2) + '-' + pad(date.getUTCDate(), 2) + 'T' + @@ -112,7 +120,7 @@ function dateToStringUTC(date) { pad(date.getUTCMinutes(), 2) + ':' + pad(date.getUTCSeconds(), 2) + '.' + pad(date.getUTCMilliseconds(), 3); - + return ret + "+00:00"; } diff --git a/test/integration/client/array-tests.js b/test/integration/client/array-tests.js index e01a252c5..2525b8a23 100644 --- a/test/integration/client/array-tests.js +++ b/test/integration/client/array-tests.js @@ -1,6 +1,36 @@ var helper = require(__dirname + "/test-helper"); var pg = helper.pg; +test('serializing arrays', function() { + pg.connect(helper.config, assert.calls(function(err, client, done) { + assert.isNull(err); + + test('nulls', function() { + client.query('SELECT $1::text[] as array', [[null]], assert.success(function(result) { + var array = result.rows[0].array; + assert.lengthIs(array, 1); + assert.isNull(array[0]); + })); + }); + + test('elements containing JSON-escaped characters', function() { + var param = '\\"\\"'; + + for (var i = 1; i <= 0x1f; i++) { + param += String.fromCharCode(i); + } + + client.query('SELECT $1::text[] as array', [[param]], assert.success(function(result) { + var array = result.rows[0].array; + assert.lengthIs(array, 1); + assert.equal(array[0], param); + })); + + done(); + }); + })); +}); + test('parsing array results', function() { pg.connect(helper.config, assert.calls(function(err, client, done) { assert.isNull(err); From 5feacd66d0499ff672f52bc3b68db657eeafa556 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Sat, 10 Dec 2016 18:17:09 -0600 Subject: [PATCH 0136/1037] Remove redundant test This functionality is already tested in the node-pg-types repo. --- test/integration/client/type-coercion-tests.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index 70eff30b2..d961c291d 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -198,19 +198,3 @@ helper.pg.connect(helper.config, assert.calls(function(err, client, done) { done(); }) })) - -if(!helper.config.binary) { - test("postgres date type", function() { - var client = helper.client(); - var testDate = new Date(2010, 9, 31); - client.on('error', function(err) { - console.log(err); - client.end(); - }); - client.query("SELECT $1::date", [testDate], assert.calls(function(err, result){ - assert.isNull(err); - assert.strictEqual(result.rows[0].date.toString(), new Date(Date.UTC(2010, 9, 31)).toString()); - })); - client.on('drain', client.end.bind(client)); - }); -} From c4879e321da1f3c0229fdd303b19b9f02503578c Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Sat, 10 Dec 2016 18:58:27 -0600 Subject: [PATCH 0137/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index afc531340..01545dce3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.1.0", + "version": "6.1.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 48a9738a0b6a43600e106788e6c7824bd2f07afd Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 13 Dec 2016 05:36:13 -0800 Subject: [PATCH 0138/1037] Run inbound parser tests (#1182) They were disabled by 4cdd7a116bab03c6096ab1af8f0f522b04993768 without comment; it seems that this might have been unintentional? In any case, they should probably be enabled, updated, or removed. --- test/unit/connection/inbound-parser-tests.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/connection/inbound-parser-tests.js b/test/unit/connection/inbound-parser-tests.js index 55d71d579..13e6fd9eb 100644 --- a/test/unit/connection/inbound-parser-tests.js +++ b/test/unit/connection/inbound-parser-tests.js @@ -1,5 +1,4 @@ require(__dirname+'/test-helper'); -return false; var Connection = require(__dirname + '/../../../lib/connection'); var buffers = require(__dirname + '/../../test-buffers'); var PARSE = function(buffer) { From 981960b445c041ad8c97c631470b5e5c367eb60f Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 13 Dec 2016 05:50:07 -0800 Subject: [PATCH 0139/1037] Remove confusing conditions (#1159) * Remove unreachable code * Remove redundant condition Every path with `!this.values` results in `false` regardless of `this.binary`. --- lib/query.js | 6 ++---- lib/utils.js | 3 --- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/lib/query.js b/lib/query.js index 9e474d121..36d52ba70 100644 --- a/lib/query.js +++ b/lib/query.js @@ -65,11 +65,9 @@ Query.prototype.requiresPreparation = function() { if(this.rows) { return true; } //don't prepare empty text queries if(!this.text) { return false; } - //binary should be prepared to specify results should be in binary - //unless there are no parameters - if(this.binary && !this.values) { return false; } //prepare if there are values - return (this.values || 0).length > 0; + if(!this.values) { return false; } + return this.values.length > 0; }; diff --git a/lib/utils.js b/lib/utils.js index 017aa5cd5..861b7c5b6 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -64,9 +64,6 @@ var prepareValue = function(val, seen) { if(typeof val === 'object') { return prepareObject(val, seen); } - if (typeof val === 'undefined') { - throw new Error('SQL queries with undefined where clause option'); - } return val.toString(); }; From 7f35240a5ceb7d89c5a72c1297b56a8e4031eaac Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 13 Dec 2016 11:51:36 -0600 Subject: [PATCH 0140/1037] Fix for utf-8 characters in md5 passwords (#1183) This is the same fix as supplied in 1178 but includes a test. Closes #1178 --- lib/client.js | 2 +- test/unit/client/md5-password-tests.js | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/client.js b/lib/client.js index 54ab017cb..770f353d2 100644 --- a/lib/client.js +++ b/lib/client.js @@ -344,7 +344,7 @@ Client.prototype.end = function(cb) { }; Client.md5 = function(string) { - return crypto.createHash('md5').update(string).digest('hex'); + return crypto.createHash('md5').update(string, 'utf-8').digest('hex'); }; // expose a Query constructor diff --git a/test/unit/client/md5-password-tests.js b/test/unit/client/md5-password-tests.js index bd5ca46f0..3c5403685 100644 --- a/test/unit/client/md5-password-tests.js +++ b/test/unit/client/md5-password-tests.js @@ -17,5 +17,8 @@ test('md5 authentication', function() { .addCString(password).join(true,'p')); }); }); +}); +test('md5 of utf-8 strings', function() { + assert.equal(Client.md5('😊'), '5deda34cd95f304948d2bc1b4a62c11e'); }); From 2c636c750fb0acf7735c684403edb613b0345a93 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Tue, 13 Dec 2016 11:53:57 -0600 Subject: [PATCH 0141/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 01545dce3..017e04c54 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.1.1", + "version": "6.1.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From f6c40b9331c90d794d5fcbb1d4ae2f28eabd4d42 Mon Sep 17 00:00:00 2001 From: Alexander Mochalin Date: Fri, 16 Dec 2016 20:44:19 +0500 Subject: [PATCH 0142/1037] parse int8[] (#1152) * parse int8[] * missing semicolon * test * test fixed * test fixed * test fixed. again. --- lib/defaults.js | 8 +++++++- test/integration/client/parse-int-8-tests.js | 13 ++++++++++--- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/defaults.js b/lib/defaults.js index a05c21f86..b99e4a8c5 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -62,7 +62,13 @@ var defaults = module.exports = { parseInputDatesAsUTC: false }; +var pgTypes = require('pg-types'); +// save default parsers +var parseBigInteger = pgTypes.getTypeParser(20, 'text'); +var parseBigIntegerArray = pgTypes.getTypeParser(1016, 'text'); + //parse int8 so you can get your count values as actual numbers module.exports.__defineSetter__("parseInt8", function(val) { - require('pg-types').setTypeParser(20, 'text', val ? parseInt : function(val) { return val; }); + pgTypes.setTypeParser(20, 'text', val ? pgTypes.getTypeParser(23, 'text') : parseBigInteger); + pgTypes.setTypeParser(1016, 'text', val ? pgTypes.getTypeParser(1007, 'text') : parseBigIntegerArray); }); diff --git a/test/integration/client/parse-int-8-tests.js b/test/integration/client/parse-int-8-tests.js index 7028e9004..42228cb8b 100644 --- a/test/integration/client/parse-int-8-tests.js +++ b/test/integration/client/parse-int-8-tests.js @@ -6,11 +6,18 @@ test('ability to turn on and off parser', function() { pg.connect(helper.config, assert.success(function(client, done) { pg.defaults.parseInt8 = true; client.query('CREATE TEMP TABLE asdf(id SERIAL PRIMARY KEY)'); - client.query('SELECT COUNT(*) as "count" FROM asdf', assert.success(function(res) { + client.query('SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', assert.success(function(res) { + assert.strictEqual(0, res.rows[0].count); + assert.strictEqual(1, res.rows[0].array[0]); + assert.strictEqual(2, res.rows[0].array[1]); + assert.strictEqual(3, res.rows[0].array[2]); pg.defaults.parseInt8 = false; - client.query('SELECT COUNT(*) as "count" FROM asdf', assert.success(function(res) { + client.query('SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', assert.success(function(res) { done(); - assert.strictEqual("0", res.rows[0].count); + assert.strictEqual('0', res.rows[0].count); + assert.strictEqual('1', res.rows[0].array[0]); + assert.strictEqual('2', res.rows[0].array[1]); + assert.strictEqual('3', res.rows[0].array[2]); pg.end(); })); })); From 6e63f0e2170cfd69992b7e691629e4565db0caa7 Mon Sep 17 00:00:00 2001 From: Patai Adam Date: Mon, 13 Feb 2017 05:20:41 +0100 Subject: [PATCH 0143/1037] Update readme (#1210) * Fix sample code in README * Fix typo --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 308e9738d..2901ee686 100644 --- a/README.md +++ b/README.md @@ -83,8 +83,8 @@ pool.connect(function(err, client, done) { return console.error('error fetching client from pool', err); } client.query('SELECT $1::int AS number', ['1'], function(err, result) { - //call `done()` to release the client back to the pool - done(); + //call `done(err)` to release the client back to the pool (or destroy it if there is an error) + done(err); if(err) { return console.error('error running query', err); From 5b6d883723d97936e309fdddfb3c438efcea84fd Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Sun, 12 Feb 2017 20:23:09 -0800 Subject: [PATCH 0144/1037] Remove broken tests with external dependency (#1209) Yikes. --- .../integration/client/heroku-pgpass-tests.js | 39 ------------------- test/integration/client/heroku-ssl-tests.js | 28 ------------- test/integration/client/heroku.pgpass | 1 - 3 files changed, 68 deletions(-) delete mode 100644 test/integration/client/heroku-pgpass-tests.js delete mode 100644 test/integration/client/heroku-ssl-tests.js delete mode 100644 test/integration/client/heroku.pgpass diff --git a/test/integration/client/heroku-pgpass-tests.js b/test/integration/client/heroku-pgpass-tests.js deleted file mode 100644 index 578342f13..000000000 --- a/test/integration/client/heroku-pgpass-tests.js +++ /dev/null @@ -1,39 +0,0 @@ -var helper = require(__dirname + '/../test-helper'); - -// Path to the password file -var passfile = __dirname + '/heroku.pgpass'; - -// Export the path to the password file -process.env.PGPASSFILE = passfile; - -// Do a chmod 660, because git doesn't track those permissions -require('fs').chmodSync(passfile, 384); - -var pg = helper.pg; - -var host = 'ec2-107-20-224-218.compute-1.amazonaws.com'; -var database = 'db6kfntl5qhp2'; -var user = 'kwdzdnqpdiilfs'; - -var config = { - host: host, - database: database, - user: user, - ssl: true -}; - -test('uses password file when PGPASSFILE env variable is set', function() { - // connect & disconnect from heroku - pg.connect(config, assert.calls(function(err, client, done) { - assert.isNull(err); - client.query('SELECT NOW() as time', assert.success(function(res) { - assert(res.rows[0].time.getTime()); - - // cleanup ... remove the env variable - delete process.env.PGPASSFILE; - - done(); - pg.end(); - })) - })); -}); diff --git a/test/integration/client/heroku-ssl-tests.js b/test/integration/client/heroku-ssl-tests.js deleted file mode 100644 index dce3701f8..000000000 --- a/test/integration/client/heroku-ssl-tests.js +++ /dev/null @@ -1,28 +0,0 @@ -var helper = require(__dirname + '/../test-helper'); -var pg = helper.pg; - -var host = 'ec2-107-20-224-218.compute-1.amazonaws.com'; -var database = 'db6kfntl5qhp2'; -var user = 'kwdzdnqpdiilfs'; -var port = 5432; - -var config = { - host: host, - port: port, - database: database, - user: user, - password: 'uaZoSSHgi7mVM7kYaROtusClKu', - ssl: true -}; - -test('connection with config ssl = true', function() { - //connect & disconnect from heroku - pg.connect(config, assert.calls(function(err, client, done) { - assert.isNull(err); - client.query('SELECT NOW() as time', assert.success(function(res) { - assert(res.rows[0].time.getTime()); - done(); - pg.end(); - })) - })); -}); diff --git a/test/integration/client/heroku.pgpass b/test/integration/client/heroku.pgpass deleted file mode 100644 index 39bba52ec..000000000 --- a/test/integration/client/heroku.pgpass +++ /dev/null @@ -1 +0,0 @@ -ec2-107-20-224-218.compute-1.amazonaws.com:5432:db6kfntl5qhp2:kwdzdnqpdiilfs:uaZoSSHgi7mVM7kYaROtusClKu From 41017814d3c3195590bf23098aa9c63b3cb395de Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 21 Feb 2017 09:19:03 -0800 Subject: [PATCH 0145/1037] Avoid infinite loop on malformed message (#1208) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Avoid infinite loop on malformed message If handling of such messages is deemed unimportant, `indexOf` is still faster (~40%) and cleaner than a manual loop. Addresses #1048 to an extent. * Use indexOf fallback for Node ≤0.12 --- lib/connection.js | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 6584c871d..59247a7c4 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -13,6 +13,21 @@ var util = require('util'); var Writer = require('buffer-writer'); var Reader = require('packet-reader'); +var indexOf = + 'indexOf' in Buffer.prototype ? + function indexOf(buffer, value, start) { + return buffer.indexOf(value, start); + } : + function indexOf(buffer, value, start) { + for (var i = start, len = buffer.length; i < len; i++) { + if (buffer[i] === value) { + return i; + } + } + + return -1; + }; + var TEXT_MODE = 0; var BINARY_MODE = 1; var Connection = function(config) { @@ -647,8 +662,9 @@ Connection.prototype.readBytes = function(buffer, length) { Connection.prototype.parseCString = function(buffer) { var start = this.offset; - while(buffer[this.offset++] !== 0) { } - return buffer.toString(this.encoding, start, this.offset - 1); + var end = indexOf(buffer, 0, start); + this.offset = end + 1; + return buffer.toString(this.encoding, start, end); }; //end parsing methods module.exports = Connection; From 2a46c8a3d4337a99176186c053ced4db17da4739 Mon Sep 17 00:00:00 2001 From: Arnaud Benhamdine Date: Wed, 1 Mar 2017 15:11:40 +0100 Subject: [PATCH 0146/1037] Add node LTS and current versions to travis matrix --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 95eb599ef..0e1916fb4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,5 +3,7 @@ node_js: - "0.10" - "0.12" - "4.2" + - "6" + - "7" env: - PGUSER=postgres PGDATABASE=postgres From 5cb38f58921ca84f3fd47c74fa7e895cee804918 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Mon, 6 Mar 2017 18:04:16 +0100 Subject: [PATCH 0147/1037] Handle throws in type parsers (#1218) * Handle throws in type parsers * Fix throw in type parsers test for Node 0.x --- lib/query.js | 14 ++- .../unit/client/throw-in-type-parser-tests.js | 112 ++++++++++++++++++ 2 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 test/unit/client/throw-in-type-parser-tests.js diff --git a/lib/query.js b/lib/query.js index 36d52ba70..19a8613ec 100644 --- a/lib/query.js +++ b/lib/query.js @@ -80,7 +80,19 @@ Query.prototype.handleRowDescription = function(msg) { }; Query.prototype.handleDataRow = function(msg) { - var row = this._result.parseRow(msg.fields); + var row; + + if (this._canceledDueToError) { + return; + } + + try { + row = this._result.parseRow(msg.fields); + } catch (err) { + this._canceledDueToError = err; + return; + } + this.emit('row', row, this._result); if (this._accumulateRows) { this._result.addRow(row); diff --git a/test/unit/client/throw-in-type-parser-tests.js b/test/unit/client/throw-in-type-parser-tests.js new file mode 100644 index 000000000..ed3711376 --- /dev/null +++ b/test/unit/client/throw-in-type-parser-tests.js @@ -0,0 +1,112 @@ +var helper = require(__dirname + "/test-helper"); +var types = require('pg-types') + +test('handles throws in type parsers', function() { + var typeParserError = new Error('TEST: Throw in type parsers'); + + types.setTypeParser('special oid that will throw', function () { + throw typeParserError; + }); + + test('emits error', function() { + var handled; + var client = helper.client(); + var con = client.connection; + var query = client.query('whatever'); + + handled = con.emit('readyForQuery'); + assert.ok(handled, "should have handled ready for query"); + + con.emit('rowDescription',{ + fields: [{ + name: 'boom', + dataTypeID: 'special oid that will throw' + }] + }); + assert.ok(handled, "should have handled row description"); + + assert.emits(query, 'error', function(err) { + assert.equal(err, typeParserError); + }); + + handled = con.emit('dataRow', { fields: ["hi"] }); + assert.ok(handled, "should have handled first data row message"); + + handled = con.emit('commandComplete', { text: 'INSERT 31 1' }); + assert.ok(handled, "should have handled command complete"); + + handled = con.emit('readyForQuery'); + assert.ok(handled, "should have handled ready for query"); + }); + + test('calls callback with error', function() { + var handled; + + var callbackCalled = 0; + + var client = helper.client(); + var con = client.connection; + var query = client.query('whatever', assert.calls(function (err) { + callbackCalled += 1; + + assert.equal(callbackCalled, 1); + assert.equal(err, typeParserError); + })); + + handled = con.emit('readyForQuery'); + assert.ok(handled, "should have handled ready for query"); + + handled = con.emit('rowDescription',{ + fields: [{ + name: 'boom', + dataTypeID: 'special oid that will throw' + }] + }); + assert.ok(handled, "should have handled row description"); + + handled = con.emit('dataRow', { fields: ["hi"] }); + assert.ok(handled, "should have handled first data row message"); + + handled = con.emit('dataRow', { fields: ["hi"] }); + assert.ok(handled, "should have handled second data row message"); + + con.emit('commandComplete', { text: 'INSERT 31 1' }); + assert.ok(handled, "should have handled command complete"); + + handled = con.emit('readyForQuery'); + assert.ok(handled, "should have handled ready for query"); + }); + + test('rejects promise with error', function() { + var handled; + var client = helper.client(); + var con = client.connection; + var query = client.query('whatever'); + var queryPromise = query.promise(); + + handled = con.emit('readyForQuery'); + assert.ok(handled, "should have handled ready for query"); + + handled = con.emit('rowDescription',{ + fields: [{ + name: 'boom', + dataTypeID: 'special oid that will throw' + }] + }); + assert.ok(handled, "should have handled row description"); + + handled = con.emit('dataRow', { fields: ["hi"] }); + assert.ok(handled, "should have handled first data row message"); + + handled = con.emit('commandComplete', { text: 'INSERT 31 1' }); + assert.ok(handled, "should have handled command complete"); + + handled = con.emit('readyForQuery'); + assert.ok(handled, "should have handled ready for query"); + + queryPromise.catch(assert.calls(function (err) { + assert.equal(err, typeParserError); + })); + }); + +}); From ff5ceb4304535fe69cf472faac0bf61a057af253 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 6 Mar 2017 11:06:08 -0600 Subject: [PATCH 0148/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 017e04c54..db7c0be33 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.1.2", + "version": "6.1.3", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 2aed8bf7b3a03917b14336f5048c2092109f40b9 Mon Sep 17 00:00:00 2001 From: Shakeel Mohamed Date: Mon, 6 Mar 2017 09:47:30 -0800 Subject: [PATCH 0149/1037] Add syntax highlighting to code block in README (#42) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 39711ab3c..b86447b40 100644 --- a/README.md +++ b/README.md @@ -188,7 +188,7 @@ await pool.end() 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 From ce8f215c88583d82b0dde22743f4fdc688942d9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20Unneb=C3=A4ck?= Date: Thu, 9 Mar 2017 22:05:26 +0100 Subject: [PATCH 0150/1037] Fix throw in type parsers when in prepared statement (#1242) --- lib/client.js | 2 +- lib/query.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/client.js b/lib/client.js index 770f353d2..a77e5d480 100644 --- a/lib/client.js +++ b/lib/client.js @@ -169,7 +169,7 @@ Client.prototype.connect = function(callback) { self.readyForQuery = true; self._pulseQueryQueue(); if(activeQuery) { - activeQuery.handleReadyForQuery(); + activeQuery.handleReadyForQuery(con); } }); diff --git a/lib/query.js b/lib/query.js index 19a8613ec..f62786022 100644 --- a/lib/query.js +++ b/lib/query.js @@ -116,9 +116,9 @@ Query.prototype.handleEmptyQuery = function(con) { } }; -Query.prototype.handleReadyForQuery = function() { +Query.prototype.handleReadyForQuery = function(con) { if(this._canceledDueToError) { - return this.handleError(this._canceledDueToError); + return this.handleError(this._canceledDueToError, con); } if(this.callback) { this.callback(null, this._result); From 4fae7a9a7fc42fd25345a940ea9b8be2d4eaa012 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 9 Mar 2017 15:06:29 -0600 Subject: [PATCH 0151/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index db7c0be33..a2be721ef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.1.3", + "version": "6.1.4", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 549404e21edd2a89c42ad7b9630e120c7b1cae1d Mon Sep 17 00:00:00 2001 From: Ryan Hamilton Date: Tue, 21 Mar 2017 01:00:57 +0800 Subject: [PATCH 0152/1037] Update README.md (#1247) grammar fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2901ee686..6bb0fe0e9 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ var config = { //this initializes a connection pool -//it will keep idle connections open for a 30 seconds +//it will keep idle connections open for 30 seconds //and set a limit of maximum 10 idle clients var pool = new pg.Pool(config); From 197f86f90decd7604249863460e828890f8632ba Mon Sep 17 00:00:00 2001 From: Magnus Hiie Date: Mon, 20 Mar 2017 19:01:41 +0200 Subject: [PATCH 0153/1037] Fix ECONNRESET error emitted after failed connect (#1230) On Windows, after a connect attempt has failed, an error event with ECONNRESET is emitted after the real connect error is propagated to the connect callback, because the connection is not in ending state (connection._ending) where ECONNRESET is ignored. This change ends the connection when connect has failed. This fixes #746. --- lib/client.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/client.js b/lib/client.js index a77e5d480..5d365dab5 100644 --- a/lib/client.js +++ b/lib/client.js @@ -182,6 +182,7 @@ Client.prototype.connect = function(callback) { if(!callback) { return self.emit('error', error); } + con.end(); // make sure ECONNRESET errors don't cause error events callback(error); callback = null; }); From 3de22ba991676534b366144c02145c015cca6125 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 20 Mar 2017 12:01:56 -0500 Subject: [PATCH 0154/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a2be721ef..5d7b20cca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.1.4", + "version": "6.1.5", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 7504c2074531a368712efa377a2bd9504e84973d Mon Sep 17 00:00:00 2001 From: Rocky Date: Mon, 27 Mar 2017 22:20:27 -0500 Subject: [PATCH 0155/1037] Fix README.md (#1250) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6bb0fe0e9..befd73916 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -#node-postgres +# node-postgres [![Build Status](https://secure.travis-ci.org/brianc/node-postgres.svg?branch=master)](http://travis-ci.org/brianc/node-postgres) [![Dependency Status](https://david-dm.org/brianc/node-postgres.svg)](https://david-dm.org/brianc/node-postgres) From 71a136488bf99b4ccdb4912902c451c74314d48c Mon Sep 17 00:00:00 2001 From: javiertury Date: Tue, 28 Mar 2017 05:21:04 +0200 Subject: [PATCH 0156/1037] Improve Readme.md for not so advanced users (#1235) * Improve Readme.md for not so advanced users 1. Add brief description about the 3 possible ways of executing queries: passing the query to a pool, borrowing a client from a pool or obtaining an exclusive client. Give examples for the 3 of them. 2. Use the examples to teach how to reuse a pool in all of your project. This should be helpful for not so advanced users and prevents mistakes. 3. Open a troubleshooting section. * Shrink Troubleshooting and Point to Examples 1. Troubleshooting/FAQ section will only contain a reference to the wiki FAQ. I've already moved the content to the wiki. 2. At the end of "Pooling example" point to the wiki example page. Also indicate that there they can find how to use node-postgres with promises and async/await. I've already created that content in the wiki. --- README.md | 141 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 96 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index befd73916..dc39e38ae 100644 --- a/README.md +++ b/README.md @@ -15,46 +15,36 @@ $ npm install pg ## Intro & Examples -### Simple example +There are 3 ways of executing queries -```js -var pg = require('pg'); +1. Passing the query to a pool +2. Borrowing a client from a pool and executing the query with it +3. Obtaining an exclusive client and executing the query with it -// instantiate a new client -// the client will read connection information from -// the same environment variables used by postgres cli tools -var client = new pg.Client(); +It is recommended to pass the query to a pool as often as possible. If that isn't possible, because of long and complex transactions for example, borrow a client from a pool. Just remember to initialize the pool only once in your code so you maximize reusability of connections. -// connect to our database -client.connect(function (err) { - if (err) throw err; +### Why pooling? - // execute a query on our database - client.query('SELECT $1::text as name', ['brianc'], function (err, result) { - if (err) throw err; +If you're working on something like a web application which makes frequent queries you'll want to access the PostgreSQL server through a pool of clients. Why? For one thing, there is ~20-30 millisecond delay (YMMV) when connecting a new client to the PostgreSQL server because of the startup handshake. Furthermore, PostgreSQL can support only a limited number of clients...it depends on the amount of ram on your database server, but generally more than 100 clients at a time is a __very bad thing__. :tm: Additionally, PostgreSQL can only execute 1 query at a time per connected client, so pipelining all queries for all requests through a single, long-lived client will likely introduce a bottleneck into your application if you need high concurrency. - // just print the result to the console - console.log(result.rows[0]); // outputs: { name: 'brianc' } +With that in mind we can imagine a situation where you have a web server which connects and disconnects a new client for every web request or every query (don't do this!). If you get only 1 request at a time everything will seem to work fine, though it will be a touch slower due to the connection overhead. Once you get >100 simultaneous requests your web server will attempt to open 100 connections to the PostgreSQL backend and :boom: you'll run out of memory on the PostgreSQL server, your database will become unresponsive, your app will seem to hang, and everything will break. Boooo! - // disconnect the client - client.end(function (err) { - if (err) throw err; - }); - }); -}); +__Good news__: node-postgres ships with built in client pooling. Client pooling allows your application to use a pool of already connected clients and reuse them for each request to your application. If your app needs to make more queries than there are available clients in the pool the queries will queue instead of overwhelming your database & causing a cascading failure. :thumbsup: -``` +node-postgres uses [pg-pool](https://github.com/brianc/node-pg-pool.git) to manage pooling. It bundles it and exports it for convenience. If you want, you can `require('pg-pool')` and use it directly - it's the same as the constructor exported at `pg.Pool`. -### Client pooling +It's __highly recommended__ you read the documentation for [pg-pool](https://github.com/brianc/node-pg-pool.git). -If you're working on something like a web application which makes frequent queries you'll want to access the PostgreSQL server through a pool of clients. Why? For one thing, there is ~20-30 millisecond delay (YMMV) when connecting a new client to the PostgreSQL server because of the startup handshake. Furthermore, PostgreSQL can support only a limited number of clients...it depends on the amount of ram on your database server, but generally more than 100 clients at a time is a __very bad thing__. :tm: Additionally, PostgreSQL can only execute 1 query at a time per connected client, so pipelining all queries for all requests through a single, long-lived client will likely introduce a bottleneck into your application if you need high concurrency. +[Here is an up & running quickly example](https://github.com/brianc/node-postgres/wiki/Example) -With that in mind we can imagine a situation where you have a web server which connects and disconnects a new client for every web request or every query (don't do this!). If you get only 1 request at a time everything will seem to work fine, though it will be a touch slower due to the connection overhead. Once you get >100 simultaneous requests your web server will attempt to open 100 connections to the PostgreSQL backend and :boom: you'll run out of memory on the PostgreSQL server, your database will become unresponsive, your app will seem to hang, and everything will break. Boooo! +For more information about `config.ssl` check [TLS (SSL) of nodejs](https://nodejs.org/dist/latest-v4.x/docs/api/tls.html) -__Good news__: node-postgres ships with built in client pooling. Client pooling allows your application to use a pool of already connected clients and reuse them for each request to your application. If your app needs to make more queries than there are available clients in the pool the queries will queue instead of overwhelming your database & causing a cascading failure. :thumbsup: +### Pooling example + +Let's create a pool in `./lib/db.js` which will be reused across the whole project ```javascript -var pg = require('pg'); +const pg = require('pg') // create a config to configure both pooling behavior // and client options @@ -70,18 +60,63 @@ var config = { idleTimeoutMillis: 30000, // how long a client is allowed to remain idle before being closed }; - //this initializes a connection pool //it will keep idle connections open for 30 seconds //and set a limit of maximum 10 idle clients -var pool = new pg.Pool(config); +const pool = new pg.Pool(config); -// to run a query we can acquire a client from the pool, -// run a query on the client, and then return the client to the pool +pool.on('error', function (err, client) { + // if an error is encountered by a client while it sits idle in the pool + // the pool itself will emit an error event with both the error and + // the client which emitted the original error + // this is a rare occurrence but can happen if there is a network partition + // between your application and the database, the database restarts, etc. + // and so you might want to handle it and at least log it out + console.error('idle client error', err.message, err.stack) +}) + +//export the query method for passing queries to the pool +module.exports.query = function (text, values, callback) { + console.log('query:', text, values); + return pool.query(text, values, callback); +}; + +// the pool also supports checking out a client for +// multiple operations, such as a transaction +module.exports.connect = function (callback) { + return pool.connect(callback); +}; +``` + +Now if in `./foo.js` you want to pass a query to the pool + +```js +const pool = require('./lib/db'); + +//to run a query we just pass it to the pool +//after we're done nothing has to be taken care of +//we don't have to return any client to the pool or close a connection +pool.query('SELECT $1::int AS number', ['2'], function(err, res) { + if(err) { + return console.error('error running query', err); + } + + console.log('number:', res.rows[0].number); +}); +``` + +Or if in `./bar.js` you want borrow a client from the pool + +```js +const pool = require('./lib/db'); + +//ask for a client from the pool pool.connect(function(err, client, done) { if(err) { return console.error('error fetching client from pool', err); } + + //use the client for executing the query client.query('SELECT $1::int AS number', ['1'], function(err, result) { //call `done(err)` to release the client back to the pool (or destroy it if there is an error) done(err); @@ -93,27 +128,39 @@ pool.connect(function(err, client, done) { //output: 1 }); }); - -pool.on('error', function (err, client) { - // if an error is encountered by a client while it sits idle in the pool - // the pool itself will emit an error event with both the error and - // the client which emitted the original error - // this is a rare occurrence but can happen if there is a network partition - // between your application and the database, the database restarts, etc. - // and so you might want to handle it and at least log it out - console.error('idle client error', err.message, err.stack) -}) ``` -node-postgres uses [pg-pool](https://github.com/brianc/node-pg-pool.git) to manage pooling. It bundles it and exports it for convenience. If you want, you can `require('pg-pool')` and use it directly - it's the same as the constructor exported at `pg.Pool`. +For more examples, including how to use a connection pool with promises and async/await see the [example](https://github.com/brianc/node-postgres/wiki/Example) page in the wiki. -It's __highly recommended__ you read the documentation for [pg-pool](https://github.com/brianc/node-pg-pool.git). +### Obtaining an exclusive client, example +```js +var pg = require('pg'); -[Here is an up & running quickly example](https://github.com/brianc/node-postgres/wiki/Example) +// instantiate a new client +// the client will read connection information from +// the same environment variables used by postgres cli tools +var client = new pg.Client(); +// connect to our database +client.connect(function (err) { + if (err) throw err; -For more information about `config.ssl` check [TLS (SSL) of nodejs](https://nodejs.org/dist/latest-v4.x/docs/api/tls.html) + // execute a query on our database + client.query('SELECT $1::text as name', ['brianc'], function (err, result) { + if (err) throw err; + + // just print the result to the console + console.log(result.rows[0]); // outputs: { name: 'brianc' } + + // disconnect the client + client.end(function (err) { + if (err) throw err; + }); + }); +}); + +``` ## [More Documentation](https://github.com/brianc/node-postgres/wiki) @@ -183,6 +230,10 @@ Information about the testing processes is in the [wiki](https://github.com/bria Open source belongs to all of us, and we're all invited to participate! +## Troubleshooting and FAQ + +The causes and solutions to common errors can be found among the [Frequently Asked Questions(FAQ)](https://github.com/brianc/node-postgres/wiki/FAQ) + ## Support If at all possible when you open an issue please provide From 0f323999fc071ee471a34f0a937d64087ae23f6a Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Sat, 1 Apr 2017 18:28:27 +0200 Subject: [PATCH 0157/1037] Access `Promise` through global (#39) This matches the proposed way in "bring your own promise". --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index d3551868e..43cccae30 100644 --- a/index.js +++ b/index.js @@ -11,7 +11,7 @@ var Pool = module.exports = function (options, Client) { this.options = objectAssign({}, options) this.log = this.options.log || function () { } this.Client = this.options.Client || Client || require('pg').Client - this.Promise = this.options.Promise || Promise + this.Promise = this.options.Promise || global.Promise this.options.max = this.options.max || this.options.poolSize || 10 this.options.create = this.options.create || this._create.bind(this) From 0b3d68ef31e4f315214be7f150123fe7088f2815 Mon Sep 17 00:00:00 2001 From: Lewis J Ellis Date: Sat, 1 Apr 2017 09:31:33 -0700 Subject: [PATCH 0158/1037] Bump generic-pool dep to 2.4.3 (#35) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0e01513cb..41514287b 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "standard-format": "2.2.1" }, "dependencies": { - "generic-pool": "2.4.2", + "generic-pool": "2.4.3", "object-assign": "4.1.0" } } From 5918a9e10547a96d8b059714bc2140a296ad3656 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 1 Apr 2017 18:43:04 -0500 Subject: [PATCH 0159/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 41514287b..f6e76a677 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.6.0", + "version": "1.7.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From c89b74bb5d4ccac201414bf3c6f4860cbb7b74c5 Mon Sep 17 00:00:00 2001 From: Russ Tyndall Date: Thu, 13 Apr 2017 09:26:53 -0400 Subject: [PATCH 0160/1037] Make a test case and fix for errors drainging the pool (#49) * this bug leaves the pool empty even if there is work to be done, if there are enough consecutive errors to empty the pool re brianc/node-pg-pool#48 --- index.js | 28 ++++++++++++++++++++++++++++ test/index.js | 30 ++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/index.js b/index.js index 43cccae30..aec3a1ec3 100644 --- a/index.js +++ b/index.js @@ -3,6 +3,26 @@ var util = require('util') var EventEmitter = require('events').EventEmitter var objectAssign = require('object-assign') +// there is a bug in the generic pool where it will not recreate +// destroyed workers (even if there is waiting work to do) unless +// there is a min specified. Make sure we keep some connections +// SEE: https://github.com/coopernurse/node-pool/pull/186 +// SEE: https://github.com/brianc/node-pg-pool/issues/48 +// SEE: https://github.com/strongloop/loopback-connector-postgresql/issues/231 +function _ensureMinimum () { + var i, diff, waiting + if (this._draining) return + waiting = this._waitingClients.size() + if (this._factory.min > 0) { // we have positive specified minimum + diff = this._factory.min - this._count + } else if (waiting > 0) { // we have no minimum, but we do have work to do + diff = Math.min(waiting, this._factory.max - this._count) + } + for (i = 0; i < diff; i++) { + this._createResource() + } +}; + var Pool = module.exports = function (options, Client) { if (!(this instanceof Pool)) { return new Pool(options, Client) @@ -17,6 +37,14 @@ var Pool = module.exports = function (options, Client) { this.options.create = this.options.create || this._create.bind(this) this.options.destroy = this.options.destroy || this._destroy.bind(this) this.pool = new genericPool.Pool(this.options) + // Monkey patch to ensure we always finish our work + // - There is a bug where callbacks go uncalled if min is not set + // - We might still not want a connection to *always* exist + // - but we do want to create up to max connections if we have work + // - still waiting + // This should be safe till the version of pg-pool is upgraded + // SEE: https://github.com/coopernurse/node-pool/pull/186 + this.pool._ensureMinimum = _ensureMinimum this.onCreate = this.options.onCreate } diff --git a/test/index.js b/test/index.js index 5f6d0ad5e..3f2b99d95 100644 --- a/test/index.js +++ b/test/index.js @@ -194,6 +194,36 @@ describe('pool', function () { }) }) +describe('pool error handling', function () { + it('Should complete these queries without dying', function (done) { + var pgPool = new Pool() + var pool = pgPool.pool + pool._factory.max = 1 + pool._factory.min = null + var errors = 0 + var shouldGet = 0 + function runErrorQuery () { + shouldGet++ + return new Promise(function (resolve, reject) { + pgPool.query("SELECT 'asd'+1 ").then(function (res) { + reject(res) // this should always error + }).catch(function (err) { + errors++ + resolve(err) + }) + }) + } + var ps = [] + for (var i = 0; i < 5; i++) { + ps.push(runErrorQuery()) + } + Promise.all(ps).then(function () { + expect(shouldGet).to.eql(errors) + done() + }) + }) +}) + process.on('unhandledRejection', function (e) { console.error(e.message, e.stack) setImmediate(function () { From 659a448fabe7e4426666748cb6daf2350c33e840 Mon Sep 17 00:00:00 2001 From: brianc Date: Thu, 13 Apr 2017 10:50:00 -0500 Subject: [PATCH 0161/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f6e76a677..763b273c7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.7.0", + "version": "1.7.1", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From 0e2625b74ee1c0e57df36795846a490ee4df375b Mon Sep 17 00:00:00 2001 From: Kenneth Schnall Date: Mon, 17 Apr 2017 12:43:09 -0400 Subject: [PATCH 0162/1037] Add semicolons to Pooling example in README.md (#1266) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index dc39e38ae..2f9d11beb 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ For more information about `config.ssl` check [TLS (SSL) of nodejs](https://node Let's create a pool in `./lib/db.js` which will be reused across the whole project ```javascript -const pg = require('pg') +const pg = require('pg'); // create a config to configure both pooling behavior // and client options @@ -72,8 +72,8 @@ pool.on('error', function (err, client) { // this is a rare occurrence but can happen if there is a network partition // between your application and the database, the database restarts, etc. // and so you might want to handle it and at least log it out - console.error('idle client error', err.message, err.stack) -}) + console.error('idle client error', err.message, err.stack); +}); //export the query method for passing queries to the pool module.exports.query = function (text, values, callback) { From 4505ae98d9ff2ddf85a2b6d6d4831b1e4729c26e Mon Sep 17 00:00:00 2001 From: Ary Purnomoz Date: Wed, 19 Apr 2017 21:55:56 +0700 Subject: [PATCH 0163/1037] support ssl params for pg-native (#1169) Make pg-native able to pass sslmode, sslca, sslkey and sslcert params to libpq --- lib/connection-parameters.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index f5126a644..68658eff0 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -79,6 +79,12 @@ ConnectionParameters.prototype.getLibpqConnectionString = function(cb) { add(params, this, 'application_name'); add(params, this, 'fallback_application_name'); + var ssl = typeof this.ssl === 'object' ? this.ssl : {sslmode: this.ssl}; + add(params, ssl, 'sslmode'); + add(params, ssl, 'sslca'); + add(params, ssl, 'sslkey'); + add(params, ssl, 'sslcert'); + if(this.database) { params.push("dbname='" + this.database + "'"); } From 4f790deb7310a58a1d342836315a77ca2d76a927 Mon Sep 17 00:00:00 2001 From: Kibae Shin Date: Tue, 25 Apr 2017 01:24:30 +0700 Subject: [PATCH 0164/1037] Support for logical streaming replication (#1271) * Support for logical streaming replication * Wrong compare expr in getLibpqConnectionString * Simplify codes for replication parameter --- lib/client.js | 4 ++++ lib/connection-parameters.js | 4 ++++ lib/connection.js | 3 +++ 3 files changed, 11 insertions(+) diff --git a/lib/client.js b/lib/client.js index 5d365dab5..1bb27ea22 100644 --- a/lib/client.js +++ b/lib/client.js @@ -26,6 +26,7 @@ var Client = function(config) { this.port = this.connectionParameters.port; this.host = this.connectionParameters.host; this.password = this.connectionParameters.password; + this.replication = this.connectionParameters.replication; var c = config || {}; @@ -222,6 +223,9 @@ Client.prototype.getStartupConf = function() { if (appName) { data.application_name = appName; } + if (params.replication) { + data.replication = '' + params.replication; + } return data; }; diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index 68658eff0..c1c535e98 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -57,6 +57,7 @@ var ConnectionParameters = function(config) { this.binary = val('binary', config); this.ssl = typeof config.ssl === 'undefined' ? useSsl() : config.ssl; this.client_encoding = val("client_encoding", config); + this.replication = val("replication", config); //a domain socket begins with '/' this.isDomainSocket = (!(this.host||'').indexOf('/')); @@ -88,6 +89,9 @@ ConnectionParameters.prototype.getLibpqConnectionString = function(cb) { if(this.database) { params.push("dbname='" + this.database + "'"); } + if(this.replication) { + params.push("replication='" + this.replication + "'"); + } if(this.host) { params.push("host=" + this.host); } diff --git a/lib/connection.js b/lib/connection.js index 59247a7c4..7318287c2 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -425,6 +425,9 @@ Connection.prototype.parseMessage = function(buffer) { case 0x48: //H return this.parseH(buffer, length); + case 0x57: //W + return new Message('replicationStart', length); + case 0x63: //c return new Message('copyDone', length); From 80d136a531e65b22ae0f9e04652bcf524bd015ec Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 24 Apr 2017 13:33:38 -0500 Subject: [PATCH 0165/1037] Add test & documentation for replicationStart message --- CHANGELOG.md | 4 ++++ test/unit/connection/inbound-parser-tests.js | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8efbfed6..56b294133 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### v6.2.0 + +- Add support for [parsing `replicationStart` messages](https://github.com/brianc/node-postgres/pull/1271/files). + ### v6.1.0 - Add optional callback parameter to the pure JavaScript `client.end` method. The native client already supported this. diff --git a/test/unit/connection/inbound-parser-tests.js b/test/unit/connection/inbound-parser-tests.js index 13e6fd9eb..a9910966b 100644 --- a/test/unit/connection/inbound-parser-tests.js +++ b/test/unit/connection/inbound-parser-tests.js @@ -347,6 +347,13 @@ test('Connection', function() { name: 'portalSuspended' }); }); + + test('parses replication start message', function() { + testForMessage(new Buffer([0x57, 0x00, 0x00, 0x00, 0x04]), { + name: 'replicationStart', + length: 4 + }); + }); }); //since the data message on a stream can randomly divide the incomming @@ -465,5 +472,4 @@ test('split buffer, multiple message parsing', function() { splitAndVerifyTwoMessages(1); }); }); - }); From f42924bf057943d5a79ff02c4d35b18777dc5754 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 24 Apr 2017 13:34:03 -0500 Subject: [PATCH 0166/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5d7b20cca..f22d223ed 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.1.5", + "version": "6.2.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 54c204441629b65754dade6cb58a443566fefb22 Mon Sep 17 00:00:00 2001 From: Attila Olah Date: Thu, 27 Apr 2017 12:41:30 +0200 Subject: [PATCH 0167/1037] feat: add basic typings To make this app consumable by Typescript apps a typings file must be present. --- index.d.ts | 14 ++++++++++++++ package.json | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 index.d.ts diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 000000000..556375110 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,14 @@ +export function parse(connectionString: string): ConnectionOptions; + +export interface ConnectionOptions { + host: string | null; + password: string | null; + user: string | null; + port: number | null; + database: string | null; + client_encoding: string | null; + ssl: boolean | null; + + application_name: string | null; + fallback_application_name: string | null; +} diff --git a/package.json b/package.json index c6d4512d9..f3b14c907 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,8 @@ "name": "pg-connection-string", "version": "0.1.3", "description": "Functions for dealing with a PostgresSQL connection string", - "main": "index.js", + "main": "./index.js", + "types": "./index.d.ts", "scripts": { "test": "tap ./test" }, From a3204168b728ef059d4d410786184abbf27a2452 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Thu, 27 Apr 2017 11:42:19 -0500 Subject: [PATCH 0168/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c6c4e0761..3ce243260 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "1.0.1", + "version": "1.0.2", "description": "", "main": "index.js", "directories": { From 557e5f879d25cd82e7adc905c804f0841da8a03f Mon Sep 17 00:00:00 2001 From: Sam Beran Date: Thu, 27 Apr 2017 14:26:11 -0500 Subject: [PATCH 0169/1037] Return result accumulator in callback fixes issue: https://github.com/brianc/node-pg-cursor/issues/22 --- README.md | 3 ++- index.js | 3 ++- test/index.js | 11 +++++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1cddfbfdc..fe79bf74b 100644 --- a/README.md +++ b/README.md @@ -59,12 +59,13 @@ pg.connect(function(err, client, done) { Creates an instance of a query cursor. Pass this instance to node-postgres [`client#query`](https://github.com/brianc/node-postgres/wiki/Client#wiki-method-query-parameterized) -#### cursor#read(int rowCount, function callback(Error err, Array rows) +#### cursor#read(int rowCount, function callback(Error err, Array rows, Result result) Read `rowCount` rows from the cursor instance. The `callback` will be called when the rows are available, loaded into memory, parsed, and converted to JavaScript types. If the cursor has read to the end of the result sets all subsequent calls to `cursor#read` will return a 0 length array of rows. I'm open to other ways to signal the end of a cursor, but this has worked out well for me so far. +`result` is a special [https://github.com/brianc/node-postgres/wiki/Query#result-object](Result) object that can be used to accumulate rows. #### cursor#close(function callback(Error err)) diff --git a/index.js b/index.js index 70a90f571..71c125228 100644 --- a/index.js +++ b/index.js @@ -70,7 +70,8 @@ Cursor.prototype._sendRows = function() { //within the call to this callback this._cb = null if(cb) { - cb(null, this._rows) + this._result.rows = this._rows + cb(null, this._rows, this._result) } this._rows = [] }.bind(this)) diff --git a/test/index.js b/test/index.js index 8f04ccc21..af4f041c5 100644 --- a/test/index.js +++ b/test/index.js @@ -116,4 +116,15 @@ describe('cursor', function() { }) }) }) + + it('returns result along with rows', function(done) { + var cursor = this.pgCursor(text) + cursor.read(1, function(err, rows, result) { + assert.ifError(err) + assert.equal(rows.length, 1) + assert.strictEqual(rows, result.rows) + assert.deepEqual(result.fields.map(f => f.name), ['num']) + done() + }) + }) }) From 4bf66e65dec960865ccd16a5e13b0c7c26766878 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Thu, 27 Apr 2017 14:37:58 -0500 Subject: [PATCH 0170/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3ce243260..9ff7cc9fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "1.0.2", + "version": "1.1.0", "description": "", "main": "index.js", "directories": { From 42af0144832219fce3b185342f5755c84ef2f0e2 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 8 May 2017 16:49:24 -0500 Subject: [PATCH 0171/1037] Update travis.yml --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 061e3d15a..3bd6f9c65 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: node_js node_js: - - "0.10" - - "0.11" + - "6" env: - PGUSER=postgres From acae15de53a2dfb449cfe0dc4d1040f80dbd50da Mon Sep 17 00:00:00 2001 From: Sam Beran Date: Mon, 8 May 2017 16:16:17 -0500 Subject: [PATCH 0172/1037] Emit Query Events This change adds events to the `Cursor` object as per the [Query API](https://github.com/brianc/node-postgres/wiki/Query). --- index.js | 11 ++++++++++- test/index.js | 29 +++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 71c125228..0c20e4868 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,11 @@ var Result = require('./pg').Result var prepare = require('./pg').prepareValue +var EventEmitter = require('events').EventEmitter; +var util = require('util'); + +function Cursor (text, values) { + EventEmitter.call(this); -var Cursor = function(text, values) { this.text = text this.values = values ? values.map(prepare) : null this.connection = null @@ -12,6 +16,8 @@ var Cursor = function(text, values) { this._rows = null } +util.inherits(Cursor, EventEmitter) + Cursor.prototype.submit = function(connection) { this.connection = connection @@ -58,6 +64,7 @@ Cursor.prototype.handleRowDescription = function(msg) { Cursor.prototype.handleDataRow = function(msg) { var row = this._result.parseRow(msg.fields) + this.emit('row', row, this._result) this._rows.push(row) } @@ -87,6 +94,7 @@ Cursor.prototype.handlePortalSuspended = function() { Cursor.prototype.handleReadyForQuery = function() { this._sendRows() + this.emit('end', this._result) this.state = 'done' } @@ -107,6 +115,7 @@ Cursor.prototype.handleError = function(msg) { for(var i = 0; i < this._queue.length; i++) { this._queue.pop()[1](msg) } + this.emit('error', msg) //call sync to keep this connection from hanging this.connection.sync() } diff --git a/test/index.js b/test/index.js index af4f041c5..cc97960e5 100644 --- a/test/index.js +++ b/test/index.js @@ -127,4 +127,33 @@ describe('cursor', function() { done() }) }) + + it('emits row events', function(done) { + var cursor = this.pgCursor(text) + cursor.read(10) + cursor.on('row', (row, result) => result.addRow(row)) + cursor.on('end', (result) => { + assert.equal(result.rows.length, 6) + done() + }) + }) + + it('emits row events when cursor is closed manually', function(done) { + var cursor = this.pgCursor(text) + cursor.on('row', (row, result) => result.addRow(row)) + cursor.on('end', (result) => { + assert.equal(result.rows.length, 3) + done() + }) + + cursor.read(3, () => cursor.close()) + }) + + it('emits error events', function(done) { + var cursor = this.pgCursor('select asdfasdf') + cursor.on('error', function(err) { + assert(err) + done() + }) + }) }) From 2f480217cb599a8ebe2f3ad658eac35a07c8cc68 Mon Sep 17 00:00:00 2001 From: Sam Beran Date: Tue, 9 May 2017 09:16:45 -0500 Subject: [PATCH 0173/1037] fix: only dispatch error events if we have a listener --- index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 0c20e4868..0827043e5 100644 --- a/index.js +++ b/index.js @@ -115,7 +115,11 @@ Cursor.prototype.handleError = function(msg) { for(var i = 0; i < this._queue.length; i++) { this._queue.pop()[1](msg) } - this.emit('error', msg) + + if (this.eventNames().indexOf('error') >= 0) { + //only dispatch error events if we have a listener + this.emit('error', msg) + } //call sync to keep this connection from hanging this.connection.sync() } From 4427e31661df2019df004afded5d8e3cd8f467c0 Mon Sep 17 00:00:00 2001 From: Sam Beran Date: Tue, 9 May 2017 09:30:16 -0500 Subject: [PATCH 0174/1037] fix travis build env --- .travis.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3bd6f9c65..267b07b57 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,13 @@ language: node_js +dist: trusty +sudo: false node_js: - "6" env: - PGUSER=postgres +services: + - postgresql +addons: + postgresql: "9.6" +before_script: + - psql -c 'create database travis;' -U postgres | true \ No newline at end of file From db5f4ae1ab3b53529fe568f20b21d4f78f06d41d Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 15 May 2017 09:36:18 -0500 Subject: [PATCH 0175/1037] Upgrade packet reader (#1287) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f22d223ed..a3142c4ec 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "main": "./lib", "dependencies": { "buffer-writer": "1.0.1", - "packet-reader": "0.2.0", + "packet-reader": "0.3.1", "pg-connection-string": "0.1.3", "pg-pool": "1.*", "pg-types": "1.*", From 4659d5d75fa283e5c6fdb75dccfaba698581a630 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 15 May 2017 09:54:09 -0500 Subject: [PATCH 0176/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a3142c4ec..dfbdfbb1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.2.0", + "version": "6.2.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From ee8193673c551e5f11d46150aa4b989f64fd95c2 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Mon, 15 May 2017 13:19:13 -0400 Subject: [PATCH 0177/1037] Libpq connection string escaping (#1285) * Fix escaping of libpq connection string properties Fix handlings of libpq connection properties to properly escape single quotes and backslashes. Previously the values were surrounded in single quotes which handled whitespace within the property value, but internal single quotes and backslashes would cause invalid connection strings to be generated. * Update expected output in test to be quoted Update the expect host output in the connection parameter test to expect it to be surrounded by single quotes. * Add test for configs with quotes and backslashes --- lib/connection-parameters.js | 17 +++++++++----- .../connection-parameters/creation-tests.js | 22 ++++++++++++++++--- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index c1c535e98..da0e998d9 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -65,10 +65,15 @@ var ConnectionParameters = function(config) { this.fallback_application_name = val('fallback_application_name', config, false); }; +// Convert arg to a string, surround in single quotes, and escape single quotes and backslashes +var quoteParamValue = function(value) { + return "'" + ('' + value).replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'"; +}; + var add = function(params, config, paramName) { var value = config[paramName]; if(value) { - params.push(paramName+"='"+value+"'"); + params.push(paramName + "=" + quoteParamValue(value)); } }; @@ -87,23 +92,23 @@ ConnectionParameters.prototype.getLibpqConnectionString = function(cb) { add(params, ssl, 'sslcert'); if(this.database) { - params.push("dbname='" + this.database + "'"); + params.push("dbname=" + quoteParamValue(this.database)); } if(this.replication) { - params.push("replication='" + this.replication + "'"); + params.push("replication=" + quoteParamValue(this.replication)); } if(this.host) { - params.push("host=" + this.host); + params.push("host=" + quoteParamValue(this.host)); } if(this.isDomainSocket) { return cb(null, params.join(' ')); } if(this.client_encoding) { - params.push("client_encoding='" + this.client_encoding + "'"); + params.push("client_encoding=" + quoteParamValue(this.client_encoding)); } dns.lookup(this.host, function(err, address) { if(err) return cb(err, null); - params.push("hostaddr=" + address); + params.push("hostaddr=" + quoteParamValue(address)); return cb(null, params.join(' ')); }); }; diff --git a/test/unit/connection-parameters/creation-tests.js b/test/unit/connection-parameters/creation-tests.js index 33ee7eeeb..85c2bd037 100644 --- a/test/unit/connection-parameters/creation-tests.js +++ b/test/unit/connection-parameters/creation-tests.js @@ -126,7 +126,7 @@ test('libpq connection string building', function() { checkForPart(parts, "user='brian'"); checkForPart(parts, "password='xyz'"); checkForPart(parts, "port='888'"); - checkForPart(parts, "hostaddr=127.0.0.1"); + checkForPart(parts, "hostaddr='127.0.0.1'"); checkForPart(parts, "dbname='bam'"); })); }); @@ -143,7 +143,7 @@ test('libpq connection string building', function() { assert.isNull(err); var parts = constring.split(" "); checkForPart(parts, "user='brian'"); - checkForPart(parts, "hostaddr=127.0.0.1"); + checkForPart(parts, "hostaddr='127.0.0.1'"); })); }); @@ -173,7 +173,23 @@ test('libpq connection string building', function() { assert.isNull(err); var parts = constring.split(" "); checkForPart(parts, "user='brian'"); - checkForPart(parts, "host=/tmp/"); + checkForPart(parts, "host='/tmp/'"); + })); + }); + + test('config contains quotes and backslashes', function() { + var config = { + user: 'not\\brian', + password: 'bad\'chars', + port: 5432, + host: '/tmp/' + }; + var subject = new ConnectionParameters(config); + subject.getLibpqConnectionString(assert.calls(function(err, constring) { + assert.isNull(err); + var parts = constring.split(" "); + checkForPart(parts, "user='not\\\\brian'"); + checkForPart(parts, "password='bad\\'chars'"); })); }); From c32316df776f58b087b7a1d1882f024b089195cc Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 15 May 2017 12:21:32 -0500 Subject: [PATCH 0178/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dfbdfbb1b..30e4719ad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.2.1", + "version": "6.2.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 6e462ffae62123d15c66481be4b2b122cf8473df Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 15 May 2017 23:16:55 -0500 Subject: [PATCH 0179/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9ff7cc9fb..f3a0d6429 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "1.1.0", + "version": "1.2.0", "description": "", "main": "index.js", "directories": { From e5f0e5d36a91a72dda93c74388ac890fa42b3be0 Mon Sep 17 00:00:00 2001 From: "T.J. Schuck" Date: Wed, 17 May 2017 17:47:07 -0400 Subject: [PATCH 0180/1037] s/2016/2017/ (#1291) --- README.md | 2 +- lib/client.js | 2 +- lib/connection-parameters.js | 2 +- lib/connection.js | 2 +- lib/defaults.js | 2 +- lib/index.js | 2 +- lib/native/index.js | 2 +- lib/native/query.js | 2 +- lib/native/result.js | 2 +- lib/query.js | 2 +- lib/result.js | 2 +- lib/type-overrides.js | 2 +- lib/utils.js | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 2f9d11beb..679b5796d 100644 --- a/README.md +++ b/README.md @@ -253,7 +253,7 @@ Follow me [@briancarlson](https://twitter.com/briancarlson) to keep up to date. ## License -Copyright (c) 2010-2016 Brian Carlson (brian.m.carlson@gmail.com) +Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/lib/client.js b/lib/client.js index 1bb27ea22..a0d7f21c7 100644 --- a/lib/client.js +++ b/lib/client.js @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2016 Brian Carlson (brian.m.carlson@gmail.com) + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. * * This source code is licensed under the MIT license found in the diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index da0e998d9..e6efa158e 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2016 Brian Carlson (brian.m.carlson@gmail.com) + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. * * This source code is licensed under the MIT license found in the diff --git a/lib/connection.js b/lib/connection.js index 7318287c2..87d4f274b 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2016 Brian Carlson (brian.m.carlson@gmail.com) + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. * * This source code is licensed under the MIT license found in the diff --git a/lib/defaults.js b/lib/defaults.js index b99e4a8c5..b94d33f3c 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2016 Brian Carlson (brian.m.carlson@gmail.com) + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. * * This source code is licensed under the MIT license found in the diff --git a/lib/index.js b/lib/index.js index b2372cf4f..65e7be3a5 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2016 Brian Carlson (brian.m.carlson@gmail.com) + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. * * This source code is licensed under the MIT license found in the diff --git a/lib/native/index.js b/lib/native/index.js index db5dfbf51..1e192e8bf 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2016 Brian Carlson (brian.m.carlson@gmail.com) + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. * * This source code is licensed under the MIT license found in the diff --git a/lib/native/query.js b/lib/native/query.js index af75d39b7..fcb1eff4f 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2016 Brian Carlson (brian.m.carlson@gmail.com) + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. * * This source code is licensed under the MIT license found in the diff --git a/lib/native/result.js b/lib/native/result.js index dc68f76c4..519037316 100644 --- a/lib/native/result.js +++ b/lib/native/result.js @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2016 Brian Carlson (brian.m.carlson@gmail.com) + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. * * This source code is licensed under the MIT license found in the diff --git a/lib/query.js b/lib/query.js index f62786022..4d49dafd3 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2016 Brian Carlson (brian.m.carlson@gmail.com) + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. * * This source code is licensed under the MIT license found in the diff --git a/lib/result.js b/lib/result.js index 463fbdbe6..093a73c37 100644 --- a/lib/result.js +++ b/lib/result.js @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2016 Brian Carlson (brian.m.carlson@gmail.com) + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. * * This source code is licensed under the MIT license found in the diff --git a/lib/type-overrides.js b/lib/type-overrides.js index e0cf00e6a..905260898 100644 --- a/lib/type-overrides.js +++ b/lib/type-overrides.js @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2016 Brian Carlson (brian.m.carlson@gmail.com) + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. * * This source code is licensed under the MIT license found in the diff --git a/lib/utils.js b/lib/utils.js index 861b7c5b6..82d1aefd5 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,5 +1,5 @@ /** - * Copyright (c) 2010-2016 Brian Carlson (brian.m.carlson@gmail.com) + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. * * This source code is licensed under the MIT license found in the From 4cd56cc4f857a723aa8eb42ee04b312b86bb0f1e Mon Sep 17 00:00:00 2001 From: Raul Ochoa Date: Wed, 24 May 2017 16:04:50 +0200 Subject: [PATCH 0181/1037] Make pool name consistent on missing config params (#1279) * Going red: using a config object creates two pools when missing some params It should only create a pool in a consistent way, even if some params are not provided in the first place. * Delay the pool name generation to make it consistent between calls * Don't fallback to empty object as config is already defined --- lib/index.js | 2 +- .../single-pool-on-object-config-tests.js | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 test/integration/connection-pool/single-pool-on-object-config-tests.js diff --git a/lib/index.js b/lib/index.js index 65e7be3a5..a2c2792f4 100644 --- a/lib/index.js +++ b/lib/index.js @@ -54,7 +54,6 @@ PG.prototype.connect = function(config, callback) { callback = config; config = null; } - var poolName = JSON.stringify(config || {}); if (typeof config == 'string') { config = new ConnectionParameters(config); } @@ -66,6 +65,7 @@ PG.prototype.connect = function(config, callback) { config.idleTimeoutMillis = config.idleTimeoutMillis || config.poolIdleTimeout || defaults.poolIdleTimeout; config.log = config.log || config.poolLog || defaults.poolLog; + var poolName = JSON.stringify(config); this._pools[poolName] = this._pools[poolName] || new this.Pool(config); var pool = this._pools[poolName]; if(!pool.listeners('error').length) { diff --git a/test/integration/connection-pool/single-pool-on-object-config-tests.js b/test/integration/connection-pool/single-pool-on-object-config-tests.js new file mode 100644 index 000000000..a28cbf5c4 --- /dev/null +++ b/test/integration/connection-pool/single-pool-on-object-config-tests.js @@ -0,0 +1,13 @@ +var helper = require(__dirname + "/../test-helper"); +var pg = require(__dirname + "/../../../lib"); + +pg.connect(helper.config, assert.success(function(client, done) { + assert.equal(Object.keys(pg._pools).length, 1); + pg.connect(helper.config, assert.success(function(client2, done2) { + assert.equal(Object.keys(pg._pools).length, 1); + + done(); + done2(); + pg.end(); + })); +})); From 3757ff7300f03798ee1865f1eaf7125abe9cbda4 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 24 May 2017 09:05:31 -0500 Subject: [PATCH 0182/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 30e4719ad..590a91557 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.2.2", + "version": "6.2.3", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 52c96a4b2e516d069a96ab8435b9a9395830fca7 Mon Sep 17 00:00:00 2001 From: Amila Welihinda Date: Mon, 29 May 2017 08:48:58 -0700 Subject: [PATCH 0183/1037] Create LICENSE (#54) * Create LICENSE * Update LICENSE --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..4e9058148 --- /dev/null +++ b/LICENSE @@ -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. From a51fe56bc11ce8c5370db51cb3f5b171f95d38e4 Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 2 Jun 2017 09:40:11 -0500 Subject: [PATCH 0184/1037] Update .travis.yml Drop node@0.10 and node@0.12 from the test matrix. --- .travis.yml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 8a1126aa0..155d50624 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,18 +2,12 @@ language: node_js matrix: include: - - node_js: "0.10" - addons: - postgresql: "9.1" - - node_js: "0.12" - addons: - postgresql: "9.1" - node_js: "4" addons: postgresql: "9.1" - - node_js: "5" - addons: - postgresql: "9.4" - node_js: "6" addons: postgresql: "9.4" + - node_js: "8" + addons: + postgresql: "9.6" From f93385284df62d8aec3882721f288ba0f30b0727 Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 2 Jun 2017 13:00:42 -0500 Subject: [PATCH 0185/1037] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 155d50624..47358a12a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,4 +10,4 @@ matrix: postgresql: "9.4" - node_js: "8" addons: - postgresql: "9.6" + postgresql: "9.4" From 959d89e043bfba0fd3e16e48483dbd10d25e29fb Mon Sep 17 00:00:00 2001 From: brianc Date: Wed, 7 Jun 2017 22:35:55 -0500 Subject: [PATCH 0186/1037] Add test for connectionString property delegation --- index.js | 2 +- test/connection-strings.js | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 test/connection-strings.js diff --git a/index.js b/index.js index aec3a1ec3..ccad96864 100644 --- a/index.js +++ b/index.js @@ -96,7 +96,7 @@ Pool.prototype._create = function (cb) { client.connect(function (err) { if (err) { this.log('client connection error:', err) - cb(err) + cb(err, client) } else { this.log('client connected') this.emit('connect', client) diff --git a/test/connection-strings.js b/test/connection-strings.js new file mode 100644 index 000000000..cc624a146 --- /dev/null +++ b/test/connection-strings.js @@ -0,0 +1,22 @@ +var expect = require('expect.js') +var describe = require('mocha').describe +var it = require('mocha').it +var Pool = require('../') + +describe('Connection strings', function () { + it('pool delegates connectionString property to client', function () { + var pool = new Pool({ + connectionString: 'postgres://foo:bar@baz:1234/xur' + }) + pool.connect(function (err, client) { + expect(err).to.not.be(undefined) + expect(client).to.not.be(undefined) + expect(client.username).to.equal('foo') + expect(client.password).to.equal('bar') + expect(client.database).to.equal('baz') + expect(client.port).to.equal(1234) + expect(client.database).to.equal('xur') + }) + }) +}) + From 934ca3af16036986dbf2a687b80edcb36695830a Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 7 Jun 2017 20:45:32 -0700 Subject: [PATCH 0187/1037] Remove fallbacks for unsupported Node versions (#1304) * Remove unsupported Node versions 0.10 and 0.12 from CI * Replace deprecated Buffer constructor with .from/.alloc * Remove Promise polyfill * Make use of Object.assign * Remove checks for versions of Node earlier than 4 * Remove Buffer#indexOf fallback for Node 0.10 --- .travis.yml | 8 ----- lib/client.js | 2 +- lib/connection.js | 21 ++---------- package.json | 4 +-- test/buffer-list.js | 10 +++--- .../client/query-as-promise-tests.js | 5 --- .../connection-pool/idle-timeout-tests.js | 3 +- .../connection-pool/yield-support-body.js | 28 ---------------- .../connection-pool/yield-support-tests.js | 33 ++++++++++++++++--- test/integration/gh-issues/675-tests.js | 4 +-- test/test-buffers.js | 8 ++--- test/test-helper.js | 5 --- test/unit/client/md5-password-tests.js | 2 +- test/unit/connection/inbound-parser-tests.js | 16 ++++----- .../unit/connection/outbound-sending-tests.js | 16 ++++----- test/unit/utils-tests.js | 6 ++-- 16 files changed, 65 insertions(+), 106 deletions(-) delete mode 100644 test/integration/connection-pool/yield-support-body.js diff --git a/.travis.yml b/.travis.yml index 74f1e4c0c..885cfa0ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,14 +12,6 @@ addons: matrix: include: - - node_js: "0.10" - addons: - postgresql: "9.6" - env: [] - - node_js: "0.12" - addons: - postgresql: "9.6" - env: [] - node_js: "4" addons: postgresql: "9.6" diff --git a/lib/client.js b/lib/client.js index a0d7f21c7..a565ccbcb 100644 --- a/lib/client.js +++ b/lib/client.js @@ -94,7 +94,7 @@ Client.prototype.connect = function(callback) { //password request handling con.on('authenticationMD5Password', checkPgPass(function(msg) { var inner = Client.md5(self.password + self.user); - var outer = Client.md5(Buffer.concat([new Buffer(inner), msg.salt])); + var outer = Client.md5(Buffer.concat([Buffer.from(inner), msg.salt])); var md5password = "md5" + outer; con.password(md5password); })); diff --git a/lib/connection.js b/lib/connection.js index 87d4f274b..676b5f0cb 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -13,21 +13,6 @@ var util = require('util'); var Writer = require('buffer-writer'); var Reader = require('packet-reader'); -var indexOf = - 'indexOf' in Buffer.prototype ? - function indexOf(buffer, value, start) { - return buffer.indexOf(value, start); - } : - function indexOf(buffer, value, start) { - for (var i = start, len = buffer.length; i < len; i++) { - if (buffer[i] === value) { - return i; - } - } - - return -1; - }; - var TEXT_MODE = 0; var BINARY_MODE = 1; var Connection = function(config) { @@ -311,7 +296,7 @@ Connection.prototype.execute = function(config, more) { this._send(0x45, more); }; -var emptyBuffer = Buffer(0); +var emptyBuffer = Buffer.alloc(0); Connection.prototype.flush = function() { //0x48 = 'H' @@ -450,7 +435,7 @@ Connection.prototype.parseR = function(buffer, length) { code = this.parseInt32(buffer); if(code === 5) { //md5 required msg.name = 'authenticationMD5Password'; - msg.salt = new Buffer(4); + msg.salt = Buffer.alloc(4); buffer.copy(msg.salt, 0, this.offset, this.offset + 4); this.offset += 4; return msg; @@ -665,7 +650,7 @@ Connection.prototype.readBytes = function(buffer, length) { Connection.prototype.parseCString = function(buffer) { var start = this.offset; - var end = indexOf(buffer, 0, start); + var end = buffer.indexOf(0, start); this.offset = end + 1; return buffer.toString(this.encoding, start, end); }; diff --git a/package.json b/package.json index 590a91557..d52ba05ca 100644 --- a/package.json +++ b/package.json @@ -30,9 +30,7 @@ "async": "0.9.0", "co": "4.6.0", "jshint": "2.5.2", - "lodash": "4.13.1", - "pg-copy-streams": "0.3.0", - "promise-polyfill": "5.2.1" + "pg-copy-streams": "0.3.0" }, "minNativeVersion": "1.7.0", "scripts": { diff --git a/test/buffer-list.js b/test/buffer-list.js index 3aa245521..2b1ac73e1 100644 --- a/test/buffer-list.js +++ b/test/buffer-list.js @@ -9,7 +9,7 @@ p.add = function(buffer, front) { }; p.addInt16 = function(val, front) { - return this.add(Buffer([(val >>> 8),(val >>> 0)]),front); + return this.add(Buffer.from([(val >>> 8),(val >>> 0)]),front); }; p.getByteLength = function(initial) { @@ -19,7 +19,7 @@ p.getByteLength = function(initial) { }; p.addInt32 = function(val, first) { - return this.add(Buffer([ + return this.add(Buffer.from([ (val >>> 24 & 0xFF), (val >>> 16 & 0xFF), (val >>> 8 & 0xFF), @@ -29,14 +29,14 @@ p.addInt32 = function(val, first) { p.addCString = function(val, front) { var len = Buffer.byteLength(val); - var buffer = new Buffer(len+1); + var buffer = Buffer.alloc(len+1); buffer.write(val); buffer[len] = 0; return this.add(buffer, front); }; p.addChar = function(char, first) { - return this.add(Buffer(char,'utf8'), first); + return this.add(Buffer.from(char,'utf8'), first); }; p.join = function(appendLength, char) { @@ -49,7 +49,7 @@ p.join = function(appendLength, char) { this.addChar(char, true); length++; } - var result = Buffer(length); + var result = Buffer.alloc(length); var index = 0; this.buffers.forEach(function(buffer) { buffer.copy(result, index, 0); diff --git a/test/integration/client/query-as-promise-tests.js b/test/integration/client/query-as-promise-tests.js index 8dcdeb517..ac958729b 100644 --- a/test/integration/client/query-as-promise-tests.js +++ b/test/integration/client/query-as-promise-tests.js @@ -1,10 +1,5 @@ var helper = require(__dirname + '/../test-helper'); var pg = helper.pg; -var semver = require('semver') - -if (semver.lt(process.version, '0.12.0')) { - return console.log('promises are not supported in node < v0.10') -} process.on('unhandledRejection', function(e) { console.error(e, e.stack) diff --git a/test/integration/connection-pool/idle-timeout-tests.js b/test/integration/connection-pool/idle-timeout-tests.js index 0a60ce504..5a5db0ba9 100644 --- a/test/integration/connection-pool/idle-timeout-tests.js +++ b/test/integration/connection-pool/idle-timeout-tests.js @@ -1,7 +1,6 @@ var helper = require(__dirname + '/test-helper'); -var _ = require('lodash') -const config = _.extend({ }, helper.config, { idleTimeoutMillis: 50 }) +const config = Object.assign({ }, helper.config, { idleTimeoutMillis: 50 }) test('idle timeout', function() { helper.pg.connect(config, assert.calls(function(err, client, done) { diff --git a/test/integration/connection-pool/yield-support-body.js b/test/integration/connection-pool/yield-support-body.js deleted file mode 100644 index 943ab3a2e..000000000 --- a/test/integration/connection-pool/yield-support-body.js +++ /dev/null @@ -1,28 +0,0 @@ -var helper = require('./test-helper') -var co = require('co') - -var tid = setTimeout(function() { - throw new Error('Tests did not complete in time') -}, 1000) - -co(function * () { - var client = yield helper.pg.connect() - var res = yield client.query('SELECT $1::text as name', ['foo']) - assert.equal(res.rows[0].name, 'foo') - - var threw = false - try { - yield client.query('SELECT LKDSJDSLKFJ') - } catch(e) { - threw = true - } - assert(threw) - client.release() - helper.pg.end() - clearTimeout(tid) -}) -.catch(function(e) { - setImmediate(function() { - throw e - }) -}) diff --git a/test/integration/connection-pool/yield-support-tests.js b/test/integration/connection-pool/yield-support-tests.js index fb79ddc4c..943ab3a2e 100644 --- a/test/integration/connection-pool/yield-support-tests.js +++ b/test/integration/connection-pool/yield-support-tests.js @@ -1,5 +1,28 @@ -var semver = require('semver') -if (semver.lt(process.version, '1.0.0')) { - return console.log('yield is not supported in node <= v0.12') -} -require('./yield-support-body') +var helper = require('./test-helper') +var co = require('co') + +var tid = setTimeout(function() { + throw new Error('Tests did not complete in time') +}, 1000) + +co(function * () { + var client = yield helper.pg.connect() + var res = yield client.query('SELECT $1::text as name', ['foo']) + assert.equal(res.rows[0].name, 'foo') + + var threw = false + try { + yield client.query('SELECT LKDSJDSLKFJ') + } catch(e) { + threw = true + } + assert(threw) + client.release() + helper.pg.end() + clearTimeout(tid) +}) +.catch(function(e) { + setImmediate(function() { + throw e + }) +}) diff --git a/test/integration/gh-issues/675-tests.js b/test/integration/gh-issues/675-tests.js index f7d95427d..c27d3632b 100644 --- a/test/integration/gh-issues/675-tests.js +++ b/test/integration/gh-issues/675-tests.js @@ -11,11 +11,11 @@ helper.pg.connect(helper.config, function(err, client, done) { c = 'INSERT INTO posts (body) VALUES ($1) RETURNING *'; - var body = new Buffer('foo'); + var body = Buffer.from('foo'); client.query(c, [body], function(err) { if (err) throw err; - body = new Buffer([]); + body = Buffer.from([]); client.query(c, [body], function(err, res) { done(); diff --git a/test/test-buffers.js b/test/test-buffers.js index ddb6ba637..b16a7ab62 100644 --- a/test/test-buffers.js +++ b/test/test-buffers.js @@ -4,7 +4,7 @@ require(__dirname+'/test-helper'); var buffers = {}; buffers.readyForQuery = function() { return new BufferList() - .add(Buffer('I')) + .add(Buffer.from('I')) .join(true,'Z'); }; @@ -23,7 +23,7 @@ buffers.authenticationCleartextPassword = function() { buffers.authenticationMD5Password = function() { return new BufferList() .addInt32(5) - .add(Buffer([1,2,3,4])) + .add(Buffer.from([1,2,3,4])) .join(true, 'R'); }; @@ -71,7 +71,7 @@ buffers.dataRow = function(columns) { if(col == null) { buf.addInt32(-1); } else { - var strBuf = new Buffer(col, 'utf8'); + var strBuf = Buffer.from(col, 'utf8'); buf.addInt32(strBuf.length); buf.add(strBuf); } @@ -94,7 +94,7 @@ var errorOrNotice = function(fields) { buf.addChar(field.type); buf.addCString(field.value); }); - return buf.add(Buffer([0]));//terminator + return buf.add(Buffer.from([0]));//terminator } buffers.parseComplete = function() { diff --git a/test/test-helper.js b/test/test-helper.js index d8e068764..175cbbb9d 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -1,11 +1,6 @@ //make assert a global... assert = require('assert'); -//support for node@0.10.x -if (typeof Promise == 'undefined') { - global.Promise = require('promise-polyfill') -} - var EventEmitter = require('events').EventEmitter; var sys = require('util'); var BufferList = require(__dirname+'/buffer-list') diff --git a/test/unit/client/md5-password-tests.js b/test/unit/client/md5-password-tests.js index 3c5403685..315ef197b 100644 --- a/test/unit/client/md5-password-tests.js +++ b/test/unit/client/md5-password-tests.js @@ -3,7 +3,7 @@ require(__dirname + '/test-helper'); test('md5 authentication', function() { var client = createClient(); client.password = "!"; - var salt = Buffer([1, 2, 3, 4]); + var salt = Buffer.from([1, 2, 3, 4]); client.connection.emit('authenticationMD5Password', {salt: salt}); test('responds', function() { diff --git a/test/unit/connection/inbound-parser-tests.js b/test/unit/connection/inbound-parser-tests.js index a9910966b..2b822e440 100644 --- a/test/unit/connection/inbound-parser-tests.js +++ b/test/unit/connection/inbound-parser-tests.js @@ -158,7 +158,7 @@ test('Connection', function() { testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage); var msg = testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage); test('md5 has right salt', function() { - assert.equalBuffers(msg.salt, Buffer([1,2,3,4])); + assert.equalBuffers(msg.salt, Buffer.from([1,2,3,4])); }); testForMessage(paramStatusBuffer, expectedParameterStatusMessage); testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage); @@ -173,7 +173,7 @@ test('Connection', function() { }); test("no data message", function() { - testForMessage(Buffer([0x6e, 0, 0, 0, 4]), { + testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), { name: 'noData' }); }); @@ -349,7 +349,7 @@ test('Connection', function() { }); test('parses replication start message', function() { - testForMessage(new Buffer([0x57, 0x00, 0x00, 0x00, 0x04]), { + testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { name: 'replicationStart', length: 4 }); @@ -383,8 +383,8 @@ test('split buffer, single message parsing', function() { }); var testMessageRecievedAfterSpiltAt = function(split) { - var firstBuffer = new Buffer(fullBuffer.length-split); - var secondBuffer = new Buffer(fullBuffer.length-firstBuffer.length); + var firstBuffer = Buffer.alloc(fullBuffer.length-split); + var secondBuffer = Buffer.alloc(fullBuffer.length-firstBuffer.length); fullBuffer.copy(firstBuffer, 0, 0); fullBuffer.copy(secondBuffer, 0, firstBuffer.length); stream.emit('data', firstBuffer); @@ -416,7 +416,7 @@ test('split buffer, single message parsing', function() { test('split buffer, multiple message parsing', function() { var dataRowBuffer = buffers.dataRow(['!']); var readyForQueryBuffer = buffers.readyForQuery(); - var fullBuffer = new Buffer(dataRowBuffer.length + readyForQueryBuffer.length); + var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length); dataRowBuffer.copy(fullBuffer, 0, 0); readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0); @@ -449,8 +449,8 @@ test('split buffer, multiple message parsing', function() { verifyMessages(); }); var splitAndVerifyTwoMessages = function(split) { - var firstBuffer = new Buffer(fullBuffer.length-split); - var secondBuffer = new Buffer(fullBuffer.length-firstBuffer.length); + var firstBuffer = Buffer.alloc(fullBuffer.length-split); + var secondBuffer = Buffer.alloc(fullBuffer.length-firstBuffer.length); fullBuffer.copy(firstBuffer, 0, 0); fullBuffer.copy(secondBuffer, 0, firstBuffer.length); stream.emit('data', firstBuffer); diff --git a/test/unit/connection/outbound-sending-tests.js b/test/unit/connection/outbound-sending-tests.js index 3dde8a3cb..353c073bf 100644 --- a/test/unit/connection/outbound-sending-tests.js +++ b/test/unit/connection/outbound-sending-tests.js @@ -104,12 +104,12 @@ test('bind messages', function() { .addInt16(0) .addInt16(4) .addInt32(1) - .add(Buffer("1")) + .add(Buffer.from("1")) .addInt32(2) - .add(Buffer("hi")) + .add(Buffer.from("hi")) .addInt32(-1) .addInt32(4) - .add(Buffer('zing')) + .add(Buffer.from('zing')) .addInt16(0) .join(true, 'B'); assert.received(stream, expectedBuffer); @@ -120,7 +120,7 @@ test('with named statement, portal, and buffer value', function() { con.bind({ portal: 'bang', statement: 'woo', - values: ['1', 'hi', null, new Buffer('zing', 'UTF-8')] + values: ['1', 'hi', null, Buffer.from('zing', 'utf8')] }); var expectedBuffer = new BufferList() .addCString('bang') //portal name @@ -132,12 +132,12 @@ test('with named statement, portal, and buffer value', function() { .addInt16(1)//binary .addInt16(4) .addInt32(1) - .add(Buffer("1")) + .add(Buffer.from("1")) .addInt32(2) - .add(Buffer("hi")) + .add(Buffer.from("hi")) .addInt32(-1) .addInt32(4) - .add(new Buffer('zing', 'UTF-8')) + .add(Buffer.from('zing', 'UTF-8')) .addInt16(0) .join(true, 'B'); assert.received(stream, expectedBuffer); @@ -181,7 +181,7 @@ test('sends sync command', function() { test('sends end command', function() { con.end(); - var expected = new Buffer([0x58, 0, 0, 0, 4]); + var expected = Buffer.from([0x58, 0, 0, 0, 4]); assert.received(stream, expected); }); diff --git a/test/unit/utils-tests.js b/test/unit/utils-tests.js index d640f9880..82b11715a 100644 --- a/test/unit/utils-tests.js +++ b/test/unit/utils-tests.js @@ -50,7 +50,7 @@ test('normalizing query configs', function() { }) test('prepareValues: buffer prepared properly', function() { - var buf = new Buffer("quack"); + var buf = Buffer.from("quack"); var out = utils.prepareValue(buf); assert.strictEqual(buf, out); }); @@ -142,7 +142,7 @@ test('prepareValue: objects with simple toPostgres prepared properly', function( }); test('prepareValue: objects with complex toPostgres prepared properly', function() { - var buf = new Buffer("zomgcustom!"); + var buf = Buffer.from("zomgcustom!"); var customType = { toPostgres: function() { return [1, 2]; @@ -165,7 +165,7 @@ test('prepareValue: objects with toPostgres receive prepareValue', function() { }); test('prepareValue: objects with circular toPostgres rejected', function() { - var buf = new Buffer("zomgcustom!"); + var buf = Buffer.from("zomgcustom!"); var customType = { toPostgres: function() { return { toPostgres: function () { return customType; } }; From f2b87e02f129a5508eca6ba5ff60f99ba6cdbe58 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 7 Jun 2017 22:58:03 -0500 Subject: [PATCH 0188/1037] Add client connectionString tests (#1310) * Remove redundant tests * Add client connectionString test Add test to ensure { connectionString } is respected as an argument to the client constructor * Add test for connection string property Also fixed some legacy require statements. --- lib/pool-factory.js | 1 - .../double-connection-tests.js | 2 +- .../ending-empty-pool-tests.js | 2 +- .../connection-pool/ending-pool-tests.js | 3 ++- .../connection-pool/error-tests.js | 4 +-- .../connection-pool/idle-timeout-tests.js | 2 +- .../connection-pool/max-connection-tests.js | 2 +- .../connection-pool/native-instance-tests.js | 2 +- .../connection-pool/optional-config-tests.js | 2 +- .../single-connection-tests.js | 2 +- .../single-pool-on-object-config-tests.js | 4 +-- .../waiting-connection-tests.js | 2 +- test/unit/client/configuration-tests.js | 11 ++++++++ test/unit/client/connection-string-tests.js | 27 ------------------- 14 files changed, 25 insertions(+), 41 deletions(-) delete mode 100644 test/unit/client/connection-string-tests.js diff --git a/lib/pool-factory.js b/lib/pool-factory.js index aa7bd0b19..85f0e6a50 100644 --- a/lib/pool-factory.js +++ b/lib/pool-factory.js @@ -3,7 +3,6 @@ var util = require('util'); var Pool = require('pg-pool'); module.exports = function(Client) { - var BoundPool = function(options) { var config = { Client: Client }; for (var key in options) { diff --git a/test/integration/connection-pool/double-connection-tests.js b/test/integration/connection-pool/double-connection-tests.js index ae7eb3169..421e1f9ea 100644 --- a/test/integration/connection-pool/double-connection-tests.js +++ b/test/integration/connection-pool/double-connection-tests.js @@ -1,2 +1,2 @@ -var helper = require(__dirname + "/test-helper") +var helper = require("./test-helper") helper.testPoolSize(2); diff --git a/test/integration/connection-pool/ending-empty-pool-tests.js b/test/integration/connection-pool/ending-empty-pool-tests.js index 4f5dd80ad..d1acc6f20 100644 --- a/test/integration/connection-pool/ending-empty-pool-tests.js +++ b/test/integration/connection-pool/ending-empty-pool-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') var called = false; test('disconnects', function() { diff --git a/test/integration/connection-pool/ending-pool-tests.js b/test/integration/connection-pool/ending-pool-tests.js index 83f4b1bc2..3a1ab46f9 100644 --- a/test/integration/connection-pool/ending-pool-tests.js +++ b/test/integration/connection-pool/ending-pool-tests.js @@ -1,6 +1,7 @@ -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') var called = false; + test('disconnects', function() { var sink = new helper.Sink(4, function() { called = true; diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index 2cf0501fa..59121a86e 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -1,5 +1,5 @@ -var helper = require(__dirname + "/../test-helper"); -var pg = require(__dirname + "/../../../lib"); +var helper = require("../test-helper"); +var pg = require("../../../lib"); //first make pool hold 2 clients pg.defaults.poolSize = 2; diff --git a/test/integration/connection-pool/idle-timeout-tests.js b/test/integration/connection-pool/idle-timeout-tests.js index 0a60ce504..b0908b6fb 100644 --- a/test/integration/connection-pool/idle-timeout-tests.js +++ b/test/integration/connection-pool/idle-timeout-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); var _ = require('lodash') const config = _.extend({ }, helper.config, { idleTimeoutMillis: 50 }) diff --git a/test/integration/connection-pool/max-connection-tests.js b/test/integration/connection-pool/max-connection-tests.js index 68c0773f9..944d2fb2e 100644 --- a/test/integration/connection-pool/max-connection-tests.js +++ b/test/integration/connection-pool/max-connection-tests.js @@ -1,2 +1,2 @@ -var helper = require(__dirname + "/test-helper") +var helper = require("./test-helper") helper.testPoolSize(40); diff --git a/test/integration/connection-pool/native-instance-tests.js b/test/integration/connection-pool/native-instance-tests.js index 06fbdb45b..314920c4d 100644 --- a/test/integration/connection-pool/native-instance-tests.js +++ b/test/integration/connection-pool/native-instance-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + "/../test-helper") +var helper = require("./../test-helper") var pg = helper.pg var native = helper.args.native diff --git a/test/integration/connection-pool/optional-config-tests.js b/test/integration/connection-pool/optional-config-tests.js index f0ba2e76e..be7063eb8 100644 --- a/test/integration/connection-pool/optional-config-tests.js +++ b/test/integration/connection-pool/optional-config-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); //setup defaults helper.pg.defaults.user = helper.args.user; diff --git a/test/integration/connection-pool/single-connection-tests.js b/test/integration/connection-pool/single-connection-tests.js index 5ca0a8884..89f6f069e 100644 --- a/test/integration/connection-pool/single-connection-tests.js +++ b/test/integration/connection-pool/single-connection-tests.js @@ -1,2 +1,2 @@ -var helper = require(__dirname + "/test-helper") +var helper = require("./test-helper") helper.testPoolSize(1); diff --git a/test/integration/connection-pool/single-pool-on-object-config-tests.js b/test/integration/connection-pool/single-pool-on-object-config-tests.js index a28cbf5c4..81cdf8e45 100644 --- a/test/integration/connection-pool/single-pool-on-object-config-tests.js +++ b/test/integration/connection-pool/single-pool-on-object-config-tests.js @@ -1,5 +1,5 @@ -var helper = require(__dirname + "/../test-helper"); -var pg = require(__dirname + "/../../../lib"); +var helper = require("../test-helper"); +var pg = require("../../../lib"); pg.connect(helper.config, assert.success(function(client, done) { assert.equal(Object.keys(pg._pools).length, 1); diff --git a/test/integration/connection-pool/waiting-connection-tests.js b/test/integration/connection-pool/waiting-connection-tests.js index f2519ec55..82572d1e4 100644 --- a/test/integration/connection-pool/waiting-connection-tests.js +++ b/test/integration/connection-pool/waiting-connection-tests.js @@ -1,2 +1,2 @@ -var helper = require(__dirname + "/test-helper") +var helper = require("./test-helper") helper.testPoolSize(200); diff --git a/test/unit/client/configuration-tests.js b/test/unit/client/configuration-tests.js index 0204af22b..5548e5fb1 100644 --- a/test/unit/client/configuration-tests.js +++ b/test/unit/client/configuration-tests.js @@ -59,6 +59,17 @@ test('client settings', function() { test('initializing from a config string', function() { + test('uses connectionString property', function () { + var client = new Client({ + connectionString: 'postgres://brian:pass@host1:333/databasename' + }) + assert.equal(client.user, 'brian'); + assert.equal(client.password, "pass"); + assert.equal(client.host, "host1"); + assert.equal(client.port, 333); + assert.equal(client.database, "databasename"); + }) + test('uses the correct values from the config string', function() { var client = new Client("postgres://brian:pass@host1:333/databasename") assert.equal(client.user, 'brian'); diff --git a/test/unit/client/connection-string-tests.js b/test/unit/client/connection-string-tests.js deleted file mode 100644 index 9316daa9b..000000000 --- a/test/unit/client/connection-string-tests.js +++ /dev/null @@ -1,27 +0,0 @@ -require(__dirname + '/test-helper'); - -/* - * Perhaps duplicate of test named 'initializing from a config string' in - * configuration-tests.js - */ - -test("using connection string in client constructor", function() { - var client = new Client("postgres://brian:pw@boom:381/lala"); - - test("parses user", function() { - assert.equal(client.user,'brian'); - }); - test("parses password", function() { - assert.equal(client.password, 'pw'); - }); - test("parses host", function() { - assert.equal(client.host, 'boom'); - }); - test('parses port', function() { - assert.equal(client.port, 381) - }); - test('parses database', function() { - assert.equal(client.database, 'lala') - }); -}); - From 5061068b0455ba77f2d317cb17543911796c9d25 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 8 Jun 2017 18:18:49 -0500 Subject: [PATCH 0189/1037] Fix test --- index.js | 2 +- test/connection-strings.js | 24 ++++++++++++++++-------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/index.js b/index.js index ccad96864..2e30ac6e3 100644 --- a/index.js +++ b/index.js @@ -96,7 +96,7 @@ Pool.prototype._create = function (cb) { client.connect(function (err) { if (err) { this.log('client connection error:', err) - cb(err, client) + cb(err, null) } else { this.log('client connected') this.emit('connect', client) diff --git a/test/connection-strings.js b/test/connection-strings.js index cc624a146..8ee3d074b 100644 --- a/test/connection-strings.js +++ b/test/connection-strings.js @@ -4,18 +4,26 @@ var it = require('mocha').it var Pool = require('../') describe('Connection strings', function () { - it('pool delegates connectionString property to client', function () { + it('pool delegates connectionString property to client', function (done) { + var connectionString = 'postgres://foo:bar@baz:1234/xur' + var pool = new Pool({ - connectionString: 'postgres://foo:bar@baz:1234/xur' + // 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) - expect(client).to.not.be(undefined) - expect(client.username).to.equal('foo') - expect(client.password).to.equal('bar') - expect(client.database).to.equal('baz') - expect(client.port).to.equal(1234) - expect(client.database).to.equal('xur') + done() }) }) }) From aeb0c759f55cccc439bcaa9b4a4225a6dd812630 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 8 Jun 2017 21:53:47 -0500 Subject: [PATCH 0190/1037] Remove fallbacks for unsupported Node versions (#1304) (#1313) * Add client connectionString tests (#1310) * Remove redundant tests * Add client connectionString test Add test to ensure { connectionString } is respected as an argument to the client constructor * Add test for connection string property Also fixed some legacy require statements. * Normalize native error properties Map native error properties to the same property names we use for errors from the JS driver. Fixes #972 Fixes #938 --- lib/native/query.js | 18 ++++++++++++- lib/pool-factory.js | 1 - .../double-connection-tests.js | 2 +- .../ending-empty-pool-tests.js | 2 +- .../connection-pool/ending-pool-tests.js | 3 ++- .../connection-pool/error-tests.js | 4 +-- .../connection-pool/max-connection-tests.js | 2 +- .../connection-pool/native-instance-tests.js | 2 +- .../connection-pool/optional-config-tests.js | 2 +- .../single-connection-tests.js | 2 +- .../single-pool-on-object-config-tests.js | 4 +-- .../waiting-connection-tests.js | 2 +- test/native/native-vs-js-error-tests.js | 20 ++++++++++++++ test/unit/client/configuration-tests.js | 11 ++++++++ test/unit/client/connection-string-tests.js | 27 ------------------- 15 files changed, 61 insertions(+), 41 deletions(-) create mode 100644 test/native/native-vs-js-error-tests.js delete mode 100644 test/unit/client/connection-string-tests.js diff --git a/lib/native/query.js b/lib/native/query.js index fcb1eff4f..a827af73e 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -51,13 +51,29 @@ NativeQuery.prototype.promise = function() { return this._promise; }; +var errorFieldMap = { + 'sqlState': 'code', + 'statementPosition': 'position', + 'messagePrimary': 'message', + 'context': 'where', + 'schemaName': 'schema', + 'tableName': 'table', + 'columnName': 'column', + 'dataTypeName': 'dataType', + 'constraintName': 'constraint', + 'sourceFile': 'file', + 'sourceLine': 'line', + 'sourceFunction': 'routine', +}; + NativeQuery.prototype.handleError = function(err) { var self = this; //copy pq error fields into the error object var fields = self.native.pq.resultErrorFields(); if(fields) { for(var key in fields) { - err[key] = fields[key]; + var normalizedFieldName = errorFieldMap[key] || key; + err[normalizedFieldName] = fields[key]; } } if(self.callback) { diff --git a/lib/pool-factory.js b/lib/pool-factory.js index aa7bd0b19..85f0e6a50 100644 --- a/lib/pool-factory.js +++ b/lib/pool-factory.js @@ -3,7 +3,6 @@ var util = require('util'); var Pool = require('pg-pool'); module.exports = function(Client) { - var BoundPool = function(options) { var config = { Client: Client }; for (var key in options) { diff --git a/test/integration/connection-pool/double-connection-tests.js b/test/integration/connection-pool/double-connection-tests.js index ae7eb3169..421e1f9ea 100644 --- a/test/integration/connection-pool/double-connection-tests.js +++ b/test/integration/connection-pool/double-connection-tests.js @@ -1,2 +1,2 @@ -var helper = require(__dirname + "/test-helper") +var helper = require("./test-helper") helper.testPoolSize(2); diff --git a/test/integration/connection-pool/ending-empty-pool-tests.js b/test/integration/connection-pool/ending-empty-pool-tests.js index 4f5dd80ad..d1acc6f20 100644 --- a/test/integration/connection-pool/ending-empty-pool-tests.js +++ b/test/integration/connection-pool/ending-empty-pool-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') var called = false; test('disconnects', function() { diff --git a/test/integration/connection-pool/ending-pool-tests.js b/test/integration/connection-pool/ending-pool-tests.js index 83f4b1bc2..3a1ab46f9 100644 --- a/test/integration/connection-pool/ending-pool-tests.js +++ b/test/integration/connection-pool/ending-pool-tests.js @@ -1,6 +1,7 @@ -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') var called = false; + test('disconnects', function() { var sink = new helper.Sink(4, function() { called = true; diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index 2cf0501fa..59121a86e 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -1,5 +1,5 @@ -var helper = require(__dirname + "/../test-helper"); -var pg = require(__dirname + "/../../../lib"); +var helper = require("../test-helper"); +var pg = require("../../../lib"); //first make pool hold 2 clients pg.defaults.poolSize = 2; diff --git a/test/integration/connection-pool/max-connection-tests.js b/test/integration/connection-pool/max-connection-tests.js index 68c0773f9..944d2fb2e 100644 --- a/test/integration/connection-pool/max-connection-tests.js +++ b/test/integration/connection-pool/max-connection-tests.js @@ -1,2 +1,2 @@ -var helper = require(__dirname + "/test-helper") +var helper = require("./test-helper") helper.testPoolSize(40); diff --git a/test/integration/connection-pool/native-instance-tests.js b/test/integration/connection-pool/native-instance-tests.js index 06fbdb45b..314920c4d 100644 --- a/test/integration/connection-pool/native-instance-tests.js +++ b/test/integration/connection-pool/native-instance-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + "/../test-helper") +var helper = require("./../test-helper") var pg = helper.pg var native = helper.args.native diff --git a/test/integration/connection-pool/optional-config-tests.js b/test/integration/connection-pool/optional-config-tests.js index f0ba2e76e..be7063eb8 100644 --- a/test/integration/connection-pool/optional-config-tests.js +++ b/test/integration/connection-pool/optional-config-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); //setup defaults helper.pg.defaults.user = helper.args.user; diff --git a/test/integration/connection-pool/single-connection-tests.js b/test/integration/connection-pool/single-connection-tests.js index 5ca0a8884..89f6f069e 100644 --- a/test/integration/connection-pool/single-connection-tests.js +++ b/test/integration/connection-pool/single-connection-tests.js @@ -1,2 +1,2 @@ -var helper = require(__dirname + "/test-helper") +var helper = require("./test-helper") helper.testPoolSize(1); diff --git a/test/integration/connection-pool/single-pool-on-object-config-tests.js b/test/integration/connection-pool/single-pool-on-object-config-tests.js index a28cbf5c4..81cdf8e45 100644 --- a/test/integration/connection-pool/single-pool-on-object-config-tests.js +++ b/test/integration/connection-pool/single-pool-on-object-config-tests.js @@ -1,5 +1,5 @@ -var helper = require(__dirname + "/../test-helper"); -var pg = require(__dirname + "/../../../lib"); +var helper = require("../test-helper"); +var pg = require("../../../lib"); pg.connect(helper.config, assert.success(function(client, done) { assert.equal(Object.keys(pg._pools).length, 1); diff --git a/test/integration/connection-pool/waiting-connection-tests.js b/test/integration/connection-pool/waiting-connection-tests.js index f2519ec55..82572d1e4 100644 --- a/test/integration/connection-pool/waiting-connection-tests.js +++ b/test/integration/connection-pool/waiting-connection-tests.js @@ -1,2 +1,2 @@ -var helper = require(__dirname + "/test-helper") +var helper = require("./test-helper") helper.testPoolSize(200); diff --git a/test/native/native-vs-js-error-tests.js b/test/native/native-vs-js-error-tests.js new file mode 100644 index 000000000..ee192ddc3 --- /dev/null +++ b/test/native/native-vs-js-error-tests.js @@ -0,0 +1,20 @@ +var assert = require('assert') +var Client = require('../../lib/client'); +var NativeClient = require('../../lib/native'); + +var client = new Client(); +var nativeClient = new NativeClient(); + +client.connect(); +nativeClient.connect((err) => { + client.query('SELECT alsdkfj', (err) => { + client.end(); + + nativeClient.query('SELECT lkdasjfasd', (nativeErr) => { + for(var key in nativeErr) { + assert.equal(err[key], nativeErr[key], `Expected err.${key} to equal nativeErr.${key}`) + } + nativeClient.end(); + }); + }); +}); diff --git a/test/unit/client/configuration-tests.js b/test/unit/client/configuration-tests.js index 0204af22b..5548e5fb1 100644 --- a/test/unit/client/configuration-tests.js +++ b/test/unit/client/configuration-tests.js @@ -59,6 +59,17 @@ test('client settings', function() { test('initializing from a config string', function() { + test('uses connectionString property', function () { + var client = new Client({ + connectionString: 'postgres://brian:pass@host1:333/databasename' + }) + assert.equal(client.user, 'brian'); + assert.equal(client.password, "pass"); + assert.equal(client.host, "host1"); + assert.equal(client.port, 333); + assert.equal(client.database, "databasename"); + }) + test('uses the correct values from the config string', function() { var client = new Client("postgres://brian:pass@host1:333/databasename") assert.equal(client.user, 'brian'); diff --git a/test/unit/client/connection-string-tests.js b/test/unit/client/connection-string-tests.js deleted file mode 100644 index 9316daa9b..000000000 --- a/test/unit/client/connection-string-tests.js +++ /dev/null @@ -1,27 +0,0 @@ -require(__dirname + '/test-helper'); - -/* - * Perhaps duplicate of test named 'initializing from a config string' in - * configuration-tests.js - */ - -test("using connection string in client constructor", function() { - var client = new Client("postgres://brian:pw@boom:381/lala"); - - test("parses user", function() { - assert.equal(client.user,'brian'); - }); - test("parses password", function() { - assert.equal(client.password, 'pw'); - }); - test("parses host", function() { - assert.equal(client.host, 'boom'); - }); - test('parses port', function() { - assert.equal(client.port, 381) - }); - test('parses database', function() { - assert.equal(client.database, 'lala') - }); -}); - From f69108869e7c63aad079bf1b65655791752c28c8 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Fri, 9 Jun 2017 06:57:42 -0400 Subject: [PATCH 0191/1037] Remove default and normalize Travis-CI matrix Removes the default node 6 / PG 9.6 combination and adds it to the Travis-CI matrix of combinations. That way all combinations are defined in a single place. --- .travis.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 885cfa0ec..c50f2f134 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,10 +6,6 @@ before_script: env: - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres -node_js: "6" -addons: - postgresql: "9.6" - matrix: include: - node_js: "4" @@ -34,3 +30,6 @@ matrix: - node_js: "6" addons: postgresql: "9.5" + - node_js: "6" + addons: + postgresql: "9.6" From 61921aae1a6f98601db6904aae596237f4189767 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Fri, 9 Jun 2017 06:58:51 -0400 Subject: [PATCH 0192/1037] Add node 8.x to Travis-CI matrix --- .travis.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/.travis.yml b/.travis.yml index c50f2f134..ec0b7e3d6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,3 +33,22 @@ matrix: - node_js: "6" addons: postgresql: "9.6" + - node_js: "8" + addons: + postgresql: "9.1" + dist: precise + - node_js: "8" + addons: + postgresql: "9.2" + - node_js: "8" + addons: + postgresql: "9.3" + - node_js: "8" + addons: + postgresql: "9.4" + - node_js: "8" + addons: + postgresql: "9.5" + - node_js: "8" + addons: + postgresql: "9.6" From 76c59a01f26c06ada75f56b1b455317cd9e2d758 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 9 Jun 2017 10:56:02 -0500 Subject: [PATCH 0193/1037] Emit error when backend unexpectedly disconnects --- lib/client.js | 46 +++++++--- lib/connection.js | 5 -- .../client/error-handling-tests.js | 22 ++++- .../client/network-partition-tests.js | 90 +++++++++++++++++++ ...error-handling-prepared-statement-tests.js | 15 ++-- ...tream-and-query-error-interaction-tests.js | 2 + 6 files changed, 156 insertions(+), 24 deletions(-) create mode 100644 test/integration/client/network-partition-tests.js diff --git a/lib/client.js b/lib/client.js index a0d7f21c7..78d8bd7b9 100644 --- a/lib/client.js +++ b/lib/client.js @@ -31,6 +31,9 @@ var Client = function(config) { var c = config || {}; this._types = new TypeOverrides(c.types); + this._ending = false; + this._connecting = false; + this._connectionError = false; this.connection = c.connection || new Connection({ stream: c.stream, @@ -50,6 +53,7 @@ util.inherits(Client, EventEmitter); Client.prototype.connect = function(callback) { var self = this; var con = this.connection; + this._connecting = true; if(this.host && this.host.indexOf('/') === 0) { con.connect(this.host + '/.s.PGSQL.' + this.port); @@ -107,6 +111,7 @@ Client.prototype.connect = function(callback) { //hook up query handling events to connection //after the connection initially becomes ready for queries con.once('readyForQuery', function() { + self._connecting = false; //delegate rowDescription to active query con.on('rowDescription', function(msg) { @@ -175,34 +180,52 @@ Client.prototype.connect = function(callback) { }); con.on('error', function(error) { - if(self.activeQuery) { + if(this.activeQuery) { var activeQuery = self.activeQuery; - self.activeQuery = null; + this.activeQuery = null; return activeQuery.handleError(error, con); } + + if (this._connecting) { + // set a flag indicating we've seen an error during connection + // the backend will terminate the connection and we don't want + // to throw a second error when the connection is terminated + this._connectionError = true; + } + if(!callback) { - return self.emit('error', error); + return this.emit('error', error); } + con.end(); // make sure ECONNRESET errors don't cause error events callback(error); callback = null; - }); + }.bind(this)); con.once('end', function() { - if ( callback ) { - // haven't received a connection message yet ! + if (callback) { + // haven't received a connection message yet! var err = new Error('Connection terminated'); callback(err); callback = null; return; } - if(self.activeQuery) { + if(this.activeQuery) { var disconnectError = new Error('Connection terminated'); - self.activeQuery.handleError(disconnectError, con); - self.activeQuery = null; + this.activeQuery.handleError(disconnectError, con); + this.activeQuery = null; } - self.emit('end'); - }); + if (!this._ending) { + // if the connection is ended without us calling .end() + // on this client then we have an unexpected disconnection + // treat this as an error unless we've already emitted an error + // during connection. + if (!this._connectionError) { + this.emit('error', new Error('Connection terminated unexpectedly')); + } + } + this.emit('end'); + }.bind(this)); con.on('notice', function(msg) { @@ -342,6 +365,7 @@ Client.prototype.query = function(config, values, callback) { }; Client.prototype.end = function(cb) { + this._ending = true; this.connection.end(); if (cb) { this.connection.once('end', cb); diff --git a/lib/connection.js b/lib/connection.js index 87d4f274b..b031ece16 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -87,9 +87,6 @@ Connection.prototype.connect = function(port, host) { }); this.stream.on('close', function() { - // NOTE: node-0.10 emits both 'end' and 'close' - // for streams closed by the peer, while - // node-0.8 only emits 'close' self.emit('end'); }); @@ -143,8 +140,6 @@ Connection.prototype.attachListeners = function(stream) { }; Connection.prototype.requestSsl = function() { - this.checkSslResponse = true; - var bodyBuffer = this.writer .addInt16(0x04D2) .addInt16(0x162F).flush(); diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index d3bf36c29..3fcd305bb 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -1,6 +1,24 @@ var helper = require(__dirname + '/test-helper'); var util = require('util'); + + test('non-query error with callback', function () { + var client = new Client({ + user:'asldkfjsadlfkj' + }); + client.connect(assert.calls(function (err) { + assert(err); + })); + }); + + test('non-query error', function() { + var client = new Client({ + user:'asldkfjsadlfkj' + }); + assert.emits(client, 'error'); + client.connect(); + }); + var createErorrClient = function() { var client = helper.client(); client.once('error', function(err) { @@ -11,9 +29,8 @@ var createErorrClient = function() { return client; }; -test('error handling', function(){ +test('error handling', function() { test('within a simple query', function() { - var client = createErorrClient(); var query = client.query("select omfg from yodas_dsflsd where pixistix = 'zoiks!!!'"); @@ -77,7 +94,6 @@ test('error handling', function(){ }); test('non-query error', function() { - var client = new Client({ user:'asldkfjsadlfkj' }); diff --git a/test/integration/client/network-partition-tests.js b/test/integration/client/network-partition-tests.js new file mode 100644 index 000000000..944df510c --- /dev/null +++ b/test/integration/client/network-partition-tests.js @@ -0,0 +1,90 @@ +var co = require('co') + +var buffers = require('../../test-buffers') +var helper = require('./test-helper') + +var net = require('net') + +var Server = function(response) { + this.server = undefined + this.socket = undefined + this.response = response +} + +Server.prototype.start = function (cb) { + // this is our fake postgres server + // it responds with our specified response immediatley after receiving every buffer + // this is sufficient into convincing the client its connectet to a valid backend + // if we respond with a readyForQuery message + this.server = net.createServer(function (socket) { + this.socket = socket + if (this.response) { + this.socket.on('data', function (data) { + // deny request for SSL + if (data.length == 8) { + this.socket.write(new Buffer('N', 'utf8')) + // consider all authentication requests as good + } else if (!data[0]) { + this.socket.write(buffers.authenticationOk()) + // respond with our canned response + } else { + this.socket.write(this.response) + } + }.bind(this)) + } + }.bind(this)) + + var port = 54321 + + var options = { + host: 'localhost', + port: port, + } + this.server.listen(options.port, options.host, function () { + cb(options) + }) +} + +Server.prototype.drop = function () { + this.socket.end() +} + +Server.prototype.close = function (cb) { + this.server.close(cb) +} + +var testServer = function (server, cb) { + // wait for our server to start + server.start(function(options) { + // connect a client to it + var client = new helper.Client(options) + client.connect() + + // after 50 milliseconds, drop the client + setTimeout(function() { + server.drop() + }, 50) + + // blow up if we don't receive an error + var timeoutId = setTimeout(function () { + throw new Error('Client should have emitted an error but it did not.') + }, 5000) + + // return our wait token + client.on('error', function () { + clearTimeout(timeoutId) + server.close(cb) + }) + }) +} + +// test being disconnected after readyForQuery +const respondingServer = new Server(buffers.readyForQuery()) +testServer(respondingServer, function () { + process.stdout.write('.') + // test being disconnected from a server that never responds + const silentServer = new Server() + testServer(silentServer, function () { + process.stdout.write('.') + }) +}) diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index 151646586..77615ff3a 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -29,12 +29,18 @@ test('query killed during query execution of prepared statement', function() { var client = new Client(helper.args); client.connect(assert.success(function() { var sleepQuery = 'select pg_sleep($1)'; - var query1 = client.query({ + + const queryConfig = { name: 'sleep query', text: sleepQuery, - values: [5] }, - assert.calls(function(err, result) { - assert.equal(err.message, 'terminating connection due to administrator command'); + values: [5], + }; + + // client should emit an error because it is unexpectedly disconnected + assert.emits(client, 'error') + + var query1 = client.query(queryConfig, assert.calls(function(err, result) { + assert.equal(err.message, 'terminating connection due to administrator command'); })); query1.on('error', function(err) { @@ -53,7 +59,6 @@ test('query killed during query execution of prepared statement', function() { })); }); - test('client end during query execution of prepared statement', function() { var client = new Client(helper.args); client.connect(assert.success(function() { diff --git a/test/unit/client/stream-and-query-error-interaction-tests.js b/test/unit/client/stream-and-query-error-interaction-tests.js index 02d66c628..a60e1f734 100644 --- a/test/unit/client/stream-and-query-error-interaction-tests.js +++ b/test/unit/client/stream-and-query-error-interaction-tests.js @@ -7,12 +7,14 @@ test('emits end when not in query', function() { stream.write = function() { //NOOP } + var client = new Client({connection: new Connection({stream: stream})}); client.connect(assert.calls(function() { client.query('SELECT NOW()', assert.calls(function(err, result) { assert(err); })); })); + assert.emits(client, 'error'); assert.emits(client, 'end'); client.connection.emit('connect'); process.nextTick(function() { From 58691218affa37b41529376c5167252846bb93fa Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 9 Jun 2017 12:33:55 -0500 Subject: [PATCH 0194/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 590a91557..40a2c6efa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.2.3", + "version": "6.2.4", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 31ee7590fde0609136a592980ab71215a85d4046 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 9 Jun 2017 13:15:26 -0500 Subject: [PATCH 0195/1037] Deprecate pg.* singleton methods --- lib/index.js | 4 + package.json | 1 + test/test-helper.js | 2 + yarn.lock | 248 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 255 insertions(+) create mode 100644 yarn.lock diff --git a/lib/index.js b/lib/index.js index a2c2792f4..343819cd8 100644 --- a/lib/index.js +++ b/lib/index.js @@ -13,6 +13,7 @@ var defaults = require('./defaults'); var Connection = require('./connection'); var ConnectionParameters = require('./connection-parameters'); var poolFactory = require('./pool-factory'); +var deprecate = require('deprecate'); var PG = function(clientConstructor) { EventEmitter.call(this); @@ -28,6 +29,7 @@ var PG = function(clientConstructor) { util.inherits(PG, EventEmitter); PG.prototype.end = function() { + deprecate('pg.end() is deprecated - please construct pools directly via new pg.Pool()'); var self = this; var keys = Object.keys(this._pools); var count = keys.length; @@ -50,6 +52,7 @@ PG.prototype.end = function() { }; PG.prototype.connect = function(config, callback) { + deprecate('pg.connect() is deprecated - please construct pools directly via new pg.Pool()'); if(typeof config == "function") { callback = config; config = null; @@ -79,6 +82,7 @@ PG.prototype.connect = function(config, callback) { // cancel the query running on the given client PG.prototype.cancel = function(config, client, query) { + deprecate('pg.cancel() is deprecated - please create your own client instances to cancel queries'); if(client.native) { return client.cancel(query); } diff --git a/package.json b/package.json index d52ba05ca..b7fd9d0c9 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "main": "./lib", "dependencies": { "buffer-writer": "1.0.1", + "deprecate": "1.0.0", "packet-reader": "0.3.1", "pg-connection-string": "0.1.3", "pg-pool": "1.*", diff --git a/test/test-helper.js b/test/test-helper.js index 175cbbb9d..ad3e785b4 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -1,6 +1,8 @@ //make assert a global... assert = require('assert'); +require('deprecate').silence = true; + var EventEmitter = require('events').EventEmitter; var sys = require('util'); var BufferList = require(__dirname+'/buffer-list') diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..7a50d7e3f --- /dev/null +++ b/yarn.lock @@ -0,0 +1,248 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +ap@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" + +async@0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.0.tgz#ac3613b1da9bed1b47510bb4651b8931e47146c7" + +buffer-writer@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-1.0.1.tgz#22a936901e3029afcd7547eb4487ceb697a3bf08" + +cli@0.6.x: + version "0.6.6" + resolved "https://registry.yarnpkg.com/cli/-/cli-0.6.6.tgz#02ad44a380abf27adac5e6f0cdd7b043d74c53e3" + dependencies: + exit "0.1.2" + glob "~ 3.2.1" + +co@4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +console-browserify@1.1.x: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" + dependencies: + date-now "^0.1.4" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +date-now@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" + +deprecate@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/deprecate/-/deprecate-1.0.0.tgz#661490ed2428916a6c8883d8834e5646f4e4a4a8" + +dom-serializer@0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" + dependencies: + domelementtype "~1.1.1" + entities "~1.1.1" + +domelementtype@1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" + +domelementtype@~1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" + +domhandler@2.2: + version "2.2.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.2.1.tgz#59df9dcd227e808b365ae73e1f6684ac3d946fc2" + dependencies: + domelementtype "1" + +domutils@1.5: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + dependencies: + dom-serializer "0" + domelementtype "1" + +entities@1.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" + +entities@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" + +exit@0.1.2, exit@0.1.x: + version "0.1.2" + resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" + +generic-pool@2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.4.3.tgz#780c36f69dfad05a5a045dd37be7adca11a4f6ff" + +"glob@~ 3.2.1": + version "3.2.11" + resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" + dependencies: + inherits "2" + minimatch "0.3" + +htmlparser2@3.7.x: + version "3.7.3" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.7.3.tgz#6a64c77637c08c6f30ec2a8157a53333be7cb05e" + dependencies: + domelementtype "1" + domhandler "2.2" + domutils "1.5" + entities "1.0" + readable-stream "1.1" + +inherits@2, inherits@~2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + +jshint@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jshint/-/jshint-2.5.2.tgz#bec223d5149e49ef6ea96dcf8b3504a27613e8be" + dependencies: + cli "0.6.x" + console-browserify "1.1.x" + exit "0.1.x" + htmlparser2 "3.7.x" + minimatch "0.x.x" + shelljs "0.3.x" + strip-json-comments "0.1.x" + underscore "1.6.x" + +lru-cache@2: + version "2.7.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" + +minimatch@0.3: + version "0.3.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +minimatch@0.x.x: + version "0.4.0" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.4.0.tgz#bd2c7d060d2c8c8fd7cde7f1f2ed2d5b270fdb1b" + dependencies: + lru-cache "2" + sigmund "~1.0.0" + +object-assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" + +packet-reader@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.3.1.tgz#cd62e60af8d7fea8a705ec4ff990871c46871f27" + +pg-connection-string@0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" + +pg-copy-streams@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/pg-copy-streams/-/pg-copy-streams-0.3.0.tgz#a4fbc2a3b788d4e9da6f77ceb35422d8d7043b7f" + +pg-pool@1.*: + version "1.7.1" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-1.7.1.tgz#421105cb7469979dcc48d6fc4fe3fe4659437437" + dependencies: + generic-pool "2.4.3" + object-assign "4.1.0" + +pg-types@1.*: + version "1.12.0" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-1.12.0.tgz#8ad3b7b897e3fd463e62de241ad5fc640b4a66f0" + dependencies: + ap "~0.2.0" + postgres-array "~1.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.0" + postgres-interval "^1.1.0" + +pgpass@1.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" + dependencies: + split "^1.0.0" + +postgres-array@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-1.0.2.tgz#8e0b32eb03bf77a5c0a7851e0441c169a256a238" + +postgres-bytea@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + +postgres-date@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.3.tgz#e2d89702efdb258ff9d9cee0fe91bd06975257a8" + +postgres-interval@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.1.0.tgz#1031e7bac34564132862adc9eb6c6d2f3aa75bb4" + dependencies: + xtend "^4.0.0" + +readable-stream@1.1: + version "1.1.13" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.1" + isarray "0.0.1" + string_decoder "~0.10.x" + +semver@4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" + +shelljs@0.3.x: + version "0.3.0" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" + +sigmund@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + +split@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.0.tgz#c4395ce683abcd254bc28fe1dabb6e5c27dcffae" + dependencies: + through "2" + +string_decoder@~0.10.x: + version "0.10.31" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" + +strip-json-comments@0.1.x: + version "0.1.3" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-0.1.3.tgz#164c64e370a8a3cc00c9e01b539e569823f0ee54" + +through@2: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +underscore@1.6.x: + version "1.6.0" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8" + +xtend@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" From 272858ca57d67d5680394e560b845893da16f7d1 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 9 Jun 2017 13:52:41 -0500 Subject: [PATCH 0196/1037] Remove lockfile because yarn in travis is blowing up the tests --- yarn.lock | 248 ------------------------------------------------------ 1 file changed, 248 deletions(-) delete mode 100644 yarn.lock diff --git a/yarn.lock b/yarn.lock deleted file mode 100644 index 7a50d7e3f..000000000 --- a/yarn.lock +++ /dev/null @@ -1,248 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -ap@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" - -async@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/async/-/async-0.9.0.tgz#ac3613b1da9bed1b47510bb4651b8931e47146c7" - -buffer-writer@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-1.0.1.tgz#22a936901e3029afcd7547eb4487ceb697a3bf08" - -cli@0.6.x: - version "0.6.6" - resolved "https://registry.yarnpkg.com/cli/-/cli-0.6.6.tgz#02ad44a380abf27adac5e6f0cdd7b043d74c53e3" - dependencies: - exit "0.1.2" - glob "~ 3.2.1" - -co@4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -console-browserify@1.1.x: - version "1.1.0" - resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.1.0.tgz#f0241c45730a9fc6323b206dbf38edc741d0bb10" - dependencies: - date-now "^0.1.4" - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - -date-now@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b" - -deprecate@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/deprecate/-/deprecate-1.0.0.tgz#661490ed2428916a6c8883d8834e5646f4e4a4a8" - -dom-serializer@0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.0.tgz#073c697546ce0780ce23be4a28e293e40bc30c82" - dependencies: - domelementtype "~1.1.1" - entities "~1.1.1" - -domelementtype@1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.0.tgz#b17aed82e8ab59e52dd9c19b1756e0fc187204c2" - -domelementtype@~1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.1.3.tgz#bd28773e2642881aec51544924299c5cd822185b" - -domhandler@2.2: - version "2.2.1" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.2.1.tgz#59df9dcd227e808b365ae73e1f6684ac3d946fc2" - dependencies: - domelementtype "1" - -domutils@1.5: - version "1.5.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - dependencies: - dom-serializer "0" - domelementtype "1" - -entities@1.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.0.0.tgz#b2987aa3821347fcde642b24fdfc9e4fb712bf26" - -entities@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.1.tgz#6e5c2d0a5621b5dadaecef80b90edfb5cd7772f0" - -exit@0.1.2, exit@0.1.x: - version "0.1.2" - resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" - -generic-pool@2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.4.3.tgz#780c36f69dfad05a5a045dd37be7adca11a4f6ff" - -"glob@~ 3.2.1": - version "3.2.11" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" - dependencies: - inherits "2" - minimatch "0.3" - -htmlparser2@3.7.x: - version "3.7.3" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.7.3.tgz#6a64c77637c08c6f30ec2a8157a53333be7cb05e" - dependencies: - domelementtype "1" - domhandler "2.2" - domutils "1.5" - entities "1.0" - readable-stream "1.1" - -inherits@2, inherits@~2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - -jshint@2.5.2: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jshint/-/jshint-2.5.2.tgz#bec223d5149e49ef6ea96dcf8b3504a27613e8be" - dependencies: - cli "0.6.x" - console-browserify "1.1.x" - exit "0.1.x" - htmlparser2 "3.7.x" - minimatch "0.x.x" - shelljs "0.3.x" - strip-json-comments "0.1.x" - underscore "1.6.x" - -lru-cache@2: - version "2.7.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" - -minimatch@0.3: - version "0.3.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" - dependencies: - lru-cache "2" - sigmund "~1.0.0" - -minimatch@0.x.x: - version "0.4.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.4.0.tgz#bd2c7d060d2c8c8fd7cde7f1f2ed2d5b270fdb1b" - dependencies: - lru-cache "2" - sigmund "~1.0.0" - -object-assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" - -packet-reader@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.3.1.tgz#cd62e60af8d7fea8a705ec4ff990871c46871f27" - -pg-connection-string@0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" - -pg-copy-streams@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/pg-copy-streams/-/pg-copy-streams-0.3.0.tgz#a4fbc2a3b788d4e9da6f77ceb35422d8d7043b7f" - -pg-pool@1.*: - version "1.7.1" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-1.7.1.tgz#421105cb7469979dcc48d6fc4fe3fe4659437437" - dependencies: - generic-pool "2.4.3" - object-assign "4.1.0" - -pg-types@1.*: - version "1.12.0" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-1.12.0.tgz#8ad3b7b897e3fd463e62de241ad5fc640b4a66f0" - dependencies: - ap "~0.2.0" - postgres-array "~1.0.0" - postgres-bytea "~1.0.0" - postgres-date "~1.0.0" - postgres-interval "^1.1.0" - -pgpass@1.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" - dependencies: - split "^1.0.0" - -postgres-array@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-1.0.2.tgz#8e0b32eb03bf77a5c0a7851e0441c169a256a238" - -postgres-bytea@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" - -postgres-date@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.3.tgz#e2d89702efdb258ff9d9cee0fe91bd06975257a8" - -postgres-interval@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.1.0.tgz#1031e7bac34564132862adc9eb6c6d2f3aa75bb4" - dependencies: - xtend "^4.0.0" - -readable-stream@1.1: - version "1.1.13" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.13.tgz#f6eef764f514c89e2b9e23146a75ba106756d23e" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -semver@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" - -shelljs@0.3.x: - version "0.3.0" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.3.0.tgz#3596e6307a781544f591f37da618360f31db57b1" - -sigmund@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - -split@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.0.tgz#c4395ce683abcd254bc28fe1dabb6e5c27dcffae" - dependencies: - through "2" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - -strip-json-comments@0.1.x: - version "0.1.3" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-0.1.3.tgz#164c64e370a8a3cc00c9e01b539e569823f0ee54" - -through@2: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - -underscore@1.6.x: - version "1.6.0" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8" - -xtend@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" From bbbd6e99f9dc5755bda6168ba2157a9513d7f2d7 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 9 Jun 2017 15:15:13 -0500 Subject: [PATCH 0197/1037] Use built-in util.deprecate --- lib/index.js | 18 ++++++++---------- package.json | 1 - test/test-helper.js | 4 +--- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/lib/index.js b/lib/index.js index 343819cd8..a24397116 100644 --- a/lib/index.js +++ b/lib/index.js @@ -13,7 +13,6 @@ var defaults = require('./defaults'); var Connection = require('./connection'); var ConnectionParameters = require('./connection-parameters'); var poolFactory = require('./pool-factory'); -var deprecate = require('deprecate'); var PG = function(clientConstructor) { EventEmitter.call(this); @@ -28,8 +27,7 @@ var PG = function(clientConstructor) { util.inherits(PG, EventEmitter); -PG.prototype.end = function() { - deprecate('pg.end() is deprecated - please construct pools directly via new pg.Pool()'); +PG.prototype.end = util.deprecate(function() { var self = this; var keys = Object.keys(this._pools); var count = keys.length; @@ -49,10 +47,10 @@ PG.prototype.end = function() { }); }); } -}; +}, +'pg.end() is deprecated - please construct pools directly via new pg.Pool()'); -PG.prototype.connect = function(config, callback) { - deprecate('pg.connect() is deprecated - please construct pools directly via new pg.Pool()'); +PG.prototype.connect = util.deprecate(function(config, callback) { if(typeof config == "function") { callback = config; config = null; @@ -78,11 +76,11 @@ PG.prototype.connect = function(config, callback) { }.bind(this)); } return pool.connect(callback); -}; +}, +'pg.connect() is deprecated - please construct pools directly via new pg.Pool()'); // cancel the query running on the given client -PG.prototype.cancel = function(config, client, query) { - deprecate('pg.cancel() is deprecated - please create your own client instances to cancel queries'); +PG.prototype.cancel = util.deprecate(function(config, client, query) { if(client.native) { return client.cancel(query); } @@ -93,7 +91,7 @@ PG.prototype.cancel = function(config, client, query) { } var cancellingClient = new this.Client(c); cancellingClient.cancel(client, query); -}; +}, 'pg.cancel() is deprecated - please create your own client instances to cancel queries'); if(typeof process.env.NODE_PG_FORCE_NATIVE != 'undefined') { module.exports = new PG(require('./native')); diff --git a/package.json b/package.json index b7fd9d0c9..d52ba05ca 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,6 @@ "main": "./lib", "dependencies": { "buffer-writer": "1.0.1", - "deprecate": "1.0.0", "packet-reader": "0.3.1", "pg-connection-string": "0.1.3", "pg-pool": "1.*", diff --git a/test/test-helper.js b/test/test-helper.js index ad3e785b4..f39cbfef3 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -1,8 +1,6 @@ //make assert a global... assert = require('assert'); - -require('deprecate').silence = true; - +process.noDeprecation = true; var EventEmitter = require('events').EventEmitter; var sys = require('util'); var BufferList = require(__dirname+'/buffer-list') From 5421e9dc0fffbbf257a9249dc17e965422ebbcc8 Mon Sep 17 00:00:00 2001 From: Amila Welihinda Date: Sun, 11 Jun 2017 12:59:33 -0700 Subject: [PATCH 0198/1037] Added MIT License --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..11cda4c0a --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Brian C + +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. From bbb759fba41028fc2b6ddef43ffea35f4695b8ed Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 12 Jun 2017 09:47:39 -0500 Subject: [PATCH 0199/1037] Create LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 11cda4c0a..a7b546d2d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Brian C +Copyright (c) 2010 - 2017 Brian 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 From bc00f90c6a2a6502774b07a2ebabfd89231f408c Mon Sep 17 00:00:00 2001 From: Amila Welihinda Date: Sun, 11 Jun 2017 12:59:33 -0700 Subject: [PATCH 0200/1037] Added MIT License --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..11cda4c0a --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Brian C + +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. From 25a98f509999b36f5c9da2cf5e870f6ec7ab9be5 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 12 Jun 2017 09:47:39 -0500 Subject: [PATCH 0201/1037] Create LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 11cda4c0a..a7b546d2d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2017 Brian C +Copyright (c) 2010 - 2017 Brian 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 From 6d98b0847cf39ff327ce45c663ee4230d7b9104a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 9 Jun 2017 16:35:01 -0500 Subject: [PATCH 0202/1037] Actual promisification of client.query --- lib/client.js | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/lib/client.js b/lib/client.js index 9fb2f8b10..d489ff8d7 100644 --- a/lib/client.js +++ b/lib/client.js @@ -349,19 +349,37 @@ Client.prototype.copyTo = function (text) { }; Client.prototype.query = function(config, values, callback) { - //can take in strings, config object or query object - var query = (typeof config.submit == 'function') ? config : - new Query(config, values, callback); + var promise; + var isQueryable = typeof config.submit == 'function'; + var query; + // if we receive an object with a 'submit' function we delegate + // processing to the passed object - this is how pg.Query, QueryStream, and Cursor work + if (isQueryable) { + query = config; + } else { + query = new Query(config, values, callback); + if (!query.callback) { + promise = new global.Promise(function (resolve, reject) { + query.on('error', reject); + query.on('end', resolve); + }); + } + } if(this.binary && !query.binary) { query.binary = true; } + + // TODO - this is a smell if(query._result) { query._result._getTypeParser = this._types.getTypeParser.bind(this._types); } this.queryQueue.push(query); this._pulseQueryQueue(); - return query; + + // if we were passed a queryable, return it + // otherwise return callback/promise result + return isQueryable ? query : promise; }; Client.prototype.end = function(cb) { From 96b7fc38a60e289d0e6e4029e563f6e1d43640b1 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 10 Jun 2017 09:40:17 -0500 Subject: [PATCH 0203/1037] Fix unit tests --- test/unit/client/prepared-statement-tests.js | 7 ++++--- test/unit/client/result-metadata-tests.js | 8 +++----- test/unit/client/simple-query-tests.js | 3 ++- test/unit/client/throw-in-type-parser-tests.js | 8 ++++---- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/test/unit/client/prepared-statement-tests.js b/test/unit/client/prepared-statement-tests.js index 6e26c7967..460cbf95d 100644 --- a/test/unit/client/prepared-statement-tests.js +++ b/test/unit/client/prepared-statement-tests.js @@ -1,4 +1,5 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); +var Query = require('../../../lib/query') var client = helper.client(); var con = client.connection; @@ -49,10 +50,10 @@ test('bound command', function() { test('simple, unnamed bound command', function() { assert.ok(client.connection.emit('readyForQuery')); - var query = client.query({ + var query = client.query(new Query({ text: 'select * from X where name = $1', values: ['hi'] - }); + })); assert.emits(query,'end', function() { test('parse argument', function() { diff --git a/test/unit/client/result-metadata-tests.js b/test/unit/client/result-metadata-tests.js index 435af25bf..5f349b57f 100644 --- a/test/unit/client/result-metadata-tests.js +++ b/test/unit/client/result-metadata-tests.js @@ -6,13 +6,11 @@ var testForTag = function(tagText, callback) { var client = helper.client(); client.connection.emit('readyForQuery') - var query = client.query("whatever"); - assert.lengthIs(client.connection.queries, 1) - - assert.emits(query, 'end', function(result) { + var query = client.query("whatever", assert.calls((err, result) => { assert.ok(result != null, "should pass something to this event") callback(result) - }) + })); + assert.lengthIs(client.connection.queries, 1) client.connection.emit('commandComplete', { text: tagText diff --git a/test/unit/client/simple-query-tests.js b/test/unit/client/simple-query-tests.js index 19f05c186..df71faed5 100644 --- a/test/unit/client/simple-query-tests.js +++ b/test/unit/client/simple-query-tests.js @@ -1,4 +1,5 @@ var helper = require(__dirname + "/test-helper"); +var Query = require('../../../lib/query') test('executing query', function() { @@ -64,7 +65,7 @@ test('executing query', function() { test("query event binding and flow", function() { var client = helper.client(); var con = client.connection; - var query = client.query('whatever'); + var query = client.query(new Query('whatever')); test("has no queries sent before ready", function() { assert.empty(con.queries); diff --git a/test/unit/client/throw-in-type-parser-tests.js b/test/unit/client/throw-in-type-parser-tests.js index ed3711376..37a272aa0 100644 --- a/test/unit/client/throw-in-type-parser-tests.js +++ b/test/unit/client/throw-in-type-parser-tests.js @@ -1,4 +1,5 @@ -var helper = require(__dirname + "/test-helper"); +var helper = require("./test-helper"); +var Query = require('../../../lib/query') var types = require('pg-types') test('handles throws in type parsers', function() { @@ -12,7 +13,7 @@ test('handles throws in type parsers', function() { var handled; var client = helper.client(); var con = client.connection; - var query = client.query('whatever'); + var query = client.query(new Query('whatever')); handled = con.emit('readyForQuery'); assert.ok(handled, "should have handled ready for query"); @@ -81,8 +82,7 @@ test('handles throws in type parsers', function() { var handled; var client = helper.client(); var con = client.connection; - var query = client.query('whatever'); - var queryPromise = query.promise(); + var queryPromise = client.query('whatever'); handled = con.emit('readyForQuery'); assert.ok(handled, "should have handled ready for query"); From 2f3d72a28ce58429e432578c0df7ec489643038d Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 10 Jun 2017 10:02:33 -0500 Subject: [PATCH 0204/1037] Start fixing integration tests --- script/create-test-tables.js | 9 ++---- test/integration/client/array-tests.js | 8 ++--- .../client/error-handling-tests.js | 31 +++++-------------- .../client/query-error-handling-tests.js | 8 +++-- test/integration/gh-issues/131-tests.js | 2 +- 5 files changed, 21 insertions(+), 37 deletions(-) diff --git a/script/create-test-tables.js b/script/create-test-tables.js index fa5d1b6e5..6a569f2a2 100644 --- a/script/create-test-tables.js +++ b/script/create-test-tables.js @@ -39,15 +39,12 @@ var con = new pg.Client({ }); con.connect(); var query = con.query("drop table if exists person"); -query.on('end', function() { - console.log("Dropped table 'person'") -}); -con.query("create table person(id serial, name varchar(10), age integer)").on('end', function(){ +con.query("create table person(id serial, name varchar(10), age integer)", (err, res) => { console.log("Created table person"); console.log("Filling it with people"); -}); +}) people.map(function(person) { - return con.query("insert into person(name, age) values('"+person.name + "', '" + person.age + "')"); + return con.query(new pg.Query("insert into person(name, age) values('"+person.name + "', '" + person.age + "')")); }).pop().on('end', function(){ console.log("Inserted 26 people"); con.end(); diff --git a/test/integration/client/array-tests.js b/test/integration/client/array-tests.js index 2525b8a23..937ea17ba 100644 --- a/test/integration/client/array-tests.js +++ b/test/integration/client/array-tests.js @@ -35,7 +35,7 @@ test('parsing array results', function() { pg.connect(helper.config, assert.calls(function(err, client, done) { assert.isNull(err); client.query("CREATE TEMP TABLE why(names text[], numbors integer[])"); - client.query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')').on('error', console.log); + client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log); test('numbers', function() { // client.connection.on('message', console.log) client.query('SELECT numbors FROM why', assert.success(function(result) { @@ -55,7 +55,7 @@ test('parsing array results', function() { assert.equal(names[2], "a b c"); })) }) - + test('empty array', function(){ client.query("SELECT '{}'::text[] as names", assert.success(function(result) { var names = result.rows[0].names; @@ -142,7 +142,7 @@ test('parsing array results', function() { assert.equal(names[2][1], 100); })) }) - + test('JS array parameter', function(){ client.query("SELECT $1::integer[] as names", [[[1,100],[2,100],[3,100]]], assert.success(function(result) { var names = result.rows[0].names; @@ -159,7 +159,7 @@ test('parsing array results', function() { pg.end(); })) }) - + })) }) diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 3fcd305bb..d66fb6111 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -1,23 +1,8 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); var util = require('util'); +const { pg } = helper - test('non-query error with callback', function () { - var client = new Client({ - user:'asldkfjsadlfkj' - }); - client.connect(assert.calls(function (err) { - assert(err); - })); - }); - - test('non-query error', function() { - var client = new Client({ - user:'asldkfjsadlfkj' - }); - assert.emits(client, 'error'); - client.connect(); - }); var createErorrClient = function() { var client = helper.client(); @@ -33,7 +18,7 @@ test('error handling', function() { test('within a simple query', function() { var client = createErorrClient(); - var query = client.query("select omfg from yodas_dsflsd where pixistix = 'zoiks!!!'"); + var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")); assert.emits(query, 'error', function(error) { assert.equal(error.severity, "ERROR"); @@ -52,17 +37,17 @@ test('error handling', function() { var ensureFuture = function(testClient) { test("client can issue more queries successfully", function() { - var goodQuery = testClient.query("select age from boom"); + var goodQuery = testClient.query(new pg.Query("select age from boom")); assert.emits(goodQuery, 'row', function(row) { assert.equal(row.age, 28); }); }); }; - var query = client.query({ + var query = client.query(new pg.Query({ text: "select * from bang where name = $1", values: ['0'] - }); + })); test("query emits the error", function() { assert.emits(query, 'error', function(err) { @@ -72,10 +57,10 @@ test('error handling', function() { test("when a query is binding", function() { - var query = client.query({ + var query = client.query(new pg.Query({ text: 'select * from boom where age = $1', values: ['asldkfjasdf'] - }); + })); test("query emits the error", function() { diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js index 2618a49df..3eba4b11e 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -1,10 +1,11 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); var util = require('util'); +const { Query } = helper.pg; test('error during query execution', function() { var client = new Client(helper.args); client.connect(assert.success(function() { - var sleepQuery = 'select pg_sleep(5)'; + var sleepQuery = new Query('select pg_sleep(5)'); var pidColName = 'procpid' var queryColName = 'current_query'; helper.versionGTE(client, '9.2.0', assert.success(function(isGreater) { @@ -27,13 +28,14 @@ test('error during query execution', function() { client2.connect(assert.success(function() { var killIdleQuery = "SELECT " + pidColName + ", (SELECT pg_terminate_backend(" + pidColName + ")) AS killed FROM pg_stat_activity WHERE " + queryColName + " = $1"; client2.query(killIdleQuery, [sleepQuery], assert.calls(function(err, res) { + console.log('\nresult', res) assert.ifError(err); assert.equal(res.rows.length, 1); client2.end(); assert.emits(client2, 'end'); })); })); - }, 100) + }, 300) })); })); }); diff --git a/test/integration/gh-issues/131-tests.js b/test/integration/gh-issues/131-tests.js index eee5086a6..f733ea705 100644 --- a/test/integration/gh-issues/131-tests.js +++ b/test/integration/gh-issues/131-tests.js @@ -5,7 +5,7 @@ test('parsing array results', function() { pg.connect(helper.config, assert.calls(function(err, client, done) { assert.isNull(err); client.query("CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])"); - client.query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')').on('error', console.log); + client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log); test('decimals', function() { client.query('SELECT decimals FROM why', assert.success(function(result) { assert.lengthIs(result.rows[0].decimals, 3); From b8c2bebcaca895d7803ebb9b86364675bd9147a2 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 10 Jun 2017 16:29:00 -0500 Subject: [PATCH 0205/1037] Fix more tests to use query instance --- lib/client.js | 4 + .../client/big-simple-query-tests.js | 18 +-- test/integration/client/cancel-query-tests.js | 11 +- .../client/error-handling-tests.js | 2 +- test/integration/client/no-data-tests.js | 11 +- .../integration/client/no-row-result-tests.js | 4 +- .../client/prepared-statement-tests.js | 104 +++++------------- ...error-handling-prepared-statement-tests.js | 10 +- .../client/query-error-handling-tests.js | 10 +- .../client/result-metadata-tests.js | 8 +- .../client/results-as-array-tests.js | 3 - test/integration/client/simple-query-tests.js | 33 ++---- .../integration/client/type-coercion-tests.js | 9 +- .../connection-pool/test-helper.js | 4 +- 14 files changed, 75 insertions(+), 156 deletions(-) diff --git a/lib/client.js b/lib/client.js index d489ff8d7..32ea76b95 100644 --- a/lib/client.js +++ b/lib/client.js @@ -356,6 +356,10 @@ Client.prototype.query = function(config, values, callback) { // processing to the passed object - this is how pg.Query, QueryStream, and Cursor work if (isQueryable) { query = config; + // accept client.query(new Query('select *'), (err, res) => { }) call signature + if (typeof values == 'function') { + query.callback = query.callback || values; + } } else { query = new Query(config, values, callback); if (!query.callback) { diff --git a/test/integration/client/big-simple-query-tests.js b/test/integration/client/big-simple-query-tests.js index cf6cdbf70..514babe63 100644 --- a/test/integration/client/big-simple-query-tests.js +++ b/test/integration/client/big-simple-query-tests.js @@ -1,4 +1,5 @@ -var helper = require(__dirname+"/test-helper"); +var helper = require("./test-helper"); +var Query = helper.pg.Query /* Test to trigger a bug. @@ -15,7 +16,7 @@ var big_query_rows_3 = []; // Works test('big simple query 1',function() { var client = helper.client(); - client.query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = '' or 1 = 1") + client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = '' or 1 = 1")) .on('row', function(row) { big_query_rows_1.push(row); }) .on('error', function(error) { console.log("big simple query 1 error"); console.log(error); }); client.on('drain', client.end.bind(client)); @@ -24,7 +25,7 @@ test('big simple query 1',function() { // Works test('big simple query 2',function() { var client = helper.client(); - client.query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",['']) + client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",[''])) .on('row', function(row) { big_query_rows_2.push(row); }) .on('error', function(error) { console.log("big simple query 2 error"); console.log(error); }); client.on('drain', client.end.bind(client)); @@ -34,7 +35,7 @@ test('big simple query 2',function() { // If test 1 and 2 are commented out it works test('big simple query 3',function() { var client = helper.client(); - client.query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",['']) + client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",[''])) .on('row', function(row) { big_query_rows_3.push(row); }) .on('error', function(error) { console.log("big simple query 3 error"); console.log(error); }); client.on('drain', client.end.bind(client)); @@ -56,19 +57,12 @@ var runBigQuery = function(client) { } assert.lengthIs(result.rows, 26); }); - q.on('row', function(row) { - rows.push(row); - }) - assert.emits(q, 'end', function() { - //query ended - assert.lengthIs(rows, 26); - }) } test('many times', function() { var client = helper.client(); for(var i = 0; i < 20; i++) { - runBigQuery(client); + runBigQuery(client); } client.on('drain', function() { client.end(); diff --git a/test/integration/client/cancel-query-tests.js b/test/integration/client/cancel-query-tests.js index b6c0c7f4d..0275fa898 100644 --- a/test/integration/client/cancel-query-tests.js +++ b/test/integration/client/cancel-query-tests.js @@ -1,4 +1,5 @@ -var helper = require(__dirname+"/test-helper"); +var helper = require("./test-helper"); +var Query = helper.pg.Query; //before running this test make sure you run the script create-test-tables test("cancellation of a query", function() { @@ -11,19 +12,19 @@ test("cancellation of a query", function() { var rows3 = 0; - var query1 = client.query(qry); + var query1 = client.query(new Query(qry)); query1.on('row', function(row) { throw new Error('Should not emit a row') }); - var query2 = client.query(qry); + var query2 = client.query(new Query(qry)); query2.on('row', function(row) { throw new Error('Should not emit a row') }); - var query3 = client.query(qry); + var query3 = client.query(new Query(qry)); query3.on('row', function(row) { rows3++; }); - var query4 = client.query(qry); + var query4 = client.query(new Query(qry)); query4.on('row', function(row) { throw new Error('Should not emit a row') }); diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index d66fb6111..08e78b333 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -1,7 +1,7 @@ var helper = require('./test-helper'); var util = require('util'); -const { pg } = helper +var pg = helper.pg var createErorrClient = function() { diff --git a/test/integration/client/no-data-tests.js b/test/integration/client/no-data-tests.js index 341d72870..3258e6a57 100644 --- a/test/integration/client/no-data-tests.js +++ b/test/integration/client/no-data-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); test("noData message handling", function() { @@ -22,7 +22,6 @@ test("noData message handling", function() { client.query({ name: 'insert', - text: 'insert into boom(size) values($1)', values: [101] }); @@ -30,12 +29,10 @@ test("noData message handling", function() { name: 'fetch', text: 'select size from boom where size < $1', values: [101] - }); - - assert.emits(query, 'row', function(row) { - assert.strictEqual(row.size,100) + }, (err, res) => { + var row = res.rows[0] + assert.strictEqual(row.size, 100) }); client.on('drain', client.end.bind(client)); - }); diff --git a/test/integration/client/no-row-result-tests.js b/test/integration/client/no-row-result-tests.js index 5555ff6f2..1929b1624 100644 --- a/test/integration/client/no-row-result-tests.js +++ b/test/integration/client/no-row-result-tests.js @@ -3,6 +3,7 @@ var pg = helper.pg; var config = helper.config; test('can access results when no rows are returned', function() { + console.log('maybe fix this?', __filename) if(config.native) return false; var checkResult = function(result) { assert(result.fields, 'should have fields definition'); @@ -13,7 +14,8 @@ test('can access results when no rows are returned', function() { }; pg.connect(config, assert.success(function(client, done) { - var query = client.query('select $1::text as val limit 0', ['hi'], assert.success(function(result) { + const q = new pg.Query('select $1::text as val limit 0', ['hi']) + var query = client.query(q, assert.success(function(result) { checkResult(result); done(); })); diff --git a/test/integration/client/prepared-statement-tests.js b/test/integration/client/prepared-statement-tests.js index 478cd007c..9735407a9 100644 --- a/test/integration/client/prepared-statement-tests.js +++ b/test/integration/client/prepared-statement-tests.js @@ -1,48 +1,5 @@ -var helper = require(__dirname +'/test-helper'); - -test("simple, unnamed prepared statement", function(){ - var client = helper.client(); - - var query = client.query({ - text: 'select age from person where name = $1', - values: ['Brian'] - }); - - assert.emits(query, 'row', function(row) { - assert.equal(row.age, 20); - }); - - assert.emits(query, 'end', function() { - client.end(); - }); -}); - -test("use interval in prepared statement", function(){ - return; - var client = helper.client(); - - client.query('SELECT interval \'15 days 2 months 3 years 6:12:05\' as interval', assert.success(function(result) { - var interval = result.rows[0].interval; - - var query = client.query({ - text: 'select cast($1 as interval) as interval', - values: [interval] - }); - - assert.emits(query, 'row', function(row) { - assert.equal(row.interval.seconds, 5); - assert.equal(row.interval.minutes, 12); - assert.equal(row.interval.hours, 6); - assert.equal(row.interval.days, 15); - assert.equal(row.interval.months, 2); - assert.equal(row.interval.years, 3); - }); - - assert.emits(query, 'end', function() { - client.end(); - }); - })); -}); +var helper = require('./test-helper'); +var Query = helper.pg.Query; test("named prepared statement", function() { @@ -52,12 +9,12 @@ test("named prepared statement", function() { var queryName = "user by age and like name"; var parseCount = 0; - test("first named prepared statement",function() { - var query = client.query({ + test("first named prepared statement", function() { + var query = client.query(new Query({ text: 'select name from person where age <= $1 and name LIKE $2', values: [20, 'Bri%'], name: queryName - }); + })); assert.emits(query, 'row', function(row) { assert.equal(row.name, 'Brian'); @@ -68,11 +25,11 @@ test("named prepared statement", function() { }); test("second named prepared statement with same name & text", function() { - var cachedQuery = client.query({ + var cachedQuery = client.query(new Query({ text: 'select name from person where age <= $1 and name LIKE $2', name: queryName, values: [10, 'A%'] - }); + })); assert.emits(cachedQuery, 'row', function(row) { assert.equal(row.name, 'Aaron'); @@ -82,28 +39,22 @@ test("named prepared statement", function() { }); }); - test("with same name, but the query text not even there batman!", function() { - var q = client.query({ + test("with same name, but without query text", function() { + var q = client.query(new Query({ name: queryName, values: [30, '%n%'] - }); - - test("gets first row", function() { - assert.emits(q, 'row', function(row) { - assert.equal(row.name, "Aaron"); + })); - test("gets second row", function() { - assert.emits(q, 'row', function(row) { - assert.equal(row.name, "Brian"); - }); - }); + assert.emits(q, 'row', function(row) { + assert.equal(row.name, "Aaron"); + // test second row is emitted as well + assert.emits(q, 'row', function(row) { + assert.equal(row.name, "Brian"); }); }); - assert.emits(q, 'end', function() { - - }); + assert.emits(q, 'end', function() { }); }); }); @@ -124,14 +75,9 @@ test("prepared statements on different clients", function() { var query = client1.query({ name: statementName, text: statement1 - }); - test('gets right data back', function() { - assert.emits(query, 'row', function(row) { - assert.equal(row.count, 26); - }); - }); - - assert.emits(query, 'end', function() { + }, (err, res) => { + assert(!err); + assert.equal(res.rows[0].count, 26); if(client2Finished) { client1.end(); client2.end(); @@ -143,11 +89,11 @@ test("prepared statements on different clients", function() { }); test('client 2 execution', function() { - var query = client2.query({ + var query = client2.query(new Query({ name: statementName, text: statement2, values: [11] - }); + })); test('gets right data', function() { assert.emits(query, 'row', function(row) { @@ -192,22 +138,22 @@ test('prepared statement', function() { }; test('with small row count', function() { - var query = client.query({ + var query = client.query(new Query({ name: 'get names', text: "SELECT name FROM zoom ORDER BY name", rows: 1 - }); + })); checkForResults(query); }) test('with large row count', function() { - var query = client.query({ + var query = client.query(new Query({ name: 'get names', text: 'SELECT name FROM zoom ORDER BY name', rows: 1000 - }) + })) checkForResults(query); }) diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index 77615ff3a..5f27e5a41 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -1,4 +1,5 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); +var Query = helper.pg.Query; var util = require('util'); function killIdleQuery(targetQuery) { @@ -39,7 +40,7 @@ test('query killed during query execution of prepared statement', function() { // client should emit an error because it is unexpectedly disconnected assert.emits(client, 'error') - var query1 = client.query(queryConfig, assert.calls(function(err, result) { + var query1 = client.query(new Query(queryConfig), assert.calls(function(err, result) { assert.equal(err.message, 'terminating connection due to administrator command'); })); @@ -63,13 +64,14 @@ test('client end during query execution of prepared statement', function() { var client = new Client(helper.args); client.connect(assert.success(function() { var sleepQuery = 'select pg_sleep($1)'; - var query1 = client.query({ + var query1 = client.query(new Query({ name: 'sleep query', text: sleepQuery, values: [5] }, assert.calls(function(err, result) { assert.equal(err.message, 'Connection terminated'); - })); + }))); + query1.on('error', function(err) { assert.fail('Prepared statement should not emit error'); diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js index 3eba4b11e..53b590419 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -1,11 +1,12 @@ var helper = require('./test-helper'); var util = require('util'); -const { Query } = helper.pg; +var Query = helper.pg.Query; test('error during query execution', function() { var client = new Client(helper.args); client.connect(assert.success(function() { - var sleepQuery = new Query('select pg_sleep(5)'); + var queryText = 'select pg_sleep(5)' + var sleepQuery = new Query(queryText); var pidColName = 'procpid' var queryColName = 'current_query'; helper.versionGTE(client, '9.2.0', assert.success(function(isGreater) { @@ -26,9 +27,8 @@ test('error during query execution', function() { setTimeout(function() { var client2 = new Client(helper.args); client2.connect(assert.success(function() { - var killIdleQuery = "SELECT " + pidColName + ", (SELECT pg_terminate_backend(" + pidColName + ")) AS killed FROM pg_stat_activity WHERE " + queryColName + " = $1"; - client2.query(killIdleQuery, [sleepQuery], assert.calls(function(err, res) { - console.log('\nresult', res) + var killIdleQuery = `SELECT ${pidColName}, (SELECT pg_cancel_backend(${pidColName})) AS killed FROM pg_stat_activity WHERE ${queryColName} LIKE $1`; + client2.query(killIdleQuery, [queryText], assert.calls(function(err, res) { assert.ifError(err); assert.equal(res.rows.length, 1); client2.end(); diff --git a/test/integration/client/result-metadata-tests.js b/test/integration/client/result-metadata-tests.js index 013630033..221db7763 100644 --- a/test/integration/client/result-metadata-tests.js +++ b/test/integration/client/result-metadata-tests.js @@ -20,16 +20,10 @@ test('should return insert metadata', function() { assert.isNull(err); if(hasRowCount) assert.equal(result.rowCount, 1); assert.equal(result.command, 'SELECT'); + done(); process.nextTick(pg.end.bind(pg)); })); })); - - assert.emits(q, 'end', function(result) { - assert.equal(result.command, "INSERT"); - if(hasRowCount) assert.equal(result.rowCount, 1); - done(); - }); - })); })); })); diff --git a/test/integration/client/results-as-array-tests.js b/test/integration/client/results-as-array-tests.js index ef11a891c..1a1d8edfc 100644 --- a/test/integration/client/results-as-array-tests.js +++ b/test/integration/client/results-as-array-tests.js @@ -26,8 +26,5 @@ test('returns results as array', function() { checkRow(result.rows[0]); client.end(); })); - assert.emits(query, 'row', function(row) { - checkRow(row); - }); })); }); diff --git a/test/integration/client/simple-query-tests.js b/test/integration/client/simple-query-tests.js index e7ffc04a0..9453f159d 100644 --- a/test/integration/client/simple-query-tests.js +++ b/test/integration/client/simple-query-tests.js @@ -1,10 +1,12 @@ -var helper = require(__dirname+"/test-helper"); +var helper = require("./test-helper"); +var Query = helper.pg.Query; + //before running this test make sure you run the script create-test-tables test("simple query interface", function() { var client = helper.client(); - var query = client.query("select name from person order by name"); + var query = client.query(new Query("select name from person order by name")); client.on('drain', client.end.bind(client)); @@ -36,34 +38,13 @@ test("simple query interface", function() { }); }); -test("simple query interface using addRow", function() { - - var client = helper.client(); - - var query = client.query("select name from person order by name"); - - client.on('drain', client.end.bind(client)); - - query.on('row', function(row, result) { - assert.ok(result); - result.addRow(row); - }); - - query.on('end', function(result) { - assert.lengthIs(result.rows, 26, "result returned wrong number of rows"); - assert.lengthIs(result.rows, result.rowCount); - assert.equal(result.rows[0].name, "Aaron"); - assert.equal(result.rows[25].name, "Zanzabar"); - }); -}); - test("prepared statements do not mutate params", function() { var client = helper.client(); var params = [1] - var query = client.query("select name from person where $1 = 1 order by name", params); + var query = client.query(new Query("select name from person where $1 = 1 order by name", params)); assert.deepEqual(params, [1]) @@ -86,7 +67,7 @@ test("multiple simple queries", function() { var client = helper.client(); client.query({ text: "create temp table bang(id serial, name varchar(5));insert into bang(name) VALUES('boom');"}) client.query("insert into bang(name) VALUES ('yes');"); - var query = client.query("select name from bang"); + var query = client.query(new Query("select name from bang")); assert.emits(query, 'row', function(row) { assert.equal(row['name'], 'boom'); assert.emits(query, 'row', function(row) { @@ -100,7 +81,7 @@ test("multiple select statements", function() { var client = helper.client(); client.query("create temp table boom(age integer); insert into boom(age) values(1); insert into boom(age) values(2); insert into boom(age) values(3)"); client.query({text: "create temp table bang(name varchar(5)); insert into bang(name) values('zoom');"}); - var result = client.query({text: "select age from boom where age < 2; select name from bang"}); + var result = client.query(new Query({text: "select age from boom where age < 2; select name from bang"})); assert.emits(result, 'row', function(row) { assert.strictEqual(row['age'], 1); assert.emits(result, 'row', function(row) { diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index d961c291d..98f3148ae 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -1,4 +1,5 @@ var helper = require(__dirname + '/test-helper'); +var pg = helper.pg; var sink; var testForTypeCoercion = function(type){ @@ -13,10 +14,10 @@ var testForTypeCoercion = function(type){ assert.isNull(err); })); - var query = client.query({ + var query = client.query(new pg.Query({ name: 'get type ' + type.name , text: 'select col from test_type' - }); + })); query.on('error', function(err) { console.log(err); throw err; @@ -128,11 +129,11 @@ test("timestampz round trip", function() { name: 'add date', values: ['now', now] }); - var result = client.query({ + var result = client.query(new pg.Query({ name: 'get date', text: 'select * from date_tests where name = $1', values: ['now'] - }); + })); assert.emits(result, 'row', function(row) { var date = row.tstz; diff --git a/test/integration/connection-pool/test-helper.js b/test/integration/connection-pool/test-helper.js index 199407cd5..e4a3e4259 100644 --- a/test/integration/connection-pool/test-helper.js +++ b/test/integration/connection-pool/test-helper.js @@ -17,8 +17,8 @@ helper.testPoolSize = function(max) { client.query("select count(*) as c from person", function(err, result) { assert.equal(result.rows[0].c, 26) }) - var query = client.query("SELECT * FROM NOW()") - query.on('end',function() { + var query = client.query("SELECT * FROM NOW()", (err) => { + assert(!err) sink.add(); done(); }) From e284cfc110da5b86930636765a243bf0fa775932 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 10 Jun 2017 16:47:33 -0500 Subject: [PATCH 0206/1037] Make all integration tests pass --- test/integration/domain-tests.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/integration/domain-tests.js b/test/integration/domain-tests.js index a51f13dda..c3beae52a 100644 --- a/test/integration/domain-tests.js +++ b/test/integration/domain-tests.js @@ -1,6 +1,8 @@ -var helper = require('./test-helper') var async = require('async') +var helper = require('./test-helper') +var Query = helper.pg.Query + var testWithoutDomain = function(cb) { test('no domain', function() { assert(!process.domain) @@ -42,7 +44,7 @@ var testErrorWithDomain = function(cb) { }) domain.run(function() { helper.pg.connect(helper.config, assert.success(function(client, done) { - client.query('SELECT SLDKJFLSKDJF') + client.query(new Query('SELECT SLDKJFLSKDJF')) client.on('drain', done) })) }) From 2add7e3407e8fb97f16f12ba4369d5c0a1db4ff5 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 12 Jun 2017 18:32:34 -0500 Subject: [PATCH 0207/1037] Make almost all tests pass --- lib/native/index.js | 29 ++++++++++++------- lib/native/query.js | 28 +++++++++++------- .../integration/client/no-row-result-tests.js | 6 ++-- test/integration/gh-issues/131-tests.js | 10 +++---- 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/lib/native/index.js b/lib/native/index.js index 1e192e8bf..39bdefff8 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -46,6 +46,8 @@ var Client = module.exports = function(config) { this.namedQueries = {}; }; +Client.Query = NativeQuery; + util.inherits(Client, EventEmitter); //connect to the backend @@ -106,34 +108,41 @@ Client.prototype.connect = function(cb) { // optional string rowMode = 'array' for an array of results // } Client.prototype.query = function(config, values, callback) { - var query = new NativeQuery(this.native); + if (typeof config.submit == 'function') { + this._queryQueue.push(config); + this._pulseQueryQueue(); + return config; + } + + var conf = { }; //support query('text', ...) style calls if(typeof config == 'string') { - query.text = config; + conf.text = config; } //support passing everything in via a config object if(typeof config == 'object') { - query.text = config.text; - query.values = config.values; - query.name = config.name; - query.callback = config.callback; - query._arrayMode = config.rowMode == 'array'; + conf.text = config.text; + conf.values = config.values; + conf.name = config.name; + conf.callback = config.callback; + conf.rowMode = config.rowMode; } //support query({...}, function() {}) style calls //& support query(..., ['values'], ...) style calls if(typeof values == 'function') { - query.callback = values; + conf.callback = values; } else if(util.isArray(values)) { - query.values = values; + conf.values = values; } if(typeof callback == 'function') { - query.callback = callback; + conf.callback = callback; } + var query = new NativeQuery(conf); this._queryQueue.push(query); this._pulseQueryQueue(); return query; diff --git a/lib/native/query.js b/lib/native/query.js index a827af73e..5d6b5881e 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -11,15 +11,20 @@ var util = require('util'); var utils = require('../utils'); var NativeResult = require('./result'); -var NativeQuery = module.exports = function(native) { +var NativeQuery = module.exports = function(config, values) { EventEmitter.call(this); - this.native = native; - this.text = null; - this.values = null; - this.name = null; - this.callback = null; + if (typeof config == 'string') { + config = { + text: config, + values: values, + }; + } + this.text = config.text; + this.values = config.values; + this.name = config.name; + this.callback = config.callback; this.state = 'new'; - this._arrayMode = false; + this._arrayMode = config.rowMode == 'array'; //if the 'row' event is listened for //then emit them as they come in @@ -87,6 +92,7 @@ NativeQuery.prototype.handleError = function(err) { NativeQuery.prototype.submit = function(client) { this.state = 'running'; var self = this; + this.native = client.native; client.native.arrayMode = this._arrayMode; var after = function(err, rows) { @@ -136,10 +142,10 @@ NativeQuery.prototype.submit = function(client) { //check if the client has already executed this named query //if so...just execute it again - skip the planning phase if(client.namedQueries[this.name]) { - return this.native.execute(this.name, values, after); + return client.native.execute(this.name, values, after); } //plan the named query the first time, then execute it - return this.native.prepare(this.name, this.text, values.length, function(err) { + return client.native.prepare(this.name, this.text, values.length, function(err) { if(err) return after(err); client.namedQueries[self.name] = true; return self.native.execute(self.name, values, after); @@ -147,8 +153,8 @@ NativeQuery.prototype.submit = function(client) { } else if(this.values) { var vals = this.values.map(utils.prepareValue); - this.native.query(this.text, vals, after); + client.native.query(this.text, vals, after); } else { - this.native.query(this.text, after); + client.native.query(this.text, after); } }; diff --git a/test/integration/client/no-row-result-tests.js b/test/integration/client/no-row-result-tests.js index 1929b1624..99ed0da7a 100644 --- a/test/integration/client/no-row-result-tests.js +++ b/test/integration/client/no-row-result-tests.js @@ -3,8 +3,10 @@ var pg = helper.pg; var config = helper.config; test('can access results when no rows are returned', function() { - console.log('maybe fix this?', __filename) - if(config.native) return false; + if(config.native) { + console.log('maybe fix this?', __filename) + return false + } var checkResult = function(result) { assert(result.fields, 'should have fields definition'); assert.equal(result.fields.length, 1); diff --git a/test/integration/gh-issues/131-tests.js b/test/integration/gh-issues/131-tests.js index f733ea705..62bad27c2 100644 --- a/test/integration/gh-issues/131-tests.js +++ b/test/integration/gh-issues/131-tests.js @@ -1,13 +1,13 @@ -var helper = require(__dirname + "/../test-helper"); +var helper = require('../test-helper'); var pg = helper.pg; -test('parsing array results', function() { - pg.connect(helper.config, assert.calls(function(err, client, done) { +test('parsing array results', function () { + pg.connect(helper.config, assert.calls(function (err, client, done) { assert.isNull(err); client.query("CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])"); client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log); - test('decimals', function() { - client.query('SELECT decimals FROM why', assert.success(function(result) { + test('decimals', function () { + client.query('SELECT decimals FROM why', assert.success(function (result) { assert.lengthIs(result.rows[0].decimals, 3); assert.equal(result.rows[0].decimals[0], 0.1); assert.equal(result.rows[0].decimals[1], 0.05); From d3ec938b82f3bd999e1fc189b49931627eac401b Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 11:15:21 -0500 Subject: [PATCH 0208/1037] Fix remainder of error tests --- Makefile | 2 ++ lib/native/index.js | 4 ++++ lib/native/query.js | 9 ++------ ...error-handling-prepared-statement-tests.js | 21 ++++++++++++------- .../client/query-error-handling-tests.js | 12 +++++------ 5 files changed, 26 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index 4eddd4f10..0da682074 100644 --- a/Makefile +++ b/Makefile @@ -36,8 +36,10 @@ test-connection: test-missing-native: @echo "***Testing optional native install***" @rm -rf node_modules/pg-native + @rm -rf node_modules/libpq @node test/native/missing-native.js @rm -rf node_modules/pg-native + @rm -rf node_modules/libpq node_modules/pg-native/index.js: @npm i pg-native diff --git a/lib/native/index.js b/lib/native/index.js index 39bdefff8..c76953d0d 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -109,6 +109,10 @@ Client.prototype.connect = function(cb) { // } Client.prototype.query = function(config, values, callback) { if (typeof config.submit == 'function') { + // accept query(new Query(...), (err, res) => { }) style + if (typeof values == 'function') { + config.callback = values; + } this._queryQueue.push(config); this._pulseQueryQueue(); return config; diff --git a/lib/native/query.js b/lib/native/query.js index 5d6b5881e..708585f48 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -11,14 +11,9 @@ var util = require('util'); var utils = require('../utils'); var NativeResult = require('./result'); -var NativeQuery = module.exports = function(config, values) { +var NativeQuery = module.exports = function(config, values, callback) { EventEmitter.call(this); - if (typeof config == 'string') { - config = { - text: config, - values: values, - }; - } + config = utils.normalizeQueryConfig(config, values, callback); this.text = config.text; this.values = config.values; this.name = config.name; diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index 5f27e5a41..e301ab681 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -64,24 +64,29 @@ test('client end during query execution of prepared statement', function() { var client = new Client(helper.args); client.connect(assert.success(function() { var sleepQuery = 'select pg_sleep($1)'; - var query1 = client.query(new Query({ + + var queryConfig = { name: 'sleep query', text: sleepQuery, - values: [5] }, - assert.calls(function(err, result) { - assert.equal(err.message, 'Connection terminated'); - }))); + values: [5], + } + var queryInstance = new Query(queryConfig, assert.calls(function (err, result) { + assert.equal(err.message, 'Connection terminated'); + })) - query1.on('error', function(err) { + var query1 = client.query(queryInstance); + + + query1.on('error', function (err) { assert.fail('Prepared statement should not emit error'); }); - query1.on('row', function(row) { + query1.on('row', function (row) { assert.fail('Prepared statement should not emit row'); }); - query1.on('end', function(err) { + query1.on('end', function (err) { assert.fail('Prepared statement when executed should not return before being killed'); }); diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js index 53b590419..2e28737d4 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -40,7 +40,9 @@ test('error during query execution', function() { })); }); -if(helper.config.native) return; +if (helper.config.native) { + return console.log("\nTODO: this should work on native as well") +} test('9.3 column error fields', function() { var client = new Client(helper.args); @@ -50,12 +52,10 @@ test('9.3 column error fields', function() { return client.end(); } - client.query('DROP TABLE IF EXISTS column_err_test'); - client.query('CREATE TABLE column_err_test(a int NOT NULL)'); + client.query('CREATE TEMP TABLE column_err_test(a int NOT NULL)'); client.query('INSERT INTO column_err_test(a) VALUES (NULL)', function (err) { assert.equal(err.severity, 'ERROR'); assert.equal(err.code, '23502'); - assert.equal(err.schema, 'public'); assert.equal(err.table, 'column_err_test'); assert.equal(err.column, 'a'); return client.end(); @@ -73,13 +73,11 @@ test('9.3 constraint error fields', function() { return client.end(); } - client.query('DROP TABLE IF EXISTS constraint_err_test'); - client.query('CREATE TABLE constraint_err_test(a int PRIMARY KEY)'); + client.query('CREATE TEMP TABLE constraint_err_test(a int PRIMARY KEY)'); client.query('INSERT INTO constraint_err_test(a) VALUES (1)'); client.query('INSERT INTO constraint_err_test(a) VALUES (1)', function (err) { assert.equal(err.severity, 'ERROR'); assert.equal(err.code, '23505'); - assert.equal(err.schema, 'public'); assert.equal(err.table, 'constraint_err_test'); assert.equal(err.constraint, 'constraint_err_test_pkey'); return client.end(); From 970d83aca45b04f404ec79b001c61ca5d7230cfe Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 11:20:47 -0500 Subject: [PATCH 0209/1037] Remove weird quasi-promise interface on JS query --- lib/query.js | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/lib/query.js b/lib/query.js index 4d49dafd3..b36cf6b8f 100644 --- a/lib/query.js +++ b/lib/query.js @@ -40,23 +40,6 @@ var Query = function(config, values, callback) { util.inherits(Query, EventEmitter); -Query.prototype.then = function(onSuccess, onFailure) { - return this.promise().then(onSuccess, onFailure); -}; - -Query.prototype.catch = function(callback) { - return this.promise().catch(callback); -}; - -Query.prototype.promise = function() { - if (this._promise) return this._promise; - this._promise = new Promise(function(resolve, reject) { - this.once('end', resolve); - this.once('error', reject); - }.bind(this)); - return this._promise; -}; - Query.prototype.requiresPreparation = function() { //named queries must always be prepared if(this.name) { return true; } From df36bece86cecfba03d44d872d7426275f91c489 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 11:21:24 -0500 Subject: [PATCH 0210/1037] Restructure native file paths Make file paths more closely match the non-native files, to make auto-complete file names slightly easier. --- lib/native/client.js | 214 ++++++++++++++++++++++++++++++++++++++++++ lib/native/index.js | 215 +------------------------------------------ 2 files changed, 215 insertions(+), 214 deletions(-) create mode 100644 lib/native/client.js diff --git a/lib/native/client.js b/lib/native/client.js new file mode 100644 index 000000000..c76953d0d --- /dev/null +++ b/lib/native/client.js @@ -0,0 +1,214 @@ +/** + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) + * All rights reserved. + * + * This source code is licensed under the MIT license found in the + * README.md file in the root directory of this source tree. + */ + +var Native = require('pg-native'); +var TypeOverrides = require('../type-overrides'); +var semver = require('semver'); +var pkg = require('../../package.json'); +var assert = require('assert'); +var EventEmitter = require('events').EventEmitter; +var util = require('util'); +var ConnectionParameters = require('../connection-parameters'); + +var msg = 'Version >= ' + pkg.minNativeVersion + ' of pg-native required.'; +assert(semver.gte(Native.version, pkg.minNativeVersion), msg); + +var NativeQuery = require('./query'); + +var Client = module.exports = function(config) { + EventEmitter.call(this); + config = config || {}; + + this._types = new TypeOverrides(config.types); + + this.native = new Native({ + types: this._types + }); + + this._queryQueue = []; + this._connected = false; + + //keep these on the object for legacy reasons + //for the time being. TODO: deprecate all this jazz + var cp = this.connectionParameters = new ConnectionParameters(config); + this.user = cp.user; + this.password = cp.password; + this.database = cp.database; + this.host = cp.host; + this.port = cp.port; + + //a hash to hold named queries + this.namedQueries = {}; +}; + +Client.Query = NativeQuery; + +util.inherits(Client, EventEmitter); + +//connect to the backend +//pass an optional callback to be called once connected +//or with an error if there was a connection error +//if no callback is passed and there is a connection error +//the client will emit an error event. +Client.prototype.connect = function(cb) { + var self = this; + + var onError = function(err) { + if(cb) return cb(err); + return self.emit('error', err); + }; + + this.connectionParameters.getLibpqConnectionString(function(err, conString) { + if(err) return onError(err); + self.native.connect(conString, function(err) { + if(err) return onError(err); + + //set internal states to connected + self._connected = true; + + //handle connection errors from the native layer + self.native.on('error', function(err) { + //error will be handled by active query + if(self._activeQuery && self._activeQuery.state != 'end') { + return; + } + self.emit('error', err); + }); + + self.native.on('notification', function(msg) { + self.emit('notification', { + channel: msg.relname, + payload: msg.extra + }); + }); + + //signal we are connected now + self.emit('connect'); + self._pulseQueryQueue(true); + + //possibly call the optional callback + if(cb) cb(); + }); + }); +}; + +//send a query to the server +//this method is highly overloaded to take +//1) string query, optional array of parameters, optional function callback +//2) object query with { +// string query +// optional array values, +// optional function callback instead of as a separate parameter +// optional string name to name & cache the query plan +// optional string rowMode = 'array' for an array of results +// } +Client.prototype.query = function(config, values, callback) { + if (typeof config.submit == 'function') { + // accept query(new Query(...), (err, res) => { }) style + if (typeof values == 'function') { + config.callback = values; + } + this._queryQueue.push(config); + this._pulseQueryQueue(); + return config; + } + + var conf = { }; + + //support query('text', ...) style calls + if(typeof config == 'string') { + conf.text = config; + } + + //support passing everything in via a config object + if(typeof config == 'object') { + conf.text = config.text; + conf.values = config.values; + conf.name = config.name; + conf.callback = config.callback; + conf.rowMode = config.rowMode; + } + + //support query({...}, function() {}) style calls + //& support query(..., ['values'], ...) style calls + if(typeof values == 'function') { + conf.callback = values; + } + else if(util.isArray(values)) { + conf.values = values; + } + if(typeof callback == 'function') { + conf.callback = callback; + } + + var query = new NativeQuery(conf); + this._queryQueue.push(query); + this._pulseQueryQueue(); + return query; +}; + +//disconnect from the backend server +Client.prototype.end = function(cb) { + var self = this; + if(!this._connected) { + this.once('connect', this.end.bind(this, cb)); + } + this.native.end(function() { + //send an error to the active query + if(self._hasActiveQuery()) { + var msg = 'Connection terminated'; + self._queryQueue.length = 0; + self._activeQuery.handleError(new Error(msg)); + } + self.emit('end'); + if(cb) cb(); + }); +}; + +Client.prototype._hasActiveQuery = function() { + return this._activeQuery && this._activeQuery.state != 'error' && this._activeQuery.state != 'end'; +}; + +Client.prototype._pulseQueryQueue = function(initialConnection) { + if(!this._connected) { + return; + } + if(this._hasActiveQuery()) { + return; + } + var query = this._queryQueue.shift(); + if(!query) { + if(!initialConnection) { + this.emit('drain'); + } + return; + } + this._activeQuery = query; + query.submit(this); + var self = this; + query.once('_done', function() { + self._pulseQueryQueue(); + }); +}; + +//attempt to cancel an in-progress query +Client.prototype.cancel = function(query) { + if(this._activeQuery == query) { + this.native.cancel(function() {}); + } else if (this._queryQueue.indexOf(query) != -1) { + this._queryQueue.splice(this._queryQueue.indexOf(query), 1); + } +}; + +Client.prototype.setTypeParser = function(oid, format, parseFn) { + return this._types.setTypeParser(oid, format, parseFn); +}; + +Client.prototype.getTypeParser = function(oid, format) { + return this._types.getTypeParser(oid, format); +}; diff --git a/lib/native/index.js b/lib/native/index.js index c76953d0d..a35a27334 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -1,214 +1 @@ -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ - -var Native = require('pg-native'); -var TypeOverrides = require('../type-overrides'); -var semver = require('semver'); -var pkg = require('../../package.json'); -var assert = require('assert'); -var EventEmitter = require('events').EventEmitter; -var util = require('util'); -var ConnectionParameters = require('../connection-parameters'); - -var msg = 'Version >= ' + pkg.minNativeVersion + ' of pg-native required.'; -assert(semver.gte(Native.version, pkg.minNativeVersion), msg); - -var NativeQuery = require('./query'); - -var Client = module.exports = function(config) { - EventEmitter.call(this); - config = config || {}; - - this._types = new TypeOverrides(config.types); - - this.native = new Native({ - types: this._types - }); - - this._queryQueue = []; - this._connected = false; - - //keep these on the object for legacy reasons - //for the time being. TODO: deprecate all this jazz - var cp = this.connectionParameters = new ConnectionParameters(config); - this.user = cp.user; - this.password = cp.password; - this.database = cp.database; - this.host = cp.host; - this.port = cp.port; - - //a hash to hold named queries - this.namedQueries = {}; -}; - -Client.Query = NativeQuery; - -util.inherits(Client, EventEmitter); - -//connect to the backend -//pass an optional callback to be called once connected -//or with an error if there was a connection error -//if no callback is passed and there is a connection error -//the client will emit an error event. -Client.prototype.connect = function(cb) { - var self = this; - - var onError = function(err) { - if(cb) return cb(err); - return self.emit('error', err); - }; - - this.connectionParameters.getLibpqConnectionString(function(err, conString) { - if(err) return onError(err); - self.native.connect(conString, function(err) { - if(err) return onError(err); - - //set internal states to connected - self._connected = true; - - //handle connection errors from the native layer - self.native.on('error', function(err) { - //error will be handled by active query - if(self._activeQuery && self._activeQuery.state != 'end') { - return; - } - self.emit('error', err); - }); - - self.native.on('notification', function(msg) { - self.emit('notification', { - channel: msg.relname, - payload: msg.extra - }); - }); - - //signal we are connected now - self.emit('connect'); - self._pulseQueryQueue(true); - - //possibly call the optional callback - if(cb) cb(); - }); - }); -}; - -//send a query to the server -//this method is highly overloaded to take -//1) string query, optional array of parameters, optional function callback -//2) object query with { -// string query -// optional array values, -// optional function callback instead of as a separate parameter -// optional string name to name & cache the query plan -// optional string rowMode = 'array' for an array of results -// } -Client.prototype.query = function(config, values, callback) { - if (typeof config.submit == 'function') { - // accept query(new Query(...), (err, res) => { }) style - if (typeof values == 'function') { - config.callback = values; - } - this._queryQueue.push(config); - this._pulseQueryQueue(); - return config; - } - - var conf = { }; - - //support query('text', ...) style calls - if(typeof config == 'string') { - conf.text = config; - } - - //support passing everything in via a config object - if(typeof config == 'object') { - conf.text = config.text; - conf.values = config.values; - conf.name = config.name; - conf.callback = config.callback; - conf.rowMode = config.rowMode; - } - - //support query({...}, function() {}) style calls - //& support query(..., ['values'], ...) style calls - if(typeof values == 'function') { - conf.callback = values; - } - else if(util.isArray(values)) { - conf.values = values; - } - if(typeof callback == 'function') { - conf.callback = callback; - } - - var query = new NativeQuery(conf); - this._queryQueue.push(query); - this._pulseQueryQueue(); - return query; -}; - -//disconnect from the backend server -Client.prototype.end = function(cb) { - var self = this; - if(!this._connected) { - this.once('connect', this.end.bind(this, cb)); - } - this.native.end(function() { - //send an error to the active query - if(self._hasActiveQuery()) { - var msg = 'Connection terminated'; - self._queryQueue.length = 0; - self._activeQuery.handleError(new Error(msg)); - } - self.emit('end'); - if(cb) cb(); - }); -}; - -Client.prototype._hasActiveQuery = function() { - return this._activeQuery && this._activeQuery.state != 'error' && this._activeQuery.state != 'end'; -}; - -Client.prototype._pulseQueryQueue = function(initialConnection) { - if(!this._connected) { - return; - } - if(this._hasActiveQuery()) { - return; - } - var query = this._queryQueue.shift(); - if(!query) { - if(!initialConnection) { - this.emit('drain'); - } - return; - } - this._activeQuery = query; - query.submit(this); - var self = this; - query.once('_done', function() { - self._pulseQueryQueue(); - }); -}; - -//attempt to cancel an in-progress query -Client.prototype.cancel = function(query) { - if(this._activeQuery == query) { - this.native.cancel(function() {}); - } else if (this._queryQueue.indexOf(query) != -1) { - this._queryQueue.splice(this._queryQueue.indexOf(query), 1); - } -}; - -Client.prototype.setTypeParser = function(oid, format, parseFn) { - return this._types.setTypeParser(oid, format, parseFn); -}; - -Client.prototype.getTypeParser = function(oid, format) { - return this._types.getTypeParser(oid, format); -}; +module.exports = require('./client') From 55c3b3691cc3e095aa7a4b6a8d27daddd2360f9a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 11:23:15 -0500 Subject: [PATCH 0211/1037] Use normalizeQueryConfig in native query --- lib/native/client.js | 30 +----------------------------- lib/native/index.js | 2 +- 2 files changed, 2 insertions(+), 30 deletions(-) diff --git a/lib/native/client.js b/lib/native/client.js index c76953d0d..e7e17b081 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -118,35 +118,7 @@ Client.prototype.query = function(config, values, callback) { return config; } - var conf = { }; - - //support query('text', ...) style calls - if(typeof config == 'string') { - conf.text = config; - } - - //support passing everything in via a config object - if(typeof config == 'object') { - conf.text = config.text; - conf.values = config.values; - conf.name = config.name; - conf.callback = config.callback; - conf.rowMode = config.rowMode; - } - - //support query({...}, function() {}) style calls - //& support query(..., ['values'], ...) style calls - if(typeof values == 'function') { - conf.callback = values; - } - else if(util.isArray(values)) { - conf.values = values; - } - if(typeof callback == 'function') { - conf.callback = callback; - } - - var query = new NativeQuery(conf); + var query = new NativeQuery(config, values, callback); this._queryQueue.push(query); this._pulseQueryQueue(); return query; diff --git a/lib/native/index.js b/lib/native/index.js index a35a27334..ccf987e3a 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -1 +1 @@ -module.exports = require('./client') +module.exports = require('./client'); From bc2f5504029c3c29a751736b0406f4fcda94e78c Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 11:43:15 -0500 Subject: [PATCH 0212/1037] Remove promise-interop from native query --- lib/native/client.js | 7 ++++- lib/native/query.js | 17 ----------- test/native/error-tests.js | 28 ------------------- test/native/evented-api-tests.js | 48 ++++++++------------------------ test/native/stress-tests.js | 5 ++-- 5 files changed, 20 insertions(+), 85 deletions(-) diff --git a/lib/native/client.js b/lib/native/client.js index e7e17b081..e57a94190 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -119,9 +119,14 @@ Client.prototype.query = function(config, values, callback) { } var query = new NativeQuery(config, values, callback); + var result = query.callback ? query : new global.Promise(function(resolve, reject) { + query.on('end', resolve); + query.on('error', reject); + }); + this._queryQueue.push(query); this._pulseQueryQueue(); - return query; + return result; }; //disconnect from the backend server diff --git a/lib/native/query.js b/lib/native/query.js index 708585f48..1523e7c7e 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -34,23 +34,6 @@ var NativeQuery = module.exports = function(config, values, callback) { util.inherits(NativeQuery, EventEmitter); -NativeQuery.prototype.then = function(onSuccess, onFailure) { - return this.promise().then(onSuccess, onFailure); -}; - -NativeQuery.prototype.catch = function(callback) { - return this.promise().catch(callback); -}; - -NativeQuery.prototype.promise = function() { - if (this._promise) return this._promise; - this._promise = new Promise(function(resolve, reject) { - this.once('end', resolve); - this.once('error', reject); - }.bind(this)); - return this._promise; -}; - var errorFieldMap = { 'sqlState': 'code', 'statementPosition': 'position', diff --git a/test/native/error-tests.js b/test/native/error-tests.js index 3a9327050..2edf34215 100644 --- a/test/native/error-tests.js +++ b/test/native/error-tests.js @@ -1,34 +1,6 @@ var helper = require(__dirname + "/../test-helper"); var Client = require(__dirname + "/../../lib/native"); -test('query with non-text as first parameter throws error', function() { - var client = new Client(helper.config); - client.connect(); - assert.emits(client, 'connect', function() { - client.end(); - assert.emits(client, 'end', function() { - assert.throws(function() { - client.query({text:{fail: true}}); - }); - }); - }); -}); - -test('parameterized query with non-text as first parameter throws error', function() { - var client = new Client(helper.config); - client.connect(); - assert.emits(client, 'connect', function() { - client.end(); - assert.emits(client, 'end', function() { - assert.throws(function() { - client.query({ - text: {fail: true}, - values: [1, 2] - }) - }); - }); - }); -}); var connect = function(callback) { var client = new Client(helper.config); diff --git a/test/native/evented-api-tests.js b/test/native/evented-api-tests.js index 9bff34109..122dc47e0 100644 --- a/test/native/evented-api-tests.js +++ b/test/native/evented-api-tests.js @@ -1,5 +1,6 @@ -var helper = require(__dirname + "/../test-helper"); -var Client = require(__dirname + "/../../lib/native"); +var helper = require("../test-helper"); +var Client = require("../../lib/native"); +var Query = Client.Query; var setupClient = function() { var client = new Client(helper.config); @@ -10,37 +11,10 @@ var setupClient = function() { return client; } -//test('connects', function() { - //var client = new Client(helper.config); - //client.connect(); - //test('good query', function() { - //var query = client.query("SELECT 1 as num, 'HELLO' as str"); - //assert.emits(query, 'row', function(row) { - //test('has integer data type', function() { - //assert.strictEqual(row.num, 1); - //}) - //test('has string data type', function() { - //assert.strictEqual(row.str, "HELLO") - //}) - //test('emits end AFTER row event', function() { - //assert.emits(query, 'end'); - //test('error query', function() { - //var query = client.query("LSKDJF"); - //assert.emits(query, 'error', function(err) { - //assert.ok(err != null, "Should not have emitted null error"); - //client.end(); - //}) - //}) - //}) - //}) - //}) -//}) - - test('multiple results', function() { test('queued queries', function() { var client = setupClient(); - var q = client.query("SELECT name FROM BOOM"); + var q = client.query(new Query("SELECT name FROM BOOM")); assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Aaron'); assert.emits(q, 'row', function(row) { @@ -49,7 +23,7 @@ test('multiple results', function() { }) assert.emits(q, 'end', function() { test('query with config', function() { - var q2 = client.query({text:'SELECT 1 as num'}); + var q2 = client.query(new Query({text:'SELECT 1 as num'})); assert.emits(q2, 'row', function(row) { assert.strictEqual(row.num, 1); assert.emits(q2, 'end', function() { @@ -64,7 +38,7 @@ test('multiple results', function() { test('parameterized queries', function() { test('with a single string param', function() { var client = setupClient(); - var q = client.query("SELECT * FROM boom WHERE name = $1", ['Aaron']); + var q = client.query(new Query("SELECT * FROM boom WHERE name = $1", ['Aaron'])); assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Aaron'); }) @@ -75,10 +49,10 @@ test('parameterized queries', function() { test('with object config for query', function() { var client = setupClient(); - var q = client.query({ + var q = client.query(new Query({ text: "SELECT name FROM boom WHERE name = $1", values: ['Brian'] - }); + })); assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Brian'); }) @@ -89,7 +63,7 @@ test('parameterized queries', function() { test('multiple parameters', function() { var client = setupClient(); - var q = client.query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name', ['Aaron', 'Brian']); + var q = client.query(new Query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name', ['Aaron', 'Brian'])); assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Aaron'); assert.emits(q, 'row', function(row) { @@ -100,10 +74,10 @@ test('parameterized queries', function() { }) }) }) - + test('integer parameters', function() { var client = setupClient(); - var q = client.query('SELECT * FROM boom WHERE age > $1', [27]); + var q = client.query(new Query('SELECT * FROM boom WHERE age > $1', [27])); assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Brian'); assert.equal(row.age, 28); diff --git a/test/native/stress-tests.js b/test/native/stress-tests.js index bd2bca5a0..08fab97ed 100644 --- a/test/native/stress-tests.js +++ b/test/native/stress-tests.js @@ -1,10 +1,11 @@ var helper = require(__dirname + "/../test-helper"); var Client = require(__dirname + "/../../lib/native"); +var Query = Client.Query; test('many rows', function() { var client = new Client(helper.config); client.connect(); - var q = client.query("SELECT * FROM person"); + var q = client.query(new Query("SELECT * FROM person")); var rows = []; q.on('row', function(row) { rows.push(row) @@ -21,7 +22,7 @@ test('many queries', function() { var count = 0; var expected = 100; for(var i = 0; i < expected; i++) { - var q = client.query("SELECT * FROM person"); + var q = client.query(new Query("SELECT * FROM person")); assert.emits(q, 'end', function() { count++; }); From 02bcc9d97af454b56106fd080146e5c8e1828586 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 12:54:07 -0500 Subject: [PATCH 0213/1037] Start working on promsie tests --- lib/client.js | 133 +++++++++++-------- test/integration/client/promise-api-tests.js | 105 +++++++++++++++ 2 files changed, 182 insertions(+), 56 deletions(-) create mode 100644 test/integration/client/promise-api-tests.js diff --git a/lib/client.js b/lib/client.js index 32ea76b95..3a8515a41 100644 --- a/lib/client.js +++ b/lib/client.js @@ -108,56 +108,21 @@ Client.prototype.connect = function(callback) { self.secretKey = msg.secretKey; }); + + con.on('readyForQuery', function() { + var activeQuery = self.activeQuery; + self.activeQuery = null; + self.readyForQuery = true; + self._pulseQueryQueue(); + if(activeQuery) { + activeQuery.handleReadyForQuery(con); + } + }); + //hook up query handling events to connection //after the connection initially becomes ready for queries con.once('readyForQuery', function() { - self._connecting = false; - - //delegate rowDescription to active query - con.on('rowDescription', function(msg) { - self.activeQuery.handleRowDescription(msg); - }); - - //delegate dataRow to active query - con.on('dataRow', function(msg) { - self.activeQuery.handleDataRow(msg); - }); - - //delegate portalSuspended to active query - con.on('portalSuspended', function(msg) { - self.activeQuery.handlePortalSuspended(con); - }); - - //deletagate emptyQuery to active query - con.on('emptyQuery', function(msg) { - self.activeQuery.handleEmptyQuery(con); - }); - - //delegate commandComplete to active query - con.on('commandComplete', function(msg) { - self.activeQuery.handleCommandComplete(msg, con); - }); - - //if a prepared statement has a name and properly parses - //we track that its already been executed so we don't parse - //it again on the same client - con.on('parseComplete', function(msg) { - if(self.activeQuery.name) { - con.parsedStatements[self.activeQuery.name] = true; - } - }); - - con.on('copyInResponse', function(msg) { - self.activeQuery.handleCopyInResponse(self.connection); - }); - - con.on('copyData', function (msg) { - self.activeQuery.handleCopyData(msg, self.connection); - }); - - con.on('notification', function(msg) { - self.emit('notification', msg); - }); + self._attachEventListeners(con) //process possible callback argument to Client#connect if (callback) { @@ -169,15 +134,15 @@ Client.prototype.connect = function(callback) { self.emit('connect'); }); - con.on('readyForQuery', function() { - var activeQuery = self.activeQuery; - self.activeQuery = null; - self.readyForQuery = true; - self._pulseQueryQueue(); - if(activeQuery) { - activeQuery.handleReadyForQuery(con); - } - }); + if (!callback) { + return new global.Promise(function (resolve, reject) { + con.once('connect', () => { + con.removeListener('error', reject) + resolve() + }) + con.once('error', reject) + }) + } con.on('error', function(error) { if(this.activeQuery) { @@ -234,6 +199,58 @@ Client.prototype.connect = function(callback) { }; +// once a connection is established connect listeners +Client.prototype._attachEventListeners = function(con) { + var self = this; + self._connecting = false; + + //delegate rowDescription to active query + con.on('rowDescription', function(msg) { + self.activeQuery.handleRowDescription(msg); + }); + + //delegate dataRow to active query + con.on('dataRow', function(msg) { + self.activeQuery.handleDataRow(msg); + }); + + //delegate portalSuspended to active query + con.on('portalSuspended', function(msg) { + self.activeQuery.handlePortalSuspended(con); + }); + + //deletagate emptyQuery to active query + con.on('emptyQuery', function(msg) { + self.activeQuery.handleEmptyQuery(con); + }); + + //delegate commandComplete to active query + con.on('commandComplete', function(msg) { + self.activeQuery.handleCommandComplete(msg, con); + }); + + //if a prepared statement has a name and properly parses + //we track that its already been executed so we don't parse + //it again on the same client + con.on('parseComplete', function(msg) { + if(self.activeQuery.name) { + con.parsedStatements[self.activeQuery.name] = true; + } + }); + + con.on('copyInResponse', function(msg) { + self.activeQuery.handleCopyInResponse(self.connection); + }); + + con.on('copyData', function (msg) { + self.activeQuery.handleCopyData(msg, self.connection); + }); + + con.on('notification', function(msg) { + self.emit('notification', msg); + }); +} + Client.prototype.getStartupConf = function() { var params = this.connectionParameters; @@ -391,6 +408,10 @@ Client.prototype.end = function(cb) { this.connection.end(); if (cb) { this.connection.once('end', cb); + } else { + return new global.Promise((resolve) => { + this.connection.once('end', resolve); + }); } }; diff --git a/test/integration/client/promise-api-tests.js b/test/integration/client/promise-api-tests.js new file mode 100644 index 000000000..783fb46cd --- /dev/null +++ b/test/integration/client/promise-api-tests.js @@ -0,0 +1,105 @@ +const async = require('async') +const helper = require('./test-helper') +const pg = helper.pg; + +class Test { + constructor(name, cb) { + this.name = name + this.action = cb + this.timeout = 5000 + } + + run(cb) { + try { + this._run(cb) + } catch (e) { + cb(e) + } + } + + _run(cb) { + if (!this.action) { + console.log(`${this.name} skipped`) + return cb() + } + if (!this.action.length) { + const result = this.action.call(this) + if ((result || 0).then) { + result + .then(() => cb()) + .catch(err => cb(err || new Error('Unhandled promise rejection'))) + } + } else { + this.action.call(this, cb) + } + } +} + +class Suite { + constructor() { + console.log('') + this._queue = async.queue(this.run.bind(this), 1) + this._queue.drain = () => { } + } + + run(test, cb) { + const tid = setTimeout(() => { + const err = Error(`test: ${test.name} did not complete withint ${test.timeout}ms`) + cb(err) + }, test.timeout) + test.run((err) => { + clearTimeout(tid) + if (err) { + console.log(test.name + ' FAILED!', err.stack) + } else { + console.log(test.name) + } + cb(err) + }) + } + + test(name, cb) { + this._queue.push(new Test(name, cb)) + } +} + +const suite = new Suite() + +suite.test('valid connection completes promise', () => { + const client = new pg.Client() + return client.connect() + .then(() => { + return client.end() + .then(() => { }) + }) +}) + +suite.test('valid connection completes promise', () => { + const client = new pg.Client() + return client.connect() + .then(() => { + return client.end() + .then(() => { }) + }) +}) + + +suite.test('invalid connection rejects promise', (done) => { + const client = new pg.Client({ host: 'alksdjflaskdfj' }) + return client.connect() + .catch(e => { + assert(e instanceof Error) + done() + }) +}) + +suite.test('connected client does not reject promise after', (done) => { + const client = new pg.Client() + return client.connect() + .then(() => { + setTimeout(() => { + // manually kill the connection + client.connection.stream.end() + }, 50) + }) +}) From 3a7b226fe3e6a0e1400fc05df4ce33c7a8a6e86c Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 16:55:56 -0500 Subject: [PATCH 0214/1037] WIP --- lib/client.js | 35 +-- lib/connection.js | 7 +- lib/promise.js | 12 ++ .../client/error-handling-tests.js | 202 +++++++----------- test/integration/client/promise-api-tests.js | 72 +------ ...error-handling-prepared-statement-tests.js | 16 +- test/suite.js | 74 +++++++ test/test-helper.js | 1 + 8 files changed, 209 insertions(+), 210 deletions(-) create mode 100644 lib/promise.js create mode 100644 test/suite.js diff --git a/lib/client.js b/lib/client.js index 3a8515a41..3104f70b1 100644 --- a/lib/client.js +++ b/lib/client.js @@ -67,12 +67,12 @@ Client.prototype.connect = function(callback) { if(self.ssl) { con.requestSsl(); } else { - con.startup(self.getStartupConf()); + con.startup(self._getStartupConfiguration()); } }); con.on('sslconnect', function() { - con.startup(self.getStartupConf()); + con.startup(self._getStartupConfiguration()); }); function checkPgPass(cb) { @@ -122,7 +122,7 @@ Client.prototype.connect = function(callback) { //hook up query handling events to connection //after the connection initially becomes ready for queries con.once('readyForQuery', function() { - self._attachEventListeners(con) + self._attachEventListeners(con); //process possible callback argument to Client#connect if (callback) { @@ -134,16 +134,6 @@ Client.prototype.connect = function(callback) { self.emit('connect'); }); - if (!callback) { - return new global.Promise(function (resolve, reject) { - con.once('connect', () => { - con.removeListener('error', reject) - resolve() - }) - con.once('error', reject) - }) - } - con.on('error', function(error) { if(this.activeQuery) { var activeQuery = self.activeQuery; @@ -197,8 +187,22 @@ Client.prototype.connect = function(callback) { self.emit('notice', msg); }); + var result; + + if (!callback) { + result = new global.Promise(function (resolve, reject) { + con.once('connect', function () { + con.removeListener('error', reject) + resolve() + }) + this.once('error', reject) + }.bind(this)) + } + + return result; }; + // once a connection is established connect listeners Client.prototype._attachEventListeners = function(con) { var self = this; @@ -251,7 +255,7 @@ Client.prototype._attachEventListeners = function(con) { }); } -Client.prototype.getStartupConf = function() { +Client.prototype._getStartupConfiguration = function() { var params = this.connectionParameters; var data = { @@ -405,6 +409,9 @@ Client.prototype.query = function(config, values, callback) { Client.prototype.end = function(cb) { this._ending = true; + if (this.activeQuery) { + return this.connection.stream.end() + } this.connection.end(); if (cb) { this.connection.once('end', cb); diff --git a/lib/connection.js b/lib/connection.js index 6bda2f8b5..c40639e02 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -186,7 +186,9 @@ Connection.prototype.password = function(password) { }; Connection.prototype._send = function(code, more) { - if(!this.stream.writable) { return false; } + if(!this.stream.writable) { + return false; + } if(more === true) { this.writer.addHeader(code); } else { @@ -308,11 +310,12 @@ Connection.prototype.sync = function() { this._send(0x53); }; +const END_BUFFER = new Buffer([0x58, 0x00, 0x00, 0x00, 0x04]); Connection.prototype.end = function() { //0x58 = 'X' this.writer.add(emptyBuffer); this._ending = true; - this._send(0x58); + return this.stream.end(END_BUFFER); }; Connection.prototype.close = function(msg, more) { diff --git a/lib/promise.js b/lib/promise.js new file mode 100644 index 000000000..4d308cb90 --- /dev/null +++ b/lib/promise.js @@ -0,0 +1,12 @@ +const util = require('util') +const deprecationMessage = 'Using the promise result as an event emitter is deprecated and will be removed in pg@8.0' +module.exports = function(emitter, callback) { + const promise = new global.Promise(callback) + promise.on = util.deprecate(function () { + emitter.on.apply(emitter, arguments) + }, deprecationMessage); + + promise.once = util.deprecate(function () { + emitter.once.apply(emitter, arguments) + }, deprecationMessage) +} diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 08e78b333..4a2be1ee0 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -1,103 +1,111 @@ +"use strict"; + var helper = require('./test-helper'); var util = require('util'); var pg = helper.pg - var createErorrClient = function() { var client = helper.client(); client.once('error', function(err) { - //console.log('error', util.inspect(err)); assert.fail('Client shoud not throw error during query execution'); }); client.on('drain', client.end.bind(client)); return client; }; -test('error handling', function() { - test('within a simple query', function() { - var client = createErorrClient(); - - var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")); +const suite = new helper.Suite('error handling') - assert.emits(query, 'error', function(error) { - assert.equal(error.severity, "ERROR"); - }); +suite.test('query receives error on client shutdown', false, function(done) { + var client = new Client(); + client.connect(function(err) { + if (err) { + return done(err) + } + client.query('SELECT pg_sleep(5)', assert.calls(function(err, res) { + assert(err instanceof Error) + done() + })); + setTimeout(() => { + client.end() + assert.emits(client, 'end'); + }, 50) }); +}); - test('within a prepared statement', function() { - - var client = createErorrClient(); - - var q = client.query({text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);", binary: false}); +suite.test('within a simple query', (done) => { + var client = createErorrClient(); - test("when query is parsing", function() { + var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")); - //this query wont parse since there ain't no table named bang + assert.emits(query, 'error', function(error) { + assert.equal(error.severity, "ERROR"); + done(); + }); +}); - var ensureFuture = function(testClient) { - test("client can issue more queries successfully", function() { - var goodQuery = testClient.query(new pg.Query("select age from boom")); - assert.emits(goodQuery, 'row', function(row) { - assert.equal(row.age, 28); - }); - }); - }; +(function () { + var client = createErorrClient(); - var query = client.query(new pg.Query({ - text: "select * from bang where name = $1", - values: ['0'] - })); + var q = client.query({ text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);", binary: false }); - test("query emits the error", function() { - assert.emits(query, 'error', function(err) { - ensureFuture(client); - }); - }); + var ensureFuture = function (testClient, done) { + var goodQuery = testClient.query(new pg.Query("select age from boom")); + assert.emits(goodQuery, 'row', function (row) { + assert.equal(row.age, 28); + done(); + }); + }; - test("when a query is binding", function() { + suite.test("when query is parsing", (done) => { - var query = client.query(new pg.Query({ - text: 'select * from boom where age = $1', - values: ['asldkfjasdf'] - })); + //this query wont parse since there isn't a table named bang + var query = client.query(new pg.Query({ + text: "select * from bang where name = $1", + values: ['0'] + })); - test("query emits the error", function() { + assert.emits(query, 'error', function (err) { + ensureFuture(client, done); + }); + }); - assert.emits(query, 'error', function(err) { - test('error has right severity', function() { - assert.equal(err.severity, "ERROR"); - }) + suite.test("when a query is binding", function (done) { - ensureFuture(client); - }); - }); + var query = client.query(new pg.Query({ + text: 'select * from boom where age = $1', + values: ['asldkfjasdf'] + })); - //TODO how to test for errors during execution? - }); + assert.emits(query, 'error', function (err) { + assert.equal(err.severity, "ERROR"); + ensureFuture(client, done); }); }); +})(); - test('non-query error', function() { - var client = new Client({ - user:'asldkfjsadlfkj' - }); - assert.emits(client, 'error'); - client.connect(); +suite.test('non-query error', function(done) { + var client = new Client({ + user:'asldkfjsadlfkj' }); - - test('non-query error with callback', function() { - var client = new Client({ - user:'asldkfjsadlfkj' - }); - client.connect(assert.calls(function(error, client) { - assert.ok(error); - })); + client.on('error', (err) => { + assert(err instanceof Error) + done() }); + client.connect(); +}); +suite.test('non-query error with callback', function(done) { + var client = new Client({ + user:'asldkfjsadlfkj' + }); + client.connect(assert.calls(function(error, client) { + assert(error instanceof Error) + done() + })); }); -test('non-error calls supplied callback', function() { +suite.test('non-error calls supplied callback', function(done) { var client = new Client({ user: helper.args.user, password: helper.args.password, @@ -108,75 +116,23 @@ test('non-error calls supplied callback', function() { client.connect(assert.calls(function(err) { assert.ifError(err); - client.end(); + client.end(done); })) }); -test('when connecting to invalid host', function() { - //this test fails about 30% on travis and only on travis... - //I'm not sure what the cause could be - if(process.env.TRAVIS) return false; - +suite.test('when connecting to invalid host with promise', function(done) { var client = new Client({ - user: 'aslkdjfsdf', - password: '1234', - host: 'asldkfjasdf!!#1308140.com' + host: 'asdlfkjasldkfjlaskdfj' }); - - var delay = 5000; - var tid = setTimeout(function() { - var msg = "When connecting to an invalid host the error event should be emitted but it has been " + delay + " and still no error event." - assert(false, msg); - }, delay); - client.on('error', function() { - clearTimeout(tid); - }) - client.connect(); + client.connect().catch((e) => done()); }); -test('when connecting to invalid host with callback', function() { +suite.test('when connecting to an invalid host with callback', function (done) { var client = new Client({ - user: 'brian', - password: '1234', host: 'asldkfjasdf!!#1308140.com' }); client.connect(function(error, client) { - assert(error); + assert(error instanceof Error); + done(); }); }); - -test('multiple connection errors (gh#31)', function() { - return false; - test('with single client', function() { - //don't run yet...this test fails...need to think of fix - var client = new Client({ - user: 'blaksdjf', - password: 'omfsadfas', - host: helper.args.host, - port: helper.args.port, - database: helper.args.database - }); - client.connect(); - assert.emits(client, 'error', function(e) { - client.connect(); - assert.emits(client, 'error'); - }); - }); - - test('with callback method', function() { - var badConString = "postgres://aslkdfj:oi14081@"+helper.args.host+":"+helper.args.port+"/"+helper.args.database; - return false; - }); -}); - -test('query receives error on client shutdown', function() { - var client = new Client(helper.config); - client.connect(assert.calls(function() { - client.query('SELECT pg_sleep(5)', assert.calls(function(err, res) { - assert(err); - })); - client.end(); - assert.emits(client, 'end'); - })); -}); - diff --git a/test/integration/client/promise-api-tests.js b/test/integration/client/promise-api-tests.js index 783fb46cd..17094c9d4 100644 --- a/test/integration/client/promise-api-tests.js +++ b/test/integration/client/promise-api-tests.js @@ -1,69 +1,9 @@ -const async = require('async') +'use strict'; + const helper = require('./test-helper') const pg = helper.pg; -class Test { - constructor(name, cb) { - this.name = name - this.action = cb - this.timeout = 5000 - } - - run(cb) { - try { - this._run(cb) - } catch (e) { - cb(e) - } - } - - _run(cb) { - if (!this.action) { - console.log(`${this.name} skipped`) - return cb() - } - if (!this.action.length) { - const result = this.action.call(this) - if ((result || 0).then) { - result - .then(() => cb()) - .catch(err => cb(err || new Error('Unhandled promise rejection'))) - } - } else { - this.action.call(this, cb) - } - } -} - -class Suite { - constructor() { - console.log('') - this._queue = async.queue(this.run.bind(this), 1) - this._queue.drain = () => { } - } - - run(test, cb) { - const tid = setTimeout(() => { - const err = Error(`test: ${test.name} did not complete withint ${test.timeout}ms`) - cb(err) - }, test.timeout) - test.run((err) => { - clearTimeout(tid) - if (err) { - console.log(test.name + ' FAILED!', err.stack) - } else { - console.log(test.name) - } - cb(err) - }) - } - - test(name, cb) { - this._queue.push(new Test(name, cb)) - } -} - -const suite = new Suite() +const suite = new helper.Suite() suite.test('valid connection completes promise', () => { const client = new pg.Client() @@ -93,11 +33,15 @@ suite.test('invalid connection rejects promise', (done) => { }) }) -suite.test('connected client does not reject promise after', (done) => { +suite.test('connected client does not reject promise after connection', (done) => { const client = new pg.Client() return client.connect() .then(() => { setTimeout(() => { + client.on('error', (e) => { + assert(e instanceof Error) + done() + }) // manually kill the connection client.connection.stream.end() }, 50) diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index e301ab681..a7bda9c76 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -2,7 +2,9 @@ var helper = require('./test-helper'); var Query = helper.pg.Query; var util = require('util'); -function killIdleQuery(targetQuery) { +var suite = new helper.Suite(); + +function killIdleQuery(targetQuery, cb) { var client2 = new Client(helper.args); var pidColName = 'procpid' var queryColName = 'current_query'; @@ -16,16 +18,16 @@ function killIdleQuery(targetQuery) { client2.query(killIdleQuery, [targetQuery], assert.calls(function(err, res) { assert.ifError(err); assert.equal(res.rows.length, 1); - client2.end(); + client2.end(cb); assert.emits(client2, 'end'); })); })); })); } -test('query killed during query execution of prepared statement', function() { +suite.test('query killed during query execution of prepared statement', function(done) { if(helper.args.native) { - return false; + return done(); } var client = new Client(helper.args); client.connect(assert.success(function() { @@ -56,11 +58,11 @@ test('query killed during query execution of prepared statement', function() { assert.fail('Prepared statement when executed should not return before being killed'); }); - killIdleQuery(sleepQuery); + killIdleQuery(sleepQuery, done); })); }); -test('client end during query execution of prepared statement', function() { +suite.test('client end during query execution of prepared statement', function(done) { var client = new Client(helper.args); client.connect(assert.success(function() { var sleepQuery = 'select pg_sleep($1)'; @@ -90,6 +92,6 @@ test('client end during query execution of prepared statement', function() { assert.fail('Prepared statement when executed should not return before being killed'); }); - client.end(); + client.end(done); })); }); diff --git a/test/suite.js b/test/suite.js new file mode 100644 index 000000000..37227fc94 --- /dev/null +++ b/test/suite.js @@ -0,0 +1,74 @@ +'use strict'; + +const async = require('async') + +class Test { + constructor(name, cb) { + this.name = name + this.action = cb + this.timeout = 5000 + } + + run(cb) { + try { + this._run(cb) + } catch (e) { + cb(e) + } + } + + _run(cb) { + if (!this.action) { + console.log(`${this.name} skipped`) + return cb() + } + if (!this.action.length) { + const result = this.action.call(this) + if ((result || 0).then) { + result + .then(() => cb()) + .catch(err => cb(err || new Error('Unhandled promise rejection'))) + } + } else { + this.action.call(this, cb) + } + } +} + +class Suite { + constructor(name) { + console.log('') + this._queue = async.queue(this.run.bind(this), 1) + this._queue.drain = () => { } + } + + run(test, cb) { + process.stdout.write(test.name + ' ') + if (!test.action) { + process.stdout.write('? - SKIPPED') + return cb() + } + + const tid = setTimeout(() => { + const err = Error(`test: ${test.name} did not complete withint ${test.timeout}ms`) + cb(err) + }, test.timeout) + + test.run((err) => { + clearTimeout(tid) + if (err) { + process.stdout.write(`FAILED!\n\n${err.stack}\n`) + process.exit(-1) + } else { + process.stdout.write('✔\n') + } + cb(err) + }) + } + + test(name, cb) { + this._queue.push(new Test(name, cb)) + } +} + +module.exports = Suite diff --git a/test/test-helper.js b/test/test-helper.js index f39cbfef3..4cf6a4554 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -240,6 +240,7 @@ var resetTimezoneOffset = function() { module.exports = { Sink: Sink, + Suite: require('./suite'), pg: require(__dirname + '/../lib/'), args: args, config: args, From 72560850d7ca0c07591acfc8421e26469d283423 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 17:02:23 -0500 Subject: [PATCH 0215/1037] Working on disconnect issue --- lib/client.js | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/client.js b/lib/client.js index 3104f70b1..5800e943d 100644 --- a/lib/client.js +++ b/lib/client.js @@ -409,17 +409,15 @@ Client.prototype.query = function(config, values, callback) { Client.prototype.end = function(cb) { this._ending = true; - if (this.activeQuery) { - return this.connection.stream.end() - } - this.connection.end(); if (cb) { this.connection.once('end', cb); - } else { - return new global.Promise((resolve) => { - this.connection.once('end', resolve); - }); + this.connection.end(); + return; } + return new global.Promise((resolve) => { + this.connection.end(); + this.connection.once('end', resolve); + }); }; Client.md5 = function(string) { From f41839b83a43c6bd5efbfe68484119770da3a756 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 17:09:27 -0500 Subject: [PATCH 0216/1037] Work on test --- ...error-handling-prepared-statement-tests.js | 69 ++++++++++--------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index a7bda9c76..a250f78b3 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -4,6 +4,41 @@ var util = require('util'); var suite = new helper.Suite(); +suite.test('client end during query execution of prepared statement', function(done) { + var client = new Client(helper.args); + client.connect(assert.success(function() { + + var sleepQuery = 'select pg_sleep($1)'; + + var queryConfig = { + name: 'sleep query', + text: sleepQuery, + values: [5], + } + + var queryInstance = new Query(queryConfig, assert.calls(function (err, result) { + assert.equal(err.message, 'Connection terminated'); + })) + + var query1 = client.query(queryInstance); + + + query1.on('error', function (err) { + assert.fail('Prepared statement should not emit error'); + }); + + query1.on('row', function (row) { + assert.fail('Prepared statement should not emit row'); + }); + + query1.on('end', function (err) { + assert.fail('Prepared statement when executed should not return before being killed'); + }); + + client.end(done); + })); +}); + function killIdleQuery(targetQuery, cb) { var client2 = new Client(helper.args); var pidColName = 'procpid' @@ -61,37 +96,3 @@ suite.test('query killed during query execution of prepared statement', function killIdleQuery(sleepQuery, done); })); }); - -suite.test('client end during query execution of prepared statement', function(done) { - var client = new Client(helper.args); - client.connect(assert.success(function() { - var sleepQuery = 'select pg_sleep($1)'; - - var queryConfig = { - name: 'sleep query', - text: sleepQuery, - values: [5], - } - - var queryInstance = new Query(queryConfig, assert.calls(function (err, result) { - assert.equal(err.message, 'Connection terminated'); - })) - - var query1 = client.query(queryInstance); - - - query1.on('error', function (err) { - assert.fail('Prepared statement should not emit error'); - }); - - query1.on('row', function (row) { - assert.fail('Prepared statement should not emit row'); - }); - - query1.on('end', function (err) { - assert.fail('Prepared statement when executed should not return before being killed'); - }); - - client.end(done); - })); -}); From 3219db993ab9880bb03499a7819c85ae177b4250 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 17:49:49 -0500 Subject: [PATCH 0217/1037] All tests passing --- Makefile | 1 - lib/client.js | 187 ++++++++---------- lib/connection.js | 2 +- .../client/error-handling-tests.js | 89 ++++----- .../client/network-partition-tests.js | 11 +- test/suite.js | 9 +- 6 files changed, 143 insertions(+), 156 deletions(-) diff --git a/Makefile b/Makefile index 0da682074..08c1e10ca 100644 --- a/Makefile +++ b/Makefile @@ -62,4 +62,3 @@ test-pool: jshint: @echo "***Starting jshint***" - @./node_modules/.bin/jshint lib diff --git a/lib/client.js b/lib/client.js index 5800e943d..c1cef452c 100644 --- a/lib/client.js +++ b/lib/client.js @@ -67,12 +67,12 @@ Client.prototype.connect = function(callback) { if(self.ssl) { con.requestSsl(); } else { - con.startup(self._getStartupConfiguration()); + con.startup(self.getStartupConf()); } }); con.on('sslconnect', function() { - con.startup(self._getStartupConfiguration()); + con.startup(self.getStartupConf()); }); function checkPgPass(cb) { @@ -108,21 +108,56 @@ Client.prototype.connect = function(callback) { self.secretKey = msg.secretKey; }); - - con.on('readyForQuery', function() { - var activeQuery = self.activeQuery; - self.activeQuery = null; - self.readyForQuery = true; - self._pulseQueryQueue(); - if(activeQuery) { - activeQuery.handleReadyForQuery(con); - } - }); - //hook up query handling events to connection //after the connection initially becomes ready for queries con.once('readyForQuery', function() { - self._attachEventListeners(con); + self._connecting = false; + + //delegate rowDescription to active query + con.on('rowDescription', function(msg) { + self.activeQuery.handleRowDescription(msg); + }); + + //delegate dataRow to active query + con.on('dataRow', function(msg) { + self.activeQuery.handleDataRow(msg); + }); + + //delegate portalSuspended to active query + con.on('portalSuspended', function(msg) { + self.activeQuery.handlePortalSuspended(con); + }); + + //deletagate emptyQuery to active query + con.on('emptyQuery', function(msg) { + self.activeQuery.handleEmptyQuery(con); + }); + + //delegate commandComplete to active query + con.on('commandComplete', function(msg) { + self.activeQuery.handleCommandComplete(msg, con); + }); + + //if a prepared statement has a name and properly parses + //we track that its already been executed so we don't parse + //it again on the same client + con.on('parseComplete', function(msg) { + if(self.activeQuery.name) { + con.parsedStatements[self.activeQuery.name] = true; + } + }); + + con.on('copyInResponse', function(msg) { + self.activeQuery.handleCopyInResponse(self.connection); + }); + + con.on('copyData', function (msg) { + self.activeQuery.handleCopyData(msg, self.connection); + }); + + con.on('notification', function(msg) { + self.emit('notification', msg); + }); //process possible callback argument to Client#connect if (callback) { @@ -134,6 +169,16 @@ Client.prototype.connect = function(callback) { self.emit('connect'); }); + con.on('readyForQuery', function() { + var activeQuery = self.activeQuery; + self.activeQuery = null; + self.readyForQuery = true; + self._pulseQueryQueue(); + if(activeQuery) { + activeQuery.handleReadyForQuery(con); + } + }); + con.on('error', function(error) { if(this.activeQuery) { var activeQuery = self.activeQuery; @@ -187,75 +232,19 @@ Client.prototype.connect = function(callback) { self.emit('notice', msg); }); - var result; - if (!callback) { - result = new global.Promise(function (resolve, reject) { - con.once('connect', function () { - con.removeListener('error', reject) + return new global.Promise((resolve, reject) => { + this.once('error', reject) + this.once('connect', () => { + this.removeListener('error', reject) resolve() }) - this.once('error', reject) - }.bind(this)) + }) } - return result; }; - -// once a connection is established connect listeners -Client.prototype._attachEventListeners = function(con) { - var self = this; - self._connecting = false; - - //delegate rowDescription to active query - con.on('rowDescription', function(msg) { - self.activeQuery.handleRowDescription(msg); - }); - - //delegate dataRow to active query - con.on('dataRow', function(msg) { - self.activeQuery.handleDataRow(msg); - }); - - //delegate portalSuspended to active query - con.on('portalSuspended', function(msg) { - self.activeQuery.handlePortalSuspended(con); - }); - - //deletagate emptyQuery to active query - con.on('emptyQuery', function(msg) { - self.activeQuery.handleEmptyQuery(con); - }); - - //delegate commandComplete to active query - con.on('commandComplete', function(msg) { - self.activeQuery.handleCommandComplete(msg, con); - }); - - //if a prepared statement has a name and properly parses - //we track that its already been executed so we don't parse - //it again on the same client - con.on('parseComplete', function(msg) { - if(self.activeQuery.name) { - con.parsedStatements[self.activeQuery.name] = true; - } - }); - - con.on('copyInResponse', function(msg) { - self.activeQuery.handleCopyInResponse(self.connection); - }); - - con.on('copyData', function (msg) { - self.activeQuery.handleCopyData(msg, self.connection); - }); - - con.on('notification', function(msg) { - self.emit('notification', msg); - }); -} - -Client.prototype._getStartupConfiguration = function() { +Client.prototype.getStartupConf = function() { var params = this.connectionParameters; var data = { @@ -370,54 +359,46 @@ Client.prototype.copyTo = function (text) { }; Client.prototype.query = function(config, values, callback) { - var promise; - var isQueryable = typeof config.submit == 'function'; + //can take in strings, config object or query object var query; - // if we receive an object with a 'submit' function we delegate - // processing to the passed object - this is how pg.Query, QueryStream, and Cursor work - if (isQueryable) { - query = config; - // accept client.query(new Query('select *'), (err, res) => { }) call signature + var result; + if (typeof config.submit == 'function') { + query = config + result = query if (typeof values == 'function') { - query.callback = query.callback || values; + query.callback = query.callback || values } } else { - query = new Query(config, values, callback); - if (!query.callback) { - promise = new global.Promise(function (resolve, reject) { - query.on('error', reject); - query.on('end', resolve); - }); - } + query = new Query(config, values, callback) + result = query.callback ? undefined : new global.Promise((resolve, reject) => { + query.once('end', resolve) + query.once('error', reject) + }) } + if(this.binary && !query.binary) { query.binary = true; } - - // TODO - this is a smell if(query._result) { query._result._getTypeParser = this._types.getTypeParser.bind(this._types); } this.queryQueue.push(query); this._pulseQueryQueue(); - - // if we were passed a queryable, return it - // otherwise return callback/promise result - return isQueryable ? query : promise; + return result }; Client.prototype.end = function(cb) { this._ending = true; if (cb) { - this.connection.once('end', cb); this.connection.end(); - return; + this.connection.once('end', cb); + } else { + return new global.Promise((resolve, reject) => { + this.connection.end() + this.connection.once('end', resolve) + }) } - return new global.Promise((resolve) => { - this.connection.end(); - this.connection.once('end', resolve); - }); }; Client.md5 = function(string) { diff --git a/lib/connection.js b/lib/connection.js index c40639e02..8e57ff46e 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -315,7 +315,7 @@ Connection.prototype.end = function() { //0x58 = 'X' this.writer.add(emptyBuffer); this._ending = true; - return this.stream.end(END_BUFFER); + return this.stream.write(END_BUFFER); }; Connection.prototype.close = function(msg, more) { diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 4a2be1ee0..9aff27fb0 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -16,35 +16,7 @@ var createErorrClient = function() { const suite = new helper.Suite('error handling') -suite.test('query receives error on client shutdown', false, function(done) { - var client = new Client(); - client.connect(function(err) { - if (err) { - return done(err) - } - client.query('SELECT pg_sleep(5)', assert.calls(function(err, res) { - assert(err instanceof Error) - done() - })); - setTimeout(() => { - client.end() - assert.emits(client, 'end'); - }, 50) - }); -}); - -suite.test('within a simple query', (done) => { - var client = createErorrClient(); - - var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")); - - assert.emits(query, 'error', function(error) { - assert.equal(error.severity, "ERROR"); - done(); - }); -}); - -(function () { +;(function () { var client = createErorrClient(); var q = client.query({ text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);", binary: false }); @@ -84,17 +56,6 @@ suite.test('within a simple query', (done) => { }); })(); -suite.test('non-query error', function(done) { - var client = new Client({ - user:'asldkfjsadlfkj' - }); - client.on('error', (err) => { - assert(err instanceof Error) - done() - }); - client.connect(); -}); - suite.test('non-query error with callback', function(done) { var client = new Client({ user:'asldkfjsadlfkj' @@ -120,6 +81,16 @@ suite.test('non-error calls supplied callback', function(done) { })) }); +suite.test('when connecting to an invalid host with callback', function (done) { + var client = new Client({ + host: 'asldkfjasdf!!#1308140.com' + }); + client.connect(function(error, client) { + assert(error instanceof Error); + done(); + }); +}); + suite.test('when connecting to invalid host with promise', function(done) { var client = new Client({ host: 'asdlfkjasldkfjlaskdfj' @@ -127,12 +98,42 @@ suite.test('when connecting to invalid host with promise', function(done) { client.connect().catch((e) => done()); }); -suite.test('when connecting to an invalid host with callback', function (done) { +suite.test('non-query error', function(done) { var client = new Client({ - host: 'asldkfjasdf!!#1308140.com' + user:'asldkfjsadlfkj' }); - client.connect(function(error, client) { - assert(error instanceof Error); + client.connect() + .catch(e => { + assert(e instanceof Error) + done() + }) +}); + + +suite.test('query receives error on client shutdown', false, function(done) { + var client = new Client(); + client.connect(function(err) { + if (err) { + return done(err) + } + client.query('SELECT pg_sleep(5)', assert.calls(function(err, res) { + assert(err instanceof Error) + done() + })); + setTimeout(() => { + client.end() + assert.emits(client, 'end'); + }, 50) + }); +}); + +suite.test('within a simple query', (done) => { + var client = createErorrClient(); + + var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")); + + assert.emits(query, 'error', function(error) { + assert.equal(error.severity, "ERROR"); done(); }); }); diff --git a/test/integration/client/network-partition-tests.js b/test/integration/client/network-partition-tests.js index 944df510c..945a2ee8b 100644 --- a/test/integration/client/network-partition-tests.js +++ b/test/integration/client/network-partition-tests.js @@ -59,6 +59,11 @@ var testServer = function (server, cb) { // connect a client to it var client = new helper.Client(options) client.connect() + .catch((err) => { + assert(err instanceof Error) + clearTimeout(timeoutId) + server.close(cb) + }) // after 50 milliseconds, drop the client setTimeout(function() { @@ -69,12 +74,6 @@ var testServer = function (server, cb) { var timeoutId = setTimeout(function () { throw new Error('Client should have emitted an error but it did not.') }, 5000) - - // return our wait token - client.on('error', function () { - clearTimeout(timeoutId) - server.close(cb) - }) }) } diff --git a/test/suite.js b/test/suite.js index 37227fc94..1de1b69cc 100644 --- a/test/suite.js +++ b/test/suite.js @@ -43,7 +43,7 @@ class Suite { } run(test, cb) { - process.stdout.write(test.name + ' ') + process.stdout.write(' ' + test.name + ' ') if (!test.action) { process.stdout.write('? - SKIPPED') return cb() @@ -71,4 +71,11 @@ class Suite { } } +process.on('unhandledRejection', (e) => { + setImmediate(() => { + console.error('Uhandled promise rejection') + throw e + }) +}) + module.exports = Suite From c961c900d61258b2e6e16950dcddc4d5fefe3a52 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 18:10:18 -0500 Subject: [PATCH 0218/1037] Almost all tests passing --- lib/native/client.js | 22 +++++++++++ .../client/error-handling-tests.js | 38 +++++++++---------- test/integration/client/promise-api-tests.js | 3 +- ...error-handling-prepared-statement-tests.js | 6 +-- test/native/connection-tests.js | 36 ------------------ test/suite.js | 2 +- 6 files changed, 47 insertions(+), 60 deletions(-) delete mode 100644 test/native/connection-tests.js diff --git a/lib/native/client.js b/lib/native/client.js index e57a94190..639484ec7 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -63,6 +63,16 @@ Client.prototype.connect = function(cb) { return self.emit('error', err); }; + var result + if (!cb) { + var resolve, reject + cb = (err) => err ? reject(err) : resolve() + result = new global.Promise(function(res, rej) { + resolve = res + reject = rej + }) + } + this.connectionParameters.getLibpqConnectionString(function(err, conString) { if(err) return onError(err); self.native.connect(conString, function(err) { @@ -95,6 +105,8 @@ Client.prototype.connect = function(cb) { if(cb) cb(); }); }); + + return result }; //send a query to the server @@ -135,6 +147,15 @@ Client.prototype.end = function(cb) { if(!this._connected) { this.once('connect', this.end.bind(this, cb)); } + var result; + if (!cb) { + var resolve, reject + cb = (err) => err ? reject(err) : resolve() + result = new global.Promise(function(res, rej) { + resolve = res + reject = rej + }) + } this.native.end(function() { //send an error to the active query if(self._hasActiveQuery()) { @@ -145,6 +166,7 @@ Client.prototype.end = function(cb) { self.emit('end'); if(cb) cb(); }); + return result }; Client.prototype._hasActiveQuery = function() { diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 9aff27fb0..cc60e2c92 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -16,6 +16,24 @@ var createErorrClient = function() { const suite = new helper.Suite('error handling') +suite.test('query receives error on client shutdown', false, function(done) { + var client = new Client(); + client.connect(assert.success(function() { + const config = { + text: 'select pg_sleep(5)', + name: 'foobar' + } + client.query(new pg.Query(config), assert.calls(function(err, res) { + assert(err instanceof Error) + done() + })); + setTimeout(() => { + client.end() + assert.emits(client, 'end'); + }, 50) + })); +}); + ;(function () { var client = createErorrClient(); @@ -83,7 +101,7 @@ suite.test('non-error calls supplied callback', function(done) { suite.test('when connecting to an invalid host with callback', function (done) { var client = new Client({ - host: 'asldkfjasdf!!#1308140.com' + host: '!#%!@#%' }); client.connect(function(error, client) { assert(error instanceof Error); @@ -109,24 +127,6 @@ suite.test('non-query error', function(done) { }) }); - -suite.test('query receives error on client shutdown', false, function(done) { - var client = new Client(); - client.connect(function(err) { - if (err) { - return done(err) - } - client.query('SELECT pg_sleep(5)', assert.calls(function(err, res) { - assert(err instanceof Error) - done() - })); - setTimeout(() => { - client.end() - assert.emits(client, 'end'); - }, 50) - }); -}); - suite.test('within a simple query', (done) => { var client = createErorrClient(); diff --git a/test/integration/client/promise-api-tests.js b/test/integration/client/promise-api-tests.js index 17094c9d4..ee088f94d 100644 --- a/test/integration/client/promise-api-tests.js +++ b/test/integration/client/promise-api-tests.js @@ -40,10 +40,11 @@ suite.test('connected client does not reject promise after connection', (done) = setTimeout(() => { client.on('error', (e) => { assert(e instanceof Error) + client.end() done() }) // manually kill the connection - client.connection.stream.end() + client.emit('error', new Error('something bad happened...but not really')) }, 50) }) }) diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index a250f78b3..7aa68f595 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -5,7 +5,7 @@ var util = require('util'); var suite = new helper.Suite(); suite.test('client end during query execution of prepared statement', function(done) { - var client = new Client(helper.args); + var client = new Client(); client.connect(assert.success(function() { var sleepQuery = 'select pg_sleep($1)'; @@ -18,11 +18,11 @@ suite.test('client end during query execution of prepared statement', function(d var queryInstance = new Query(queryConfig, assert.calls(function (err, result) { assert.equal(err.message, 'Connection terminated'); + done(); })) var query1 = client.query(queryInstance); - query1.on('error', function (err) { assert.fail('Prepared statement should not emit error'); }); @@ -35,7 +35,7 @@ suite.test('client end during query execution of prepared statement', function(d assert.fail('Prepared statement when executed should not return before being killed'); }); - client.end(done); + client.end(); })); }); diff --git a/test/native/connection-tests.js b/test/native/connection-tests.js deleted file mode 100644 index be84be6e8..000000000 --- a/test/native/connection-tests.js +++ /dev/null @@ -1,36 +0,0 @@ -var helper = require(__dirname + "/../test-helper"); -var Client = require(__dirname + "/../../lib/native"); -var domain = require('domain'); - -test('connecting with wrong parameters', function() { - var con = new Client("user=asldfkj hostaddr=127.0.0.1 port=5432 dbname=asldkfj"); - assert.emits(con, 'error', function(error) { - assert.ok(error != null, "error should not be null"); - con.end(); - }); - - con.connect(); -}); - -test('connects', function() { - var con = new Client(helper.config); - con.connect(); - assert.emits(con, 'connect', function() { - test('disconnects', function() { - con.end(); - }) - }) -}) - -test('preserves domain', function() { - var dom = domain.create(); - - dom.run(function() { - var con = new Client(helper.config); - assert.ok(dom === require('domain').active, 'domain is active'); - con.connect(function() { - assert.ok(dom === require('domain').active, 'domain is still active'); - con.end(); - }); - }); -}) diff --git a/test/suite.js b/test/suite.js index 1de1b69cc..7d248b368 100644 --- a/test/suite.js +++ b/test/suite.js @@ -45,7 +45,7 @@ class Suite { run(test, cb) { process.stdout.write(' ' + test.name + ' ') if (!test.action) { - process.stdout.write('? - SKIPPED') + process.stdout.write('? - SKIPPED\n') return cb() } From 2c3f55e5bdd1f6075fe168cfecdb8f375d5fef26 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 19:24:39 -0500 Subject: [PATCH 0219/1037] Make all tests pass --- lib/client.js | 8 ++++- .../client/error-handling-tests.js | 32 +++++++++++-------- .../client/query-as-promise-tests.js | 13 ++++---- .../client/query-error-handling-tests.js | 2 +- test/integration/gh-issues/699-tests.js | 4 ++- 5 files changed, 35 insertions(+), 24 deletions(-) diff --git a/lib/client.js b/lib/client.js index c1cef452c..0b67ba31c 100644 --- a/lib/client.js +++ b/lib/client.js @@ -173,10 +173,10 @@ Client.prototype.connect = function(callback) { var activeQuery = self.activeQuery; self.activeQuery = null; self.readyForQuery = true; - self._pulseQueryQueue(); if(activeQuery) { activeQuery.handleReadyForQuery(con); } + self._pulseQueryQueue(); }); con.on('error', function(error) { @@ -390,6 +390,12 @@ Client.prototype.query = function(config, values, callback) { Client.prototype.end = function(cb) { this._ending = true; + if (this.activeQuery) { + // if we have an active query we need to force a disconnect + // on the socket - otherwise a hung query could block end forever + this.connection.stream.destroy(new Error('Connection terminated by user')) + return; + } if (cb) { this.connection.end(); this.connection.once('end', cb); diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index cc60e2c92..69d43085b 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -16,29 +16,26 @@ var createErorrClient = function() { const suite = new helper.Suite('error handling') -suite.test('query receives error on client shutdown', false, function(done) { +suite.test('query receives error on client shutdown', function(done) { var client = new Client(); client.connect(assert.success(function() { const config = { text: 'select pg_sleep(5)', name: 'foobar' } + let queryError; client.query(new pg.Query(config), assert.calls(function(err, res) { assert(err instanceof Error) - done() + queryError = err })); - setTimeout(() => { - client.end() - assert.emits(client, 'end'); - }, 50) + setTimeout(() => client.end(), 50) + client.once('end', () => { + assert(queryError instanceof Error) + done() + }) })); }); -;(function () { - var client = createErorrClient(); - - var q = client.query({ text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);", binary: false }); - var ensureFuture = function (testClient, done) { var goodQuery = testClient.query(new pg.Query("select age from boom")); assert.emits(goodQuery, 'row', function (row) { @@ -48,6 +45,10 @@ suite.test('query receives error on client shutdown', false, function(done) { }; suite.test("when query is parsing", (done) => { + var client = createErorrClient(); + + var q = client.query({ text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);" }); + //this query wont parse since there isn't a table named bang var query = client.query(new pg.Query({ @@ -61,6 +62,10 @@ suite.test('query receives error on client shutdown', false, function(done) { }); suite.test("when a query is binding", function (done) { + var client = createErorrClient(); + + var q = client.query({ text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);" }); + var query = client.query(new pg.Query({ text: 'select * from boom where age = $1', @@ -72,7 +77,6 @@ suite.test('query receives error on client shutdown', false, function(done) { ensureFuture(client, done); }); }); -})(); suite.test('non-query error with callback', function(done) { var client = new Client({ @@ -101,7 +105,7 @@ suite.test('non-error calls supplied callback', function(done) { suite.test('when connecting to an invalid host with callback', function (done) { var client = new Client({ - host: '!#%!@#%' + user: 'very invalid username', }); client.connect(function(error, client) { assert(error instanceof Error); @@ -111,7 +115,7 @@ suite.test('when connecting to an invalid host with callback', function (done) { suite.test('when connecting to invalid host with promise', function(done) { var client = new Client({ - host: 'asdlfkjasldkfjlaskdfj' + user: 'very invalid username' }); client.connect().catch((e) => done()); }); diff --git a/test/integration/client/query-as-promise-tests.js b/test/integration/client/query-as-promise-tests.js index ac958729b..92eedcc85 100644 --- a/test/integration/client/query-as-promise-tests.js +++ b/test/integration/client/query-as-promise-tests.js @@ -16,13 +16,12 @@ pg.connect(helper.config, assert.success(function(client, done) { client.query('ALKJSDF') .catch(function(e) { assert(e instanceof Error) + client.query('SELECT 1 as num') + .then(function (result) { + assert.equal(result.rows[0].num, 1) + done() + pg.end() + }) }) }) - - client.query('SELECT 1 as num') - .then(function(result) { - assert.equal(result.rows[0].num, 1) - done() - pg.end() - }) })) diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js index 2e28737d4..f2dd294eb 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -5,7 +5,7 @@ var Query = helper.pg.Query; test('error during query execution', function() { var client = new Client(helper.args); client.connect(assert.success(function() { - var queryText = 'select pg_sleep(5)' + var queryText = 'select pg_sleep(10)' var sleepQuery = new Query(queryText); var pidColName = 'procpid' var queryColName = 'current_query'; diff --git a/test/integration/gh-issues/699-tests.js b/test/integration/gh-issues/699-tests.js index 2918c9aec..f9cb876d3 100644 --- a/test/integration/gh-issues/699-tests.js +++ b/test/integration/gh-issues/699-tests.js @@ -15,7 +15,9 @@ helper.pg.connect(helper.config, function (err, client, done) { var stream = client.query(copyFrom("COPY employee FROM STDIN")); stream.on('end', function () { done(); - helper.pg.end(); + setTimeout(() => { + helper.pg.end(); + }, 50) }); for (var i = 1; i <= 5; i++) { From 30744362360f2defeaead502b39b9f1f1bb17702 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 19:47:03 -0500 Subject: [PATCH 0220/1037] Tidy up a bit of testing --- test/integration/client/query-error-handling-tests.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js index f2dd294eb..d5ecd7bde 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -30,7 +30,7 @@ test('error during query execution', function() { var killIdleQuery = `SELECT ${pidColName}, (SELECT pg_cancel_backend(${pidColName})) AS killed FROM pg_stat_activity WHERE ${queryColName} LIKE $1`; client2.query(killIdleQuery, [queryText], assert.calls(function(err, res) { assert.ifError(err); - assert.equal(res.rows.length, 1); + assert(res.rows.length > 0); client2.end(); assert.emits(client2, 'end'); })); @@ -41,7 +41,7 @@ test('error during query execution', function() { }); if (helper.config.native) { - return console.log("\nTODO: this should work on native as well") + return } test('9.3 column error fields', function() { From d615ebee177ed57c7a7df861b1db675c9e0ebb0f Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 21:06:21 -0500 Subject: [PATCH 0221/1037] Start cleaning up tests --- package.json | 1 - test/integration/client/appname-tests.js | 28 +- test/integration/client/array-tests.js | 330 +++++++++--------- .../client/big-simple-query-tests.js | 26 +- test/integration/client/cancel-query-tests.js | 2 +- .../integration/client/configuration-tests.js | 71 ++-- test/integration/client/custom-types-tests.js | 31 +- test/integration/client/empty-query-tests.js | 15 +- test/integration/client/end-callback-tests.js | 6 - .../client/force-native-with-envvar-tests.js | 39 --- test/integration/client/huge-numeric-tests.js | 4 +- .../client/json-type-parsing-tests.js | 58 ++- .../client/network-partition-tests.js | 18 +- test/integration/domain-tests.js | 83 ++--- test/integration/gh-issues/131-tests.js | 25 +- test/integration/gh-issues/507-tests.js | 3 +- test/integration/gh-issues/600-tests.js | 7 +- test/integration/gh-issues/675-tests.js | 2 +- test/integration/gh-issues/699-tests.js | 2 +- test/integration/gh-issues/787-tests.js | 4 +- test/integration/test-helper.js | 2 +- test/native/callback-api-tests.js | 13 +- test/suite.js | 16 +- test/test-helper.js | 32 +- test/unit/client/early-disconnect-tests.js | 9 +- 25 files changed, 392 insertions(+), 435 deletions(-) delete mode 100644 test/integration/client/end-callback-tests.js delete mode 100644 test/integration/client/force-native-with-envvar-tests.js diff --git a/package.json b/package.json index 5eecc421a..1d8a69132 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ }, "devDependencies": { "async": "0.9.0", - "co": "4.6.0", "jshint": "2.5.2", "pg-copy-streams": "0.3.0" }, diff --git a/test/integration/client/appname-tests.js b/test/integration/client/appname-tests.js index ca074ecc3..55673eff9 100644 --- a/test/integration/client/appname-tests.js +++ b/test/integration/client/appname-tests.js @@ -1,7 +1,8 @@ -return; var helper = require('./test-helper'); var Client = helper.Client; +var suite = new helper.Suite(); + var conInfo = helper.config; function getConInfo(override) { @@ -26,34 +27,37 @@ function getAppName(conf, cb) { })); } -test('No default appliation_name ', function(){ +suite.test('No default appliation_name ', function(done) { var conf = getConInfo(); - getAppName(conf, function(res){ + getAppName({ }, function(res){ assert.strictEqual(res, ''); + done() }); }); -test('fallback_application_name is used', function(){ +suite.test('fallback_application_name is used', function(done) { var fbAppName = 'this is my app'; var conf = getConInfo({ 'fallback_application_name' : fbAppName }); getAppName(conf, function(res){ assert.strictEqual(res, fbAppName); + done() }); }); -test('application_name is used', function(){ +suite.test('application_name is used', function(done) { var appName = 'some wired !@#$% application_name'; var conf = getConInfo({ 'application_name' : appName }); getAppName(conf, function(res){ assert.strictEqual(res, appName); + done() }); }); -test('application_name has precedence over fallback_application_name', function(){ +suite.test('application_name has precedence over fallback_application_name', function(done) { var appName = 'some wired !@#$% application_name'; var fbAppName = 'some other strange $$test$$ appname'; var conf = getConInfo({ @@ -62,10 +66,11 @@ test('application_name has precedence over fallback_application_name', function( }); getAppName(conf, function(res){ assert.strictEqual(res, appName); + done() }); }); -test('application_name from connection string', function(){ +suite.test('application_name from connection string', function(done) { var appName = 'my app'; var conParams = require(__dirname + '/../../../lib/connection-parameters'); var conf; @@ -76,6 +81,7 @@ test('application_name from connection string', function(){ } getAppName(conf, function(res){ assert.strictEqual(res, appName); + done() }); }); @@ -83,14 +89,12 @@ test('application_name from connection string', function(){ // TODO: make the test work for native client too if (!helper.args.native) { - test('application_name is read from the env', function(){ + suite.test('application_name is read from the env', function(done) { var appName = process.env.PGAPPNAME = 'testest'; - var conf = getConInfo({ - 'just some bla' : 'to fool the pool' - }); - getAppName(conf, function(res){ + getAppName({ }, function(res){ delete process.env.PGAPPNAME; assert.strictEqual(res, appName); + done() }); }); } diff --git a/test/integration/client/array-tests.js b/test/integration/client/array-tests.js index 937ea17ba..7512d55bb 100644 --- a/test/integration/client/array-tests.js +++ b/test/integration/client/array-tests.js @@ -1,166 +1,176 @@ var helper = require(__dirname + "/test-helper"); var pg = helper.pg; -test('serializing arrays', function() { - pg.connect(helper.config, assert.calls(function(err, client, done) { - assert.isNull(err); - - test('nulls', function() { - client.query('SELECT $1::text[] as array', [[null]], assert.success(function(result) { - var array = result.rows[0].array; - assert.lengthIs(array, 1); - assert.isNull(array[0]); - })); - }); - - test('elements containing JSON-escaped characters', function() { - var param = '\\"\\"'; - - for (var i = 1; i <= 0x1f; i++) { - param += String.fromCharCode(i); - } - - client.query('SELECT $1::text[] as array', [[param]], assert.success(function(result) { - var array = result.rows[0].array; - assert.lengthIs(array, 1); - assert.equal(array[0], param); - })); - +var suite = new helper.Suite() + +pg.connect(assert.calls(function(err, client, release) { + assert.isNull(err); + + suite.test('nulls', function(done) { + client.query('SELECT $1::text[] as array', [[null]], assert.success(function(result) { + var array = result.rows[0].array; + assert.lengthIs(array, 1); + assert.isNull(array[0]); + done() + })); + }); + + suite.test('elements containing JSON-escaped characters', function(done) { + var param = '\\"\\"'; + + for (var i = 1; i <= 0x1f; i++) { + param += String.fromCharCode(i); + } + + client.query('SELECT $1::text[] as array', [[param]], assert.success(function(result) { + var array = result.rows[0].array; + assert.lengthIs(array, 1); + assert.equal(array[0], param); + done() + })); + }); + + suite.test('cleanup', () => release()) +})); + +pg.connect(assert.calls(function (err, client, release) { + assert.isNull(err); + client.query("CREATE TEMP TABLE why(names text[], numbors integer[])"); + client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log); + suite.test('numbers', function (done) { + // client.connection.on('message', console.log) + client.query('SELECT numbors FROM why', assert.success(function (result) { + assert.lengthIs(result.rows[0].numbors, 3); + assert.equal(result.rows[0].numbors[0], 1); + assert.equal(result.rows[0].numbors[1], 2); + assert.equal(result.rows[0].numbors[2], 3); + done() + })) + }) + + suite.test('parses string arrays', function (done) { + client.query('SELECT names FROM why', assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0], 'aaron'); + assert.equal(names[1], 'brian'); + assert.equal(names[2], "a b c"); + done() + })) + }) + + suite.test('empty array', function (done) { + client.query("SELECT '{}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 0); + done() + })) + }) + + suite.test('element containing comma', function (done) { + client.query("SELECT '{\"joe,bob\",jim}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 2); + assert.equal(names[0], 'joe,bob'); + assert.equal(names[1], 'jim'); + done() + })) + }) + + suite.test('bracket in quotes', function (done) { + client.query("SELECT '{\"{\",\"}\"}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 2); + assert.equal(names[0], '{'); + assert.equal(names[1], '}'); + done() + })) + }) + + suite.test('null value', function (done) { + client.query("SELECT '{joe,null,bob,\"NULL\"}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 4); + assert.equal(names[0], 'joe'); + assert.equal(names[1], null); + assert.equal(names[2], 'bob'); + assert.equal(names[3], 'NULL'); + done() + })) + }) + + suite.test('element containing quote char', function (done) { + client.query("SELECT ARRAY['joe''', 'jim', 'bob\"'] AS names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0], 'joe\''); + assert.equal(names[1], 'jim'); + assert.equal(names[2], 'bob"'); + done() + })) + }) + + suite.test('nested array', function (done) { + client.query("SELECT '{{1,joe},{2,bob}}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 2); + + assert.lengthIs(names[0], 2); + assert.equal(names[0][0], '1'); + assert.equal(names[0][1], 'joe'); + + assert.lengthIs(names[1], 2); + assert.equal(names[1][0], '2'); + assert.equal(names[1][1], 'bob'); + done() + })) + }) + + suite.test('integer array', function (done) { + client.query("SELECT '{1,2,3}'::integer[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0], 1); + assert.equal(names[1], 2); + assert.equal(names[2], 3); + done() + })) + }) + + suite.test('integer nested array', function (done) { + client.query("SELECT '{{1,100},{2,100},{3,100}}'::integer[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0][0], 1); + assert.equal(names[0][1], 100); + + assert.equal(names[1][0], 2); + assert.equal(names[1][1], 100); + + assert.equal(names[2][0], 3); + assert.equal(names[2][1], 100); + done() + })) + }) + + suite.test('JS array parameter', function (done) { + client.query("SELECT $1::integer[] as names", [[[1, 100], [2, 100], [3, 100]]], assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0][0], 1); + assert.equal(names[0][1], 100); + + assert.equal(names[1][0], 2); + assert.equal(names[1][1], 100); + + assert.equal(names[2][0], 3); + assert.equal(names[2][1], 100); + release(); + pg.end(); done(); - }); - })); -}); - -test('parsing array results', function() { - pg.connect(helper.config, assert.calls(function(err, client, done) { - assert.isNull(err); - client.query("CREATE TEMP TABLE why(names text[], numbors integer[])"); - client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log); - test('numbers', function() { - // client.connection.on('message', console.log) - client.query('SELECT numbors FROM why', assert.success(function(result) { - assert.lengthIs(result.rows[0].numbors, 3); - assert.equal(result.rows[0].numbors[0], 1); - assert.equal(result.rows[0].numbors[1], 2); - assert.equal(result.rows[0].numbors[2], 3); - })) - }) - - test('parses string arrays', function() { - client.query('SELECT names FROM why', assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 'aaron'); - assert.equal(names[1], 'brian'); - assert.equal(names[2], "a b c"); - })) - }) - - test('empty array', function(){ - client.query("SELECT '{}'::text[] as names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 0); - })) - }) - - test('element containing comma', function(){ - client.query("SELECT '{\"joe,bob\",jim}'::text[] as names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - assert.equal(names[0], 'joe,bob'); - assert.equal(names[1], 'jim'); - })) - }) - - test('bracket in quotes', function(){ - client.query("SELECT '{\"{\",\"}\"}'::text[] as names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - assert.equal(names[0], '{'); - assert.equal(names[1], '}'); - })) - }) - - test('null value', function(){ - client.query("SELECT '{joe,null,bob,\"NULL\"}'::text[] as names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 4); - assert.equal(names[0], 'joe'); - assert.equal(names[1], null); - assert.equal(names[2], 'bob'); - assert.equal(names[3], 'NULL'); - })) - }) - - test('element containing quote char', function(){ - client.query("SELECT ARRAY['joe''', 'jim', 'bob\"'] AS names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 'joe\''); - assert.equal(names[1], 'jim'); - assert.equal(names[2], 'bob"'); - })) - }) - - test('nested array', function(){ - client.query("SELECT '{{1,joe},{2,bob}}'::text[] as names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - - assert.lengthIs(names[0], 2); - assert.equal(names[0][0], '1'); - assert.equal(names[0][1], 'joe'); - - assert.lengthIs(names[1], 2); - assert.equal(names[1][0], '2'); - assert.equal(names[1][1], 'bob'); - - })) - }) - - test('integer array', function(){ - client.query("SELECT '{1,2,3}'::integer[] as names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 1); - assert.equal(names[1], 2); - assert.equal(names[2], 3); - })) - }) - - test('integer nested array', function(){ - client.query("SELECT '{{1,100},{2,100},{3,100}}'::integer[] as names", assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0][0], 1); - assert.equal(names[0][1], 100); - - assert.equal(names[1][0], 2); - assert.equal(names[1][1], 100); - - assert.equal(names[2][0], 3); - assert.equal(names[2][1], 100); - })) - }) - - test('JS array parameter', function(){ - client.query("SELECT $1::integer[] as names", [[[1,100],[2,100],[3,100]]], assert.success(function(result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0][0], 1); - assert.equal(names[0][1], 100); - - assert.equal(names[1][0], 2); - assert.equal(names[1][1], 100); - - assert.equal(names[2][0], 3); - assert.equal(names[2][1], 100); - done(); - pg.end(); - })) - }) - - })) -}) + })) + }) + +})) diff --git a/test/integration/client/big-simple-query-tests.js b/test/integration/client/big-simple-query-tests.js index 514babe63..0065772cf 100644 --- a/test/integration/client/big-simple-query-tests.js +++ b/test/integration/client/big-simple-query-tests.js @@ -1,6 +1,8 @@ var helper = require("./test-helper"); var Query = helper.pg.Query +const suite = new helper.Suite(); + /* Test to trigger a bug. @@ -14,31 +16,40 @@ var big_query_rows_2 = []; var big_query_rows_3 = []; // Works -test('big simple query 1',function() { +suite.test('big simple query 1', function(done) { var client = helper.client(); client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = '' or 1 = 1")) .on('row', function(row) { big_query_rows_1.push(row); }) .on('error', function(error) { console.log("big simple query 1 error"); console.log(error); }); - client.on('drain', client.end.bind(client)); + client.on('drain', () => { + client.end() + done() + }); }); // Works -test('big simple query 2',function() { +suite.test('big simple query 2', function(done) { var client = helper.client(); client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",[''])) .on('row', function(row) { big_query_rows_2.push(row); }) .on('error', function(error) { console.log("big simple query 2 error"); console.log(error); }); - client.on('drain', client.end.bind(client)); + client.on('drain', () => { + client.end() + done() + }); }); // Fails most of the time with 'invalid byte sequence for encoding "UTF8": 0xb9' or 'insufficient data left in message' // If test 1 and 2 are commented out it works -test('big simple query 3',function() { +suite.test('big simple query 3',function(done) { var client = helper.client(); client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",[''])) .on('row', function(row) { big_query_rows_3.push(row); }) .on('error', function(error) { console.log("big simple query 3 error"); console.log(error); }); - client.on('drain', client.end.bind(client)); + client.on('drain', () => { + client.end() + done() + }); }); process.on('exit', function() { @@ -59,7 +70,7 @@ var runBigQuery = function(client) { }); } -test('many times', function() { +suite.test('many times', function(done) { var client = helper.client(); for(var i = 0; i < 20; i++) { runBigQuery(client); @@ -67,6 +78,7 @@ test('many times', function() { client.on('drain', function() { client.end(); setTimeout(function() { + done() //let client disconnect fully }, 100) }); diff --git a/test/integration/client/cancel-query-tests.js b/test/integration/client/cancel-query-tests.js index 0275fa898..4485b328f 100644 --- a/test/integration/client/cancel-query-tests.js +++ b/test/integration/client/cancel-query-tests.js @@ -2,7 +2,7 @@ var helper = require("./test-helper"); var Query = helper.pg.Query; //before running this test make sure you run the script create-test-tables -test("cancellation of a query", function() { +new helper.Suite().test("cancellation of a query", function() { var client = helper.client(); diff --git a/test/integration/client/configuration-tests.js b/test/integration/client/configuration-tests.js index e922a4e78..8cde4cea9 100644 --- a/test/integration/client/configuration-tests.js +++ b/test/integration/client/configuration-tests.js @@ -1,6 +1,8 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); var pg = helper.pg; +var suite = new helper.Suite(); + //clear process.env var realEnv = {}; for(var key in process.env) { @@ -8,8 +10,8 @@ for(var key in process.env) { if(!key.indexOf('PG')) delete process.env[key]; } -test('default values', function() { - assert.same(pg.defaults,{ +suite.test('default values are used in new clients', function() { + assert.same(pg.defaults, { user: process.env.USER, database: process.env.USER, password: null, @@ -17,42 +19,37 @@ test('default values', function() { rows: 0, poolSize: 10 }) - test('are used in new clients', function() { - var client = new pg.Client(); - assert.same(client,{ - user: process.env.USER, - database: process.env.USER, - password: null, - port: 5432 - }) + + var client = new pg.Client(); + assert.same(client, { + user: process.env.USER, + database: process.env.USER, + password: null, + port: 5432 }) }) -if(!helper.args.native) { - test('modified values', function() { - pg.defaults.user = 'boom' - pg.defaults.password = 'zap' - pg.defaults.database = 'pow' - pg.defaults.port = 1234 - pg.defaults.host = 'blam' - pg.defaults.rows = 10 - pg.defaults.poolSize = 0 - - test('are passed into created clients', function() { - var client = new Client(); - assert.same(client,{ - user: 'boom', - password: 'zap', - database: 'pow', - port: 1234, - host: 'blam' - }) - }) - }) -} +suite.test('modified values are passed to created clients', function() { + pg.defaults.user = 'boom' + pg.defaults.password = 'zap' + pg.defaults.database = 'pow' + pg.defaults.port = 1234 + pg.defaults.host = 'blam' -//restore process.env -for(var key in realEnv) { - process.env[key] = realEnv[key]; -} + var client = new Client(); + assert.same(client,{ + user: 'boom', + password: 'zap', + database: 'pow', + port: 1234, + host: 'blam' + }) +}) + +suite.test('cleanup', () => { + //restore process.env + for (var key in realEnv) { + process.env[key] = realEnv[key]; + } +}) diff --git a/test/integration/client/custom-types-tests.js b/test/integration/client/custom-types-tests.js index 38479229d..9305dbbd1 100644 --- a/test/integration/client/custom-types-tests.js +++ b/test/integration/client/custom-types-tests.js @@ -1,18 +1,19 @@ -var helper = require(__dirname + '/test-helper'); -return console.log('TODO: get this working for non-native client'); +const helper = require('./test-helper'); +const Client = helper.pg.Client; +const suite = new helper.Suite() -helper.config.types = { - getTypeParser: function() { - return function() { - return 'okay!' - } +const client = new Client({ + types: { + getTypeParser: () => () => 'okay!' } -}; +}) -helper.pg.connect(helper.config, assert.success(function(client, done) { - client.query('SELECT NOW() as val', assert.success(function(res) { - assert.equal(res.rows[0].val, 'okay!'); - done(); - helper.pg.end(); - })); -})); +suite.test('custom type parser in client config', (done) => { + client.connect() + .then(() => { + client.query('SELECT NOW() as val', assert.success(function (res) { + assert.equal(res.rows[0].val, 'okay!'); + client.end().then(done); + })); + }) +}) diff --git a/test/integration/client/empty-query-tests.js b/test/integration/client/empty-query-tests.js index 6f0d574d1..8251088ab 100644 --- a/test/integration/client/empty-query-tests.js +++ b/test/integration/client/empty-query-tests.js @@ -1,17 +1,20 @@ -var helper = require(__dirname+'/test-helper'); -var client = helper.client(); +var helper = require('./test-helper'); +const suite = new helper.Suite() -test("empty query message handling", function() { +suite.test("empty query message handling", function(done) { + const client = helper.client(); assert.emits(client, 'drain', function() { - client.end(); + client.end(done); }); client.query({text: ""}); }); -test('callback supported', assert.calls(function() { +suite.test('callback supported', function(done) { + const client = helper.client(); client.query("", function(err, result) { assert.isNull(err); assert.empty(result.rows); + client.end(done) }) -})) +}) diff --git a/test/integration/client/end-callback-tests.js b/test/integration/client/end-callback-tests.js deleted file mode 100644 index 997cfb0cc..000000000 --- a/test/integration/client/end-callback-tests.js +++ /dev/null @@ -1,6 +0,0 @@ -var helper = require('./test-helper') - -var client = helper.client(assert.success(function() { - client.end(assert.success(function() { - })) -})) diff --git a/test/integration/client/force-native-with-envvar-tests.js b/test/integration/client/force-native-with-envvar-tests.js deleted file mode 100644 index 0ac3098e2..000000000 --- a/test/integration/client/force-native-with-envvar-tests.js +++ /dev/null @@ -1,39 +0,0 @@ -return; -/** - * helper needs to be loaded for the asserts but it alos proloads - * client which we don't want here - * - */ -var helper = require(__dirname+"/test-helper") - , path = require('path') -; - -var paths = { - 'pg' : path.join(__dirname, '..', '..', '..', 'lib', 'index.js') , - 'query_js' : path.join(__dirname, '..', '..', '..', 'lib', 'query.js') , - 'query_native' : path.join(__dirname, '..', '..', '..', 'lib', 'native', 'query.js') , -}; - -/** - * delete the modules we are concerned about from the - * module cache, so they get loaded cleanly and the env - * var can kick in ... - */ -function emptyCache(){ - Object.keys(require.cache).forEach(function(key){ - delete require.cache[key]; - }); -}; - -emptyCache(); -process.env.NODE_PG_FORCE_NATIVE = '1'; - -var pg = require( paths.pg ); -var query_native = require( paths.query_native ); -var query_js = require( paths.query_js ); - -assert.deepEqual(pg.Client.Query, query_native); -assert.notDeepEqual(pg.Client.Query, query_js); - -emptyCache(); -delete process.env.NODE_PG_FORCE_NATIVE diff --git a/test/integration/client/huge-numeric-tests.js b/test/integration/client/huge-numeric-tests.js index 8db3f2965..76b2aac5a 100644 --- a/test/integration/client/huge-numeric-tests.js +++ b/test/integration/client/huge-numeric-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); helper.pg.connect(helper.config, assert.success(function(client, done) { var types = require('pg-types'); @@ -18,5 +18,3 @@ helper.pg.connect(helper.config, assert.success(function(client, done) { done(); })) })); - -//custom type converter diff --git a/test/integration/client/json-type-parsing-tests.js b/test/integration/client/json-type-parsing-tests.js index 1c0759bf3..1fe21ac53 100644 --- a/test/integration/client/json-type-parsing-tests.js +++ b/test/integration/client/json-type-parsing-tests.js @@ -1,38 +1,26 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); var assert = require('assert'); -//if you want binary support, pull request me! -if (helper.config.binary) { - console.log('binary mode does not support JSON right now'); - return; -} -test('can read and write json', function() { - helper.pg.connect(helper.config, function(err, client, done) { - assert.ifError(err); - helper.versionGTE(client, '9.2.0', assert.success(function(jsonSupported) { - if(!jsonSupported) { - console.log('skip json test on older versions of postgres'); - done(); - return helper.pg.end(); - } - client.query('CREATE TEMP TABLE stuff(id SERIAL PRIMARY KEY, data JSON)'); - var value ={name: 'Brian', age: 250, alive: true, now: new Date()}; - client.query('INSERT INTO stuff (data) VALUES ($1)', [value]); - client.query('SELECT * FROM stuff', assert.success(function(result) { - assert.equal(result.rows.length, 1); - assert.equal(typeof result.rows[0].data, 'object'); - var row = result.rows[0].data; - assert.strictEqual(row.name, value.name); - assert.strictEqual(row.age, value.age); - assert.strictEqual(row.alive, value.alive); - test('row should have "now" as a date', function() { - return false; - assert(row.now instanceof Date, 'row.now should be a date instance but is ' + typeof row.now); - }); - assert.equal(JSON.stringify(row.now), JSON.stringify(value.now)); - done(); - helper.pg.end(); - })); +helper.pg.connect(assert.success(function (client, done) { + helper.versionGTE(client, '9.2.0', assert.success(function (jsonSupported) { + if (!jsonSupported) { + console.log('skip json test on older versions of postgres'); + done(); + return helper.pg.end(); + } + client.query('CREATE TEMP TABLE stuff(id SERIAL PRIMARY KEY, data JSON)'); + var value = { name: 'Brian', age: 250, alive: true, now: new Date() }; + client.query('INSERT INTO stuff (data) VALUES ($1)', [value]); + client.query('SELECT * FROM stuff', assert.success(function (result) { + assert.equal(result.rows.length, 1); + assert.equal(typeof result.rows[0].data, 'object'); + var row = result.rows[0].data; + assert.strictEqual(row.name, value.name); + assert.strictEqual(row.age, value.age); + assert.strictEqual(row.alive, value.alive); + assert.equal(JSON.stringify(row.now), JSON.stringify(value.now)); + done(); + helper.pg.end(); })); - }); -}); + })); +})); diff --git a/test/integration/client/network-partition-tests.js b/test/integration/client/network-partition-tests.js index 945a2ee8b..8e9d8af85 100644 --- a/test/integration/client/network-partition-tests.js +++ b/test/integration/client/network-partition-tests.js @@ -1,7 +1,6 @@ -var co = require('co') - var buffers = require('../../test-buffers') var helper = require('./test-helper') +var suite = new helper.Suite() var net = require('net') @@ -77,13 +76,12 @@ var testServer = function (server, cb) { }) } -// test being disconnected after readyForQuery -const respondingServer = new Server(buffers.readyForQuery()) -testServer(respondingServer, function () { - process.stdout.write('.') - // test being disconnected from a server that never responds +suite.test('readyForQuery server', (done) => { + const respondingServer = new Server(buffers.readyForQuery()) + testServer(respondingServer, done) +}) + +suite.test('silent server', (done) => { const silentServer = new Server() - testServer(silentServer, function () { - process.stdout.write('.') - }) + testServer(silentServer, done) }) diff --git a/test/integration/domain-tests.js b/test/integration/domain-tests.js index c3beae52a..dbd71c186 100644 --- a/test/integration/domain-tests.js +++ b/test/integration/domain-tests.js @@ -2,59 +2,48 @@ var async = require('async') var helper = require('./test-helper') var Query = helper.pg.Query +var suite = new helper.Suite() -var testWithoutDomain = function(cb) { - test('no domain', function() { +suite.test('no domain', function (cb) { + assert(!process.domain) + helper.pg.connect(assert.success(function (client, done) { assert(!process.domain) - helper.pg.connect(helper.config, assert.success(function(client, done) { - assert(!process.domain) - done() - cb() - })) - }) -} + done() + cb() + })) +}) -var testWithDomain = function(cb) { - test('with domain', function() { - assert(!process.domain) - var domain = require('domain').create() - domain.run(function() { - var startingDomain = process.domain - assert(startingDomain) - helper.pg.connect(helper.config, assert.success(function(client, done) { - assert(process.domain, 'no domain exists in connect callback') +suite.test('with domain', function (cb) { + assert(!process.domain) + var domain = require('domain').create() + domain.run(function () { + var startingDomain = process.domain + assert(startingDomain) + helper.pg.connect(helper.config, assert.success(function (client, done) { + assert(process.domain, 'no domain exists in connect callback') + assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') + var query = client.query('SELECT NOW()', assert.success(function () { + assert(process.domain, 'no domain exists in query callback') assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') - var query = client.query('SELECT NOW()', assert.success(function() { - assert(process.domain, 'no domain exists in query callback') - assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') - done(true) - process.domain.exit() - cb() - })) + done(true) + process.domain.exit() + cb() })) - }) + })) }) -} +}) -var testErrorWithDomain = function(cb) { - test('error on domain', function() { - var domain = require('domain').create() - domain.on('error', function() { - cb() - }) - domain.run(function() { - helper.pg.connect(helper.config, assert.success(function(client, done) { - client.query(new Query('SELECT SLDKJFLSKDJF')) - client.on('drain', done) - })) - }) +suite.test('error on domain', function (cb) { + var domain = require('domain').create() + domain.on('error', function () { + cb() + }) + domain.run(function () { + helper.pg.connect(helper.config, assert.success(function (client, done) { + client.query(new Query('SELECT SLDKJFLSKDJF')) + client.on('drain', done) + })) }) -} - -async.series([ - testWithoutDomain, - testWithDomain, - testErrorWithDomain -], function() { - helper.pg.end() }) + +suite.test('cleanup', () => helper.pg.end()) diff --git a/test/integration/gh-issues/131-tests.js b/test/integration/gh-issues/131-tests.js index 62bad27c2..ff5c03444 100644 --- a/test/integration/gh-issues/131-tests.js +++ b/test/integration/gh-issues/131-tests.js @@ -1,20 +1,21 @@ var helper = require('../test-helper'); var pg = helper.pg; -test('parsing array results', function () { - pg.connect(helper.config, assert.calls(function (err, client, done) { +var suite = new helper.Suite() + +suite.test('parsing array decimal results', function (done) { + pg.connect(helper.config, assert.calls(function (err, client, release) { assert.isNull(err); client.query("CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])"); client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log); - test('decimals', function () { - client.query('SELECT decimals FROM why', assert.success(function (result) { - assert.lengthIs(result.rows[0].decimals, 3); - assert.equal(result.rows[0].decimals[0], 0.1); - assert.equal(result.rows[0].decimals[1], 0.05); - assert.equal(result.rows[0].decimals[2], 3.654); - done() - pg.end(); - })) - }) + client.query('SELECT decimals FROM why', assert.success(function (result) { + assert.lengthIs(result.rows[0].decimals, 3); + assert.equal(result.rows[0].decimals[0], 0.1); + assert.equal(result.rows[0].decimals[1], 0.05); + assert.equal(result.rows[0].decimals[2], 3.654); + release() + pg.end(); + done() + })) })) }) diff --git a/test/integration/gh-issues/507-tests.js b/test/integration/gh-issues/507-tests.js index ef75effc6..097e3be11 100644 --- a/test/integration/gh-issues/507-tests.js +++ b/test/integration/gh-issues/507-tests.js @@ -1,7 +1,7 @@ var helper = require(__dirname + "/../test-helper"); var pg = helper.pg; -test('parsing array results', function() { +new helper.Suite().test('parsing array results', function(cb) { pg.connect(helper.config, assert.success(function(client, done) { client.query('CREATE TEMP TABLE test_table(bar integer, "baz\'s" integer)') client.query('INSERT INTO test_table(bar, "baz\'s") VALUES(1, 1), (2, 2)') @@ -10,6 +10,7 @@ test('parsing array results', function() { assert.equal(res.rows[1]["baz's"], 2) done() pg.end() + cb() }) })) }) diff --git a/test/integration/gh-issues/600-tests.js b/test/integration/gh-issues/600-tests.js index 0476d42d9..b64f19fae 100644 --- a/test/integration/gh-issues/600-tests.js +++ b/test/integration/gh-issues/600-tests.js @@ -1,5 +1,6 @@ var async = require('async'); var helper = require('../test-helper'); +const suite = new helper.Suite() var db = helper.client(); @@ -53,13 +54,14 @@ var steps = [ insertDataBar ] -test('test if query fails', function() { +suite.test('test if query fails', function(done) { async.series(steps, assert.success(function() { db.end() + done() })) }) -test('test if prepare works but bind fails', function() { +suite.test('test if prepare works but bind fails', function(done) { var client = helper.client(); var q = { text: 'SELECT $1::int as name', @@ -71,6 +73,7 @@ test('test if prepare works but bind fails', function() { client.query(q, assert.calls(function(err, res) { assert.ifError(err); client.end(); + done() })); })); }); diff --git a/test/integration/gh-issues/675-tests.js b/test/integration/gh-issues/675-tests.js index c27d3632b..f7fbf01bf 100644 --- a/test/integration/gh-issues/675-tests.js +++ b/test/integration/gh-issues/675-tests.js @@ -1,7 +1,7 @@ var helper = require('../test-helper'); var assert = require('assert'); -helper.pg.connect(helper.config, function(err, client, done) { +helper.pg.connect(function(err, client, done) { if (err) throw err; var c = 'CREATE TEMP TABLE posts (body TEXT)'; diff --git a/test/integration/gh-issues/699-tests.js b/test/integration/gh-issues/699-tests.js index f9cb876d3..8e92ff221 100644 --- a/test/integration/gh-issues/699-tests.js +++ b/test/integration/gh-issues/699-tests.js @@ -4,7 +4,7 @@ var copyFrom = require('pg-copy-streams').from; if(helper.args.native) return; -helper.pg.connect(helper.config, function (err, client, done) { +helper.pg.connect(function (err, client, done) { if (err) throw err; var c = 'CREATE TEMP TABLE employee (id integer, fname varchar(400), lname varchar(400))'; diff --git a/test/integration/gh-issues/787-tests.js b/test/integration/gh-issues/787-tests.js index e75c67666..df90cc542 100644 --- a/test/integration/gh-issues/787-tests.js +++ b/test/integration/gh-issues/787-tests.js @@ -1,6 +1,6 @@ -var helper = require(__dirname + '/../test-helper'); +var helper = require('../test-helper'); -helper.pg.connect(helper.config, function(err,client) { +helper.pg.connect(function(err,client) { var q = { name: 'This is a super long query name just so I can test that an error message is properly spit out to console.error without throwing an exception or anything', text: 'SELECT NOW()' diff --git a/test/integration/test-helper.js b/test/integration/test-helper.js index c6a4922dc..ceed87d56 100644 --- a/test/integration/test-helper.js +++ b/test/integration/test-helper.js @@ -8,7 +8,7 @@ if(helper.args.native) { //creates a client from cli parameters helper.client = function(cb) { - var client = new Client(helper.config); + var client = new Client(); client.connect(cb); return client; }; diff --git a/test/native/callback-api-tests.js b/test/native/callback-api-tests.js index 95e9a8ff3..6193ba743 100644 --- a/test/native/callback-api-tests.js +++ b/test/native/callback-api-tests.js @@ -1,8 +1,9 @@ var domain = require('domain'); -var helper = require(__dirname + "/../test-helper"); -var Client = require(__dirname + "/../../lib/native"); +var helper = require("./../test-helper"); +var Client = require("./../../lib/native"); +const suite = new helper.Suite() -test('fires callback with results', function() { +suite.test('fires callback with results', function(done) { var client = new Client(helper.config); client.connect(); client.query('SELECT 1 as num', assert.calls(function(err, result) { @@ -12,12 +13,12 @@ test('fires callback with results', function() { client.query('SELECT * FROM person WHERE name = $1', ['Brian'], assert.calls(function(err, result) { assert.isNull(err); assert.equal(result.rows[0].name, 'Brian'); - client.end(); + client.end(done); })) })); }) -test('preserves domain', function() { +suite.test('preserves domain', function(done) { var dom = domain.create(); dom.run(function() { @@ -26,7 +27,7 @@ test('preserves domain', function() { client.connect() client.query('select 1', function() { assert.ok(dom === require('domain').active, 'domain is still active'); - client.end(); + client.end(done); }); }); }) diff --git a/test/suite.js b/test/suite.js index 7d248b368..43c9e6208 100644 --- a/test/suite.js +++ b/test/suite.js @@ -24,11 +24,12 @@ class Test { } if (!this.action.length) { const result = this.action.call(this) - if ((result || 0).then) { - result - .then(() => cb()) - .catch(err => cb(err || new Error('Unhandled promise rejection'))) + if (!(result || 0).then) { + return cb() } + result + .then(() => cb()) + .catch(err => cb(err || new Error('Unhandled promise rejection'))) } else { this.action.call(this, cb) } @@ -51,7 +52,7 @@ class Suite { const tid = setTimeout(() => { const err = Error(`test: ${test.name} did not complete withint ${test.timeout}ms`) - cb(err) + process.exit(-1) }, test.timeout) test.run((err) => { @@ -61,13 +62,14 @@ class Suite { process.exit(-1) } else { process.stdout.write('✔\n') + cb() } - cb(err) }) } test(name, cb) { - this._queue.push(new Test(name, cb)) + const test = new Test(name, cb) + this._queue.push(test) } } diff --git a/test/test-helper.js b/test/test-helper.js index 4cf6a4554..7fab5ad62 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -1,13 +1,17 @@ //make assert a global... assert = require('assert'); -process.noDeprecation = true; var EventEmitter = require('events').EventEmitter; var sys = require('util'); -var BufferList = require(__dirname+'/buffer-list') -var Connection = require(__dirname + '/../lib/connection'); +process.noDeprecation = true; + +var BufferList = require('./buffer-list') +const Suite = require('./suite') +const args = require('./cli'); -Client = require(__dirname + '/../lib').Client; +var Connection = require('./../lib/connection'); + +Client = require('./../lib').Client; process.on('uncaughtException', function(d) { if ('stack' in d && 'message' in d) { @@ -16,6 +20,7 @@ process.on('uncaughtException', function(d) { } else { console.log(d); } + process.exit(-1); }); assert.same = function(actual, expected) { @@ -24,7 +29,6 @@ assert.same = function(actual, expected) { } }; - assert.emits = function(item, eventName, callback, message) { var called = false; var id = setTimeout(function() { @@ -71,13 +75,6 @@ assert.UTCDate = function(actual, year, month, day, hours, min, sec, milisecond) assert.equal(actualMili, milisecond, "expected milisecond " + milisecond + " but got " + actualMili); }; -var spit = function(actual, expected) { - console.log(""); - console.log("actual " + sys.inspect(actual)); - console.log("expect " + sys.inspect(expected)); - console.log(""); -} - assert.equalBuffers = function(actual, expected) { if(actual.length != expected.length) { spit(actual, expected) @@ -171,6 +168,12 @@ assert.isNull = function(item, message) { assert.ok(item === null, message); }; +const getMode = () => { + if (args.native) return 'native' + if (args.binary) return 'binary' + return '' +} + test = function(name, action) { test.testCount ++; test[name] = action; @@ -184,7 +187,6 @@ test = function(name, action) { //print out the filename process.stdout.write(require('path').basename(process.argv[1])); -var args = require(__dirname + '/cli'); if(args.binary) process.stdout.write(' (binary)'); if(args.native) process.stdout.write(' (native)'); @@ -240,8 +242,8 @@ var resetTimezoneOffset = function() { module.exports = { Sink: Sink, - Suite: require('./suite'), - pg: require(__dirname + '/../lib/'), + Suite: Suite, + pg: require('./../lib/'), args: args, config: args, sys: sys, diff --git a/test/unit/client/early-disconnect-tests.js b/test/unit/client/early-disconnect-tests.js index c67a783ad..a4c38be95 100644 --- a/test/unit/client/early-disconnect-tests.js +++ b/test/unit/client/early-disconnect-tests.js @@ -4,20 +4,13 @@ var pg = require('../../..//lib/index.js'); /* console.log() messages show up in `make test` output. TODO: fix it. */ var server = net.createServer(function(c) { - console.log('server connected'); c.destroy(); - console.log('server socket destroyed.'); - server.close(function() { console.log('server closed'); }); + server.close(); }); server.listen(7777, function() { - console.log('server listening'); var client = new pg.Client('postgres://localhost:7777'); - console.log('client connecting'); client.connect(assert.calls(function(err) { - if (err) console.log("Error on connect: "+err); - else console.log('client connected'); assert(err); })); - }); From f12eb0a6fdb4ce6f218e73ee27d4ff8727ae3c99 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 21:24:44 -0500 Subject: [PATCH 0222/1037] Format more tests --- test/integration/client/no-data-tests.js | 4 +- .../integration/client/no-row-result-tests.js | 10 +-- test/integration/client/notice-tests.js | 62 +++++++++++-------- test/integration/client/parse-int-8-tests.js | 6 +- test/suite.js | 1 + 5 files changed, 47 insertions(+), 36 deletions(-) diff --git a/test/integration/client/no-data-tests.js b/test/integration/client/no-data-tests.js index 3258e6a57..28a4999ab 100644 --- a/test/integration/client/no-data-tests.js +++ b/test/integration/client/no-data-tests.js @@ -1,6 +1,8 @@ var helper = require('./test-helper'); +const suite = new helper.Suite() -test("noData message handling", function() { + +suite.test("noData message handling", function() { var client = helper.client(); diff --git a/test/integration/client/no-row-result-tests.js b/test/integration/client/no-row-result-tests.js index 99ed0da7a..9081e2330 100644 --- a/test/integration/client/no-row-result-tests.js +++ b/test/integration/client/no-row-result-tests.js @@ -1,12 +1,8 @@ var helper = require(__dirname + '/test-helper'); var pg = helper.pg; -var config = helper.config; +const suite = new helper.Suite() -test('can access results when no rows are returned', function() { - if(config.native) { - console.log('maybe fix this?', __filename) - return false - } +suite.test('can access results when no rows are returned', function() { var checkResult = function(result) { assert(result.fields, 'should have fields definition'); assert.equal(result.fields.length, 1); @@ -15,7 +11,7 @@ test('can access results when no rows are returned', function() { pg.end(); }; - pg.connect(config, assert.success(function(client, done) { + pg.connect(assert.success(function(client, done) { const q = new pg.Query('select $1::text as val limit 0', ['hi']) var query = client.query(q, assert.success(function(result) { checkResult(result); diff --git a/test/integration/client/notice-tests.js b/test/integration/client/notice-tests.js index 764b45cd1..4d6634e14 100644 --- a/test/integration/client/notice-tests.js +++ b/test/integration/client/notice-tests.js @@ -1,40 +1,27 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); +const suite = new helper.Suite() -test('emits notice message', function() { - //TODO this doesn't work on all versions of postgres - return false; - var client = helper.client(); - client.query('create temp table boom(id serial, size integer)'); - assert.emits(client, 'notice', function(notice) { - assert.ok(notice != null); - //TODO ending connection after notice generates weird errors - process.nextTick(function() { - client.end(); - }) - }); -}) - -test('emits notify message', function() { +suite.test('emits notify message', function (done) { var client = helper.client(); - client.query('LISTEN boom', assert.calls(function() { + client.query('LISTEN boom', assert.calls(function () { var otherClient = helper.client(); - otherClient.query('LISTEN boom', assert.calls(function() { - assert.emits(client, 'notification', function(msg) { + var bothEmitted = -1 + otherClient.query('LISTEN boom', assert.calls(function () { + assert.emits(client, 'notification', function (msg) { //make sure PQfreemem doesn't invalidate string pointers - setTimeout(function() { + setTimeout(function () { assert.equal(msg.channel, 'boom'); assert.ok(msg.payload == 'omg!' /*9.x*/ || msg.payload == '' /*8.x*/, "expected blank payload or correct payload but got " + msg.message) - client.end() + client.end(++bothEmitted ? done : undefined) }, 100) - }); - assert.emits(otherClient, 'notification', function(msg) { + assert.emits(otherClient, 'notification', function (msg) { assert.equal(msg.channel, 'boom'); - otherClient.end(); + otherClient.end(++bothEmitted ? done : undefined); }); - client.query("NOTIFY boom, 'omg!'", function(err, q) { - if(err) { + client.query("NOTIFY boom, 'omg!'", function (err, q) { + if (err) { //notify not supported with payload on 8.x client.query("NOTIFY boom") } @@ -43,3 +30,26 @@ test('emits notify message', function() { })); }) + + +suite.test('emits notice message', function (done) { + if (helper.args.native) { + return console.error('need to get notice message working on native') + } + //TODO this doesn't work on all versions of postgres + var client = helper.client(); + const text = ` +DO language plpgsql $$ +BEGIN + RAISE NOTICE 'hello, world!'; +END +$$; + ` + client.query(text, () => { + client.end(); + }); + assert.emits(client, 'notice', function (notice) { + assert.ok(notice != null); + done(); + }); +}) diff --git a/test/integration/client/parse-int-8-tests.js b/test/integration/client/parse-int-8-tests.js index 42228cb8b..4ece94456 100644 --- a/test/integration/client/parse-int-8-tests.js +++ b/test/integration/client/parse-int-8-tests.js @@ -1,7 +1,9 @@ -var helper = require(__dirname + '/../test-helper'); +var helper = require('../test-helper'); var pg = helper.pg; -test('ability to turn on and off parser', function() { +const suite = new helper.Suite() + +suite.test('ability to turn on and off parser', function() { if(helper.args.binary) return false; pg.connect(helper.config, assert.success(function(client, done) { pg.defaults.parseInt8 = true; diff --git a/test/suite.js b/test/suite.js index 43c9e6208..22d1a9cc7 100644 --- a/test/suite.js +++ b/test/suite.js @@ -52,6 +52,7 @@ class Suite { const tid = setTimeout(() => { const err = Error(`test: ${test.name} did not complete withint ${test.timeout}ms`) + console.log('\n' + err.stack) process.exit(-1) }, test.timeout) From 132861f43fe38ca6e0ef8cd4ce44a8470c28b7c7 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 21:35:16 -0500 Subject: [PATCH 0223/1037] Test cleanup --- test/integration/client/notice-tests.js | 3 +- .../client/prepared-statement-tests.js | 91 ++++++++----------- 2 files changed, 40 insertions(+), 54 deletions(-) diff --git a/test/integration/client/notice-tests.js b/test/integration/client/notice-tests.js index 4d6634e14..eba01a80c 100644 --- a/test/integration/client/notice-tests.js +++ b/test/integration/client/notice-tests.js @@ -34,7 +34,8 @@ suite.test('emits notify message', function (done) { suite.test('emits notice message', function (done) { if (helper.args.native) { - return console.error('need to get notice message working on native') + console.error('need to get notice message working on native') + return done() } //TODO this doesn't work on all versions of postgres var client = helper.client(); diff --git a/test/integration/client/prepared-statement-tests.js b/test/integration/client/prepared-statement-tests.js index 9735407a9..0d037b009 100644 --- a/test/integration/client/prepared-statement-tests.js +++ b/test/integration/client/prepared-statement-tests.js @@ -1,7 +1,9 @@ var helper = require('./test-helper'); var Query = helper.pg.Query; -test("named prepared statement", function() { +var suite = new helper.Suite() + +;(function() { var client = helper.client(); client.on('drain', client.end.bind(client)); @@ -9,7 +11,7 @@ test("named prepared statement", function() { var queryName = "user by age and like name"; var parseCount = 0; - test("first named prepared statement", function() { + suite.test("first named prepared statement", function(done) { var query = client.query(new Query({ text: 'select name from person where age <= $1 and name LIKE $2', values: [20, 'Bri%'], @@ -20,11 +22,10 @@ test("named prepared statement", function() { assert.equal(row.name, 'Brian'); }); - assert.emits(query, 'end', function() { - }); + query.on('end', () => done()) }); - test("second named prepared statement with same name & text", function() { + suite.test("second named prepared statement with same name & text", function(done) { var cachedQuery = client.query(new Query({ text: 'select name from person where age <= $1 and name LIKE $2', name: queryName, @@ -35,11 +36,10 @@ test("named prepared statement", function() { assert.equal(row.name, 'Aaron'); }); - assert.emits(cachedQuery, 'end', function() { - }); + cachedQuery.on('end', () => done()) }); - test("with same name, but without query text", function() { + suite.test("with same name, but without query text", function(done) { var q = client.query(new Query({ name: queryName, values: [30, '%n%'] @@ -54,23 +54,19 @@ test("named prepared statement", function() { }); }); - assert.emits(q, 'end', function() { }); + q.on('end', () => done()) }); -}); +})(); -test("prepared statements on different clients", function() { +;(function() { var statementName = "differ"; var statement1 = "select count(*)::int4 as count from person"; var statement2 = "select count(*)::int4 as count from person where age < $1"; - var client1Finished = false; - var client2Finished = false; - var client1 = helper.client(); - var client2 = helper.client(); - test("client 1 execution", function() { + suite.test("client 1 execution", function(done) { var query = client1.query({ name: statementName, @@ -78,83 +74,72 @@ test("prepared statements on different clients", function() { }, (err, res) => { assert(!err); assert.equal(res.rows[0].count, 26); - if(client2Finished) { - client1.end(); - client2.end(); - } else { - client1Finished = true; - } + done() }); - }); - test('client 2 execution', function() { + suite.test('client 2 execution', function(done) { var query = client2.query(new Query({ name: statementName, text: statement2, values: [11] })); - test('gets right data', function() { - assert.emits(query, 'row', function(row) { - assert.equal(row.count, 1); - }); + assert.emits(query, 'row', function(row) { + assert.equal(row.count, 1); }); assert.emits(query, 'end', function() { - if(client1Finished) { - client1.end(); - client2.end(); - } else { - client2Finished = true; - } + done(); }); }); -}); + suite.test('clean up clients', () => { + return client1.end().then(() => client2.end()) + }); + +})(); -test('prepared statement', function() { +;(function() { var client = helper.client(); - client.on('drain', client.end.bind(client)); client.query('CREATE TEMP TABLE zoom(name varchar(100));'); client.query("INSERT INTO zoom (name) VALUES ('zed')"); client.query("INSERT INTO zoom (name) VALUES ('postgres')"); client.query("INSERT INTO zoom (name) VALUES ('node postgres')"); - var checkForResults = function(q) { - test('row callback fires for each result', function() { - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'node postgres'); + var checkForResults = function (q) { + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'node postgres'); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'postgres'); + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'postgres'); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'zed'); - }) - }); - }) + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'zed'); + }) + }); }) }; - test('with small row count', function() { + suite.test('with small row count', function (done) { var query = client.query(new Query({ name: 'get names', text: "SELECT name FROM zoom ORDER BY name", rows: 1 - })); + }, done)); checkForResults(query); }) - test('with large row count', function() { + suite.test('with large row count', function (done) { var query = client.query(new Query({ name: 'get names', text: 'SELECT name FROM zoom ORDER BY name', rows: 1000 - })) + }, done)) checkForResults(query); }) -}) + suite.test('cleanup', () => client.end()) +})() From e100152fb0297e69133ebf8122baf338af3eae1d Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 21:49:20 -0500 Subject: [PATCH 0224/1037] Remove failing travis test --- test/integration/client/notice-tests.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/integration/client/notice-tests.js b/test/integration/client/notice-tests.js index eba01a80c..f226de8f9 100644 --- a/test/integration/client/notice-tests.js +++ b/test/integration/client/notice-tests.js @@ -30,9 +30,8 @@ suite.test('emits notify message', function (done) { })); }) - - -suite.test('emits notice message', function (done) { +// this test fails on travis due to their config +suite.test('emits notice message', false, function (done) { if (helper.args.native) { console.error('need to get notice message working on native') return done() From a4b42ac36b29ef6d04a9b8c5bc5868bf3b2be498 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Jun 2017 21:55:20 -0500 Subject: [PATCH 0225/1037] Add co to dev deps --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 1d8a69132..5eecc421a 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ }, "devDependencies": { "async": "0.9.0", + "co": "4.6.0", "jshint": "2.5.2", "pg-copy-streams": "0.3.0" }, From fc3634045bccf8765e1354d926b9c200629fa896 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Thu, 15 Jun 2017 13:22:58 -0500 Subject: [PATCH 0226/1037] Move attach listeners into its own function Just for readability --- lib/client.js | 144 ++++++++++++++++++++++++++------------------------ 1 file changed, 74 insertions(+), 70 deletions(-) diff --git a/lib/client.js b/lib/client.js index 0b67ba31c..563adbe0f 100644 --- a/lib/client.js +++ b/lib/client.js @@ -112,52 +112,8 @@ Client.prototype.connect = function(callback) { //after the connection initially becomes ready for queries con.once('readyForQuery', function() { self._connecting = false; + self._attachListeners(con); - //delegate rowDescription to active query - con.on('rowDescription', function(msg) { - self.activeQuery.handleRowDescription(msg); - }); - - //delegate dataRow to active query - con.on('dataRow', function(msg) { - self.activeQuery.handleDataRow(msg); - }); - - //delegate portalSuspended to active query - con.on('portalSuspended', function(msg) { - self.activeQuery.handlePortalSuspended(con); - }); - - //deletagate emptyQuery to active query - con.on('emptyQuery', function(msg) { - self.activeQuery.handleEmptyQuery(con); - }); - - //delegate commandComplete to active query - con.on('commandComplete', function(msg) { - self.activeQuery.handleCommandComplete(msg, con); - }); - - //if a prepared statement has a name and properly parses - //we track that its already been executed so we don't parse - //it again on the same client - con.on('parseComplete', function(msg) { - if(self.activeQuery.name) { - con.parsedStatements[self.activeQuery.name] = true; - } - }); - - con.on('copyInResponse', function(msg) { - self.activeQuery.handleCopyInResponse(self.connection); - }); - - con.on('copyData', function (msg) { - self.activeQuery.handleCopyData(msg, self.connection); - }); - - con.on('notification', function(msg) { - self.emit('notification', msg); - }); //process possible callback argument to Client#connect if (callback) { @@ -241,10 +197,58 @@ Client.prototype.connect = function(callback) { }) }) } - }; -Client.prototype.getStartupConf = function() { +Client.prototype._attachListeners = function(con) { + const self = this + //delegate rowDescription to active query + con.on('rowDescription', function (msg) { + self.activeQuery.handleRowDescription(msg); + }); + + //delegate dataRow to active query + con.on('dataRow', function (msg) { + self.activeQuery.handleDataRow(msg); + }); + + //delegate portalSuspended to active query + con.on('portalSuspended', function (msg) { + self.activeQuery.handlePortalSuspended(con); + }); + + //deletagate emptyQuery to active query + con.on('emptyQuery', function (msg) { + self.activeQuery.handleEmptyQuery(con); + }); + + //delegate commandComplete to active query + con.on('commandComplete', function (msg) { + self.activeQuery.handleCommandComplete(msg, con); + }); + + //if a prepared statement has a name and properly parses + //we track that its already been executed so we don't parse + //it again on the same client + con.on('parseComplete', function (msg) { + if (self.activeQuery.name) { + con.parsedStatements[self.activeQuery.name] = true; + } + }); + + con.on('copyInResponse', function (msg) { + self.activeQuery.handleCopyInResponse(self.connection); + }); + + con.on('copyData', function (msg) { + self.activeQuery.handleCopyData(msg, self.connection); + }); + + con.on('notification', function (msg) { + self.emit('notification', msg); + }); +} + +Client.prototype.getStartupConf = function () { var params = this.connectionParameters; var data = { @@ -263,41 +267,41 @@ Client.prototype.getStartupConf = function() { return data; }; -Client.prototype.cancel = function(client, query) { - if(client.activeQuery == query) { +Client.prototype.cancel = function (client, query) { + if (client.activeQuery == query) { var con = this.connection; - if(this.host && this.host.indexOf('/') === 0) { + if (this.host && this.host.indexOf('/') === 0) { con.connect(this.host + '/.s.PGSQL.' + this.port); } else { con.connect(this.port, this.host); } //once connection is established send cancel message - con.on('connect', function() { + con.on('connect', function () { con.cancel(client.processID, client.secretKey); }); - } else if(client.queryQueue.indexOf(query) != -1) { + } else if (client.queryQueue.indexOf(query) != -1) { client.queryQueue.splice(client.queryQueue.indexOf(query), 1); } }; -Client.prototype.setTypeParser = function(oid, format, parseFn) { +Client.prototype.setTypeParser = function (oid, format, parseFn) { return this._types.setTypeParser(oid, format, parseFn); }; -Client.prototype.getTypeParser = function(oid, format) { +Client.prototype.getTypeParser = function (oid, format) { return this._types.getTypeParser(oid, format); }; // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c -Client.prototype.escapeIdentifier = function(str) { +Client.prototype.escapeIdentifier = function (str) { var escaped = '"'; - for(var i = 0; i < str.length; i++) { + for (var i = 0; i < str.length; i++) { var c = str[i]; - if(c === '"') { + if (c === '"') { escaped += c + c; } else { escaped += c; @@ -310,14 +314,14 @@ Client.prototype.escapeIdentifier = function(str) { }; // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c -Client.prototype.escapeLiteral = function(str) { +Client.prototype.escapeLiteral = function (str) { var hasBackslash = false; var escaped = '\''; - for(var i = 0; i < str.length; i++) { + for (var i = 0; i < str.length; i++) { var c = str[i]; - if(c === '\'') { + if (c === '\'') { escaped += c + c; } else if (c === '\\') { escaped += c + c; @@ -329,21 +333,21 @@ Client.prototype.escapeLiteral = function(str) { escaped += '\''; - if(hasBackslash === true) { + if (hasBackslash === true) { escaped = ' E' + escaped; } return escaped; }; -Client.prototype._pulseQueryQueue = function() { - if(this.readyForQuery===true) { +Client.prototype._pulseQueryQueue = function () { + if (this.readyForQuery === true) { this.activeQuery = this.queryQueue.shift(); - if(this.activeQuery) { + if (this.activeQuery) { this.readyForQuery = false; this.hasExecuted = true; this.activeQuery.submit(this.connection); - } else if(this.hasExecuted) { + } else if (this.hasExecuted) { this.activeQuery = null; this.emit('drain'); } @@ -358,7 +362,7 @@ Client.prototype.copyTo = function (text) { throw new Error("For PostgreSQL COPY TO/COPY FROM support npm install pg-copy-streams"); }; -Client.prototype.query = function(config, values, callback) { +Client.prototype.query = function (config, values, callback) { //can take in strings, config object or query object var query; var result; @@ -376,10 +380,10 @@ Client.prototype.query = function(config, values, callback) { }) } - if(this.binary && !query.binary) { + if (this.binary && !query.binary) { query.binary = true; } - if(query._result) { + if (query._result) { query._result._getTypeParser = this._types.getTypeParser.bind(this._types); } @@ -388,7 +392,7 @@ Client.prototype.query = function(config, values, callback) { return result }; -Client.prototype.end = function(cb) { +Client.prototype.end = function (cb) { this._ending = true; if (this.activeQuery) { // if we have an active query we need to force a disconnect @@ -407,7 +411,7 @@ Client.prototype.end = function(cb) { } }; -Client.md5 = function(string) { +Client.md5 = function (string) { return crypto.createHash('md5').update(string, 'utf-8').digest('hex'); }; From 5f5e40f03cd89cf212a0c6a6c1d0862cfeda8a4a Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Thu, 15 Jun 2017 14:00:37 -0500 Subject: [PATCH 0227/1037] Add tests to support deprecated event listeners --- lib/client.js | 6 ++-- lib/query.js | 19 ++++++++++++ .../client/deprecated-listener-tests.js | 30 +++++++++++++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) create mode 100644 test/integration/client/deprecated-listener-tests.js diff --git a/lib/client.js b/lib/client.js index 563adbe0f..c866f293d 100644 --- a/lib/client.js +++ b/lib/client.js @@ -374,10 +374,8 @@ Client.prototype.query = function (config, values, callback) { } } else { query = new Query(config, values, callback) - result = query.callback ? undefined : new global.Promise((resolve, reject) => { - query.once('end', resolve) - query.once('error', reject) - }) + query._deprecateListeners() + result = query } if (this.binary && !query.binary) { diff --git a/lib/query.js b/lib/query.js index b36cf6b8f..a98afaaee 100644 --- a/lib/query.js +++ b/lib/query.js @@ -53,6 +53,25 @@ Query.prototype.requiresPreparation = function() { return this.values.length > 0; }; +Query.prototype.then = function(onSuccess, onFailure) { + return this._getPromise().then(onSuccess, onFailure); +}; + +Query.prototype.catch = function(callback) { + return this._getPromise().catch(callback); +}; + +Query.prototype._getPromise = function() { + if (this._promise) return this._promise; + this._promise = new Promise(function(resolve, reject) { + this.once('end', resolve); + this.once('error', reject); + }.bind(this)); + return this._promise; +}; + +Query.prototype._deprecateListeners = function() { +} //associates row metadata from the supplied //message with this query object diff --git a/test/integration/client/deprecated-listener-tests.js b/test/integration/client/deprecated-listener-tests.js new file mode 100644 index 000000000..0687ff648 --- /dev/null +++ b/test/integration/client/deprecated-listener-tests.js @@ -0,0 +1,30 @@ +const helper = require('./test-helper') +const pg = helper.pg +const suite = new helper.Suite() + +suite.test('Query with a callback should still support event-listeners', (done) => { + const client = new pg.Client() + const sink = new helper.Sink(3, 1000, () => { + client.end() + done() + }) + client.connect() + const query = client.query('SELECT NOW()', (err, res) => { + sink.add() + }) + query.on('row', () => sink.add()) + query.on('end', () => sink.add()) +}) + +suite.test('Query with a promise should still support event-listeners', (done) => { + const client = new pg.Client() + const sink = new helper.Sink(3, 1000, () => { + client.end() + done() + }) + client.connect() + const query = client.query('SELECT NOW()') + query.on('row', () => sink.add()) + query.on('end', () => sink.add()) + query.then(() => sink.add()) +}) From 0ce8a6c675be21bf2ec450cd15ca602c77f2644d Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 16 Jun 2017 15:56:18 -0500 Subject: [PATCH 0228/1037] Fix brittle unit tests --- test/unit/client/test-helper.js | 9 +- .../unit/client/throw-in-type-parser-tests.js | 149 +++++++----------- test/unit/test-helper.js | 6 +- 3 files changed, 62 insertions(+), 102 deletions(-) diff --git a/test/unit/client/test-helper.js b/test/unit/client/test-helper.js index a82940233..7c0bb31b4 100644 --- a/test/unit/client/test-helper.js +++ b/test/unit/client/test-helper.js @@ -1,5 +1,6 @@ -var helper = require(__dirname+'/../test-helper'); -var Connection = require(__dirname + '/../../../lib/connection'); +var helper = require('../test-helper'); +var Connection = require('../../../lib/connection'); + var makeClient = function() { var connection = new Connection({stream: "no"}); connection.startup = function() {}; @@ -14,6 +15,6 @@ var makeClient = function() { return client; }; -module.exports = { +module.exports = Object.assign({ client: makeClient -}; +}, helper); diff --git a/test/unit/client/throw-in-type-parser-tests.js b/test/unit/client/throw-in-type-parser-tests.js index 37a272aa0..2f1845438 100644 --- a/test/unit/client/throw-in-type-parser-tests.js +++ b/test/unit/client/throw-in-type-parser-tests.js @@ -1,112 +1,69 @@ var helper = require("./test-helper"); -var Query = require('../../../lib/query') -var types = require('pg-types') +var Query = require("../../../lib/query"); +var types = require("pg-types"); -test('handles throws in type parsers', function() { - var typeParserError = new Error('TEST: Throw in type parsers'); +const suite = new helper.Suite(); - types.setTypeParser('special oid that will throw', function () { - throw typeParserError; - }); - - test('emits error', function() { - var handled; - var client = helper.client(); - var con = client.connection; - var query = client.query(new Query('whatever')); +var typeParserError = new Error("TEST: Throw in type parsers"); - handled = con.emit('readyForQuery'); - assert.ok(handled, "should have handled ready for query"); - - con.emit('rowDescription',{ - fields: [{ - name: 'boom', - dataTypeID: 'special oid that will throw' - }] - }); - assert.ok(handled, "should have handled row description"); +types.setTypeParser("special oid that will throw", function() { + throw typeParserError; +}); - assert.emits(query, 'error', function(err) { - assert.equal(err, typeParserError); +const emitFakeEvents = con => { + setImmediate(() => { + con.emit("readyForQuery"); + + con.emit("rowDescription", { + fields: [ + { + name: "boom", + dataTypeID: "special oid that will throw" + } + ] }); - handled = con.emit('dataRow', { fields: ["hi"] }); - assert.ok(handled, "should have handled first data row message"); - - handled = con.emit('commandComplete', { text: 'INSERT 31 1' }); - assert.ok(handled, "should have handled command complete"); - - handled = con.emit('readyForQuery'); - assert.ok(handled, "should have handled ready for query"); + con.emit("dataRow", { fields: ["hi"] }); + con.emit("dataRow", { fields: ["hi"] }); + con.emit("commandComplete", { text: "INSERT 31 1" }); + con.emit("readyForQuery"); }); - - test('calls callback with error', function() { - var handled; - - var callbackCalled = 0; - - var client = helper.client(); - var con = client.connection; - var query = client.query('whatever', assert.calls(function (err) { - callbackCalled += 1; - - assert.equal(callbackCalled, 1); - assert.equal(err, typeParserError); - })); - - handled = con.emit('readyForQuery'); - assert.ok(handled, "should have handled ready for query"); - - handled = con.emit('rowDescription',{ - fields: [{ - name: 'boom', - dataTypeID: 'special oid that will throw' - }] - }); - assert.ok(handled, "should have handled row description"); - - handled = con.emit('dataRow', { fields: ["hi"] }); - assert.ok(handled, "should have handled first data row message"); - - handled = con.emit('dataRow', { fields: ["hi"] }); - assert.ok(handled, "should have handled second data row message"); - - con.emit('commandComplete', { text: 'INSERT 31 1' }); - assert.ok(handled, "should have handled command complete"); - - handled = con.emit('readyForQuery'); - assert.ok(handled, "should have handled ready for query"); +}; + +suite.test("emits error", function(done) { + var handled; + var client = helper.client(); + var con = client.connection; + var query = client.query(new Query("whatever")); + emitFakeEvents(con) + + assert.emits(query, "error", function(err) { + assert.equal(err, typeParserError); + done(); }); +}); - test('rejects promise with error', function() { - var handled; - var client = helper.client(); - var con = client.connection; - var queryPromise = client.query('whatever'); - - handled = con.emit('readyForQuery'); - assert.ok(handled, "should have handled ready for query"); - - handled = con.emit('rowDescription',{ - fields: [{ - name: 'boom', - dataTypeID: 'special oid that will throw' - }] - }); - assert.ok(handled, "should have handled row description"); +suite.test("calls callback with error", function(done) { + var handled; - handled = con.emit('dataRow', { fields: ["hi"] }); - assert.ok(handled, "should have handled first data row message"); + var callbackCalled = 0; - handled = con.emit('commandComplete', { text: 'INSERT 31 1' }); - assert.ok(handled, "should have handled command complete"); + var client = helper.client(); + var con = client.connection; + emitFakeEvents(con); + var query = client.query("whatever", function(err) { + assert.equal(err, typeParserError); + done(); + }); - handled = con.emit('readyForQuery'); - assert.ok(handled, "should have handled ready for query"); +}); - queryPromise.catch(assert.calls(function (err) { - assert.equal(err, typeParserError); - })); +suite.test("rejects promise with error", function(done) { + var client = helper.client(); + var con = client.connection; + emitFakeEvents(con); + client.query("whatever").catch(err => { + assert.equal(err, typeParserError); + done(); }); - }); diff --git a/test/unit/test-helper.js b/test/unit/test-helper.js index 878898d8b..ad6485be8 100644 --- a/test/unit/test-helper.js +++ b/test/unit/test-helper.js @@ -1,6 +1,8 @@ -var helper = require(__dirname+'/../test-helper'); var EventEmitter = require('events').EventEmitter; -var Connection = require(__dirname + '/../../lib/connection'); + +var helper = require('../test-helper'); +var Connection = require('../../lib/connection'); + MemoryStream = function() { EventEmitter.call(this); this.packets = []; From 76c10005670bdaea6bd01e789060a4b4101f0419 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 16 Jun 2017 16:11:25 -0500 Subject: [PATCH 0229/1037] Add event-emitters back --- lib/client.js | 1 - lib/native/client.js | 7 +------ lib/native/query.js | 17 +++++++++++++++++ lib/query.js | 3 --- 4 files changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/client.js b/lib/client.js index c866f293d..8ca944b18 100644 --- a/lib/client.js +++ b/lib/client.js @@ -374,7 +374,6 @@ Client.prototype.query = function (config, values, callback) { } } else { query = new Query(config, values, callback) - query._deprecateListeners() result = query } diff --git a/lib/native/client.js b/lib/native/client.js index 639484ec7..7950bc3d4 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -131,14 +131,9 @@ Client.prototype.query = function(config, values, callback) { } var query = new NativeQuery(config, values, callback); - var result = query.callback ? query : new global.Promise(function(resolve, reject) { - query.on('end', resolve); - query.on('error', reject); - }); - this._queryQueue.push(query); this._pulseQueryQueue(); - return result; + return query; }; //disconnect from the backend server diff --git a/lib/native/query.js b/lib/native/query.js index 1523e7c7e..a1f7dd42b 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -67,6 +67,23 @@ NativeQuery.prototype.handleError = function(err) { self.state = 'error'; }; +NativeQuery.prototype.then = function(onSuccess, onFailure) { + return this._getPromise().then(onSuccess, onFailure); +}; + +NativeQuery.prototype.catch = function(callback) { + return this._getPromise().catch(callback); +}; + +NativeQuery.prototype._getPromise = function() { + if (this._promise) return this._promise; + this._promise = new Promise(function(resolve, reject) { + this.once('end', resolve); + this.once('error', reject); + }.bind(this)); + return this._promise; +}; + NativeQuery.prototype.submit = function(client) { this.state = 'running'; var self = this; diff --git a/lib/query.js b/lib/query.js index a98afaaee..d36567486 100644 --- a/lib/query.js +++ b/lib/query.js @@ -70,9 +70,6 @@ Query.prototype._getPromise = function() { return this._promise; }; -Query.prototype._deprecateListeners = function() { -} - //associates row metadata from the supplied //message with this query object //metadata used when parsing row results From cfd9caa925b68a951ab0a0976636b3db99bf72f0 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 16 Jun 2017 16:41:31 -0500 Subject: [PATCH 0230/1037] Deprecate query.on & query.once --- lib/client.js | 4 +++- lib/native/client.js | 4 +++- lib/native/query.js | 4 ++-- lib/query.js | 4 ++-- lib/utils.js | 21 ++++++++++++++++++++- 5 files changed, 30 insertions(+), 7 deletions(-) diff --git a/lib/client.js b/lib/client.js index 8ca944b18..3eee54022 100644 --- a/lib/client.js +++ b/lib/client.js @@ -362,6 +362,8 @@ Client.prototype.copyTo = function (text) { throw new Error("For PostgreSQL COPY TO/COPY FROM support npm install pg-copy-streams"); }; +const DeprecatedQuery = require('./utils').deprecateEventEmitter(Query) + Client.prototype.query = function (config, values, callback) { //can take in strings, config object or query object var query; @@ -373,7 +375,7 @@ Client.prototype.query = function (config, values, callback) { query.callback = query.callback || values } } else { - query = new Query(config, values, callback) + query = new DeprecatedQuery(config, values, callback) result = query } diff --git a/lib/native/client.js b/lib/native/client.js index 7950bc3d4..331f92061 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -109,6 +109,8 @@ Client.prototype.connect = function(cb) { return result }; +const DeprecatedQuery = require('../utils').deprecateEventEmitter(NativeQuery) + //send a query to the server //this method is highly overloaded to take //1) string query, optional array of parameters, optional function callback @@ -130,7 +132,7 @@ Client.prototype.query = function(config, values, callback) { return config; } - var query = new NativeQuery(config, values, callback); + var query = new DeprecatedQuery(config, values, callback); this._queryQueue.push(query); this._pulseQueryQueue(); return query; diff --git a/lib/native/query.js b/lib/native/query.js index a1f7dd42b..4fb501f18 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -78,8 +78,8 @@ NativeQuery.prototype.catch = function(callback) { NativeQuery.prototype._getPromise = function() { if (this._promise) return this._promise; this._promise = new Promise(function(resolve, reject) { - this.once('end', resolve); - this.once('error', reject); + this._once('end', resolve); + this._once('error', reject); }.bind(this)); return this._promise; }; diff --git a/lib/query.js b/lib/query.js index d36567486..b997091c2 100644 --- a/lib/query.js +++ b/lib/query.js @@ -64,8 +64,8 @@ Query.prototype.catch = function(callback) { Query.prototype._getPromise = function() { if (this._promise) return this._promise; this._promise = new Promise(function(resolve, reject) { - this.once('end', resolve); - this.once('error', reject); + this._once('end', resolve); + this._once('error', reject); }.bind(this)); return this._promise; }; diff --git a/lib/utils.js b/lib/utils.js index 82d1aefd5..381775ff6 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -6,6 +6,7 @@ * README.md file in the root directory of this source tree. */ +const util = require('util') var defaults = require('./defaults'); function escapeElement(elementRepresentation) { @@ -137,11 +138,29 @@ function normalizeQueryConfig (config, values, callback) { return config; } +const queryEventEmitterOverloadDeprecationMessage = ` +Using the automatically created return value from client.query as an event emitter is deprecated. +Use either the callback or promise interface. +` + +const deprecateEventEmitter = function(Emitter) { + const Result = function () { + Emitter.apply(this, arguments) + } + util.inherits(Result, Emitter) + Result.prototype._on = Result.prototype.on + Result.prototype._once = Result.prototype.once + Result.prototype.on = util.deprecate(Result.prototype.on, queryEventEmitterOverloadDeprecationMessage) + Result.prototype.once = util.deprecate(Result.prototype.once, queryEventEmitterOverloadDeprecationMessage) + return Result +} + module.exports = { prepareValue: function prepareValueWrapper (value) { //this ensures that extra arguments do not get passed into prepareValue //by accident, eg: from calling values.map(utils.prepareValue) return prepareValue(value); }, - normalizeQueryConfig: normalizeQueryConfig + normalizeQueryConfig: normalizeQueryConfig, + deprecateEventEmitter: deprecateEventEmitter, }; From f7b1edc7bbc994427b59cae57237cc52c8d51950 Mon Sep 17 00:00:00 2001 From: Brian C Date: Sun, 18 Jun 2017 14:09:18 -0500 Subject: [PATCH 0231/1037] Add client to error event emitter (#65) When the pool emits an error pass the client as the 2nd parameter to the `on('error')` handler. --- index.js | 2 +- test/events.js | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 2e30ac6e3..7e0f0ce59 100644 --- a/index.js +++ b/index.js @@ -90,7 +90,7 @@ Pool.prototype._create = function (cb) { this.log('connected client error:', e) this.pool.destroy(client) e.client = client - this.emit('error', e) + this.emit('error', e, client) }.bind(this)) client.connect(function (err) { diff --git a/test/events.js b/test/events.js index bcb523f03..759dff02d 100644 --- a/test/events.js +++ b/test/events.js @@ -60,6 +60,22 @@ describe('events', function () { pool.end(done) }, 40) }) + + it('emits error and client if an idle client in the pool hits an error', function (done) { + var pool = new Pool() + pool.connect(function (err, client) { + expect(err).to.equal(null) + 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) { From 0c32c57e0e00f695e650fb1c8b9aadac7d901cd3 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 14:09:54 -0500 Subject: [PATCH 0232/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 763b273c7..b3424f1e4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.7.1", + "version": "1.8.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From 94a628a16f74c043788a7ff37c38dee60ea7e974 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 15:16:39 -0500 Subject: [PATCH 0233/1037] Update engine support --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5eecc421a..0fee6bf44 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,6 @@ }, "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">= 4.0.0" } } From 313c41a39fa34d1902669136adbad5149c558ca0 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 12:53:12 -0500 Subject: [PATCH 0234/1037] Cleanup --- lib/client.js | 24 +- test/integration/client/api-tests.js | 342 ++++++++++-------- .../client/deprecated-listener-tests.js | 30 -- 3 files changed, 198 insertions(+), 198 deletions(-) delete mode 100644 test/integration/client/deprecated-listener-tests.js diff --git a/lib/client.js b/lib/client.js index 3eee54022..22026c1f4 100644 --- a/lib/client.js +++ b/lib/client.js @@ -354,29 +354,25 @@ Client.prototype._pulseQueryQueue = function () { } }; -Client.prototype.copyFrom = function (text) { - throw new Error("For PostgreSQL COPY TO/COPY FROM support npm install pg-copy-streams"); -}; - -Client.prototype.copyTo = function (text) { - throw new Error("For PostgreSQL COPY TO/COPY FROM support npm install pg-copy-streams"); -}; - -const DeprecatedQuery = require('./utils').deprecateEventEmitter(Query) - Client.prototype.query = function (config, values, callback) { //can take in strings, config object or query object var query; var result; if (typeof config.submit == 'function') { - query = config - result = query + result = query = config if (typeof values == 'function') { query.callback = query.callback || values } } else { - query = new DeprecatedQuery(config, values, callback) - result = query + query = new Query(config, values, callback) + if (!query.callback) { + let resolve, reject; + result = new Promise((res, rej) => { + resolve = res + reject = rej + }) + query.callback = (err, res) => err ? reject(err) : resolve(res) + } } if (this.binary && !query.binary) { diff --git a/test/integration/client/api-tests.js b/test/integration/client/api-tests.js index f8f78f195..5f999482e 100644 --- a/test/integration/client/api-tests.js +++ b/test/integration/client/api-tests.js @@ -1,173 +1,207 @@ -var helper = require(__dirname + '/../test-helper'); +var helper = require(__dirname + "/../test-helper"); var pg = helper.pg; -var log = function() { - //console.log.apply(console, arguments); -} +var suite = new helper.Suite(); -var sink = new helper.Sink(5, 10000, function() { - log("ending connection pool: %j", helper.config); - pg.end(helper.config); -}); - -test('api', function() { - log("connecting to %j", helper.config) +suite.test("pool callback behavior", done => { //test weird callback behavior with node-pool - pg.connect(helper.config, function(err) { + const pool = new pg.Pool(); + pool.connect(function(err) { assert.isNull(err); - arguments[1].emit('drain'); + arguments[1].emit("drain"); arguments[2](); + pool.end(done); }); - pg.connect(helper.config, assert.calls(function(err, client, done) { - assert.equal(err, null, "Failed to connect: " + helper.sys.inspect(err)); - - if (helper.args.native) { - assert(client.native) - } else { - assert(!client.native) - } - - client.query('CREATE TEMP TABLE band(name varchar(100))'); - - ['the flaming lips', 'wolf parade', 'radiohead', 'bright eyes', 'the beach boys', 'dead black hearts'].forEach(function(bandName) { - var query = client.query("INSERT INTO band (name) VALUES ('"+ bandName +"')") - }); - - - test('simple query execution',assert.calls( function() { - log("executing simple query") - client.query("SELECT * FROM band WHERE name = 'the beach boys'", assert.calls(function(err, result) { - assert.lengthIs(result.rows, 1) - assert.equal(result.rows.pop().name, 'the beach boys') - log("simple query executed") - })); - - })) - - test('prepared statement execution',assert.calls( function() { - log("executing prepared statement 1") - client.query('SELECT * FROM band WHERE name = $1', ['dead black hearts'],assert.calls( function(err, result) { - log("Prepared statement 1 finished") - assert.lengthIs(result.rows, 1); - assert.equal(result.rows.pop().name, 'dead black hearts'); - })) +}); - log("executing prepared statement two") - client.query('SELECT * FROM band WHERE name LIKE $1 ORDER BY name', ['the %'], assert.calls(function(err, result) { - log("prepared statement two finished") - assert.lengthIs(result.rows, 2); - assert.equal(result.rows.pop().name, 'the flaming lips'); - assert.equal(result.rows.pop().name, 'the beach boys'); - sink.add(); - done(); - })) - })) - })) -}) +suite.test("callback API", done => { + const client = new helper.Client(); + client.query("CREATE TEMP TABLE peep(name text)"); + client.query("INSERT INTO peep(name) VALUES ($1)", ["brianc"]); + const config = { + text: "INSERT INTO peep(name) VALUES ($1)", + values: ["brian"] + }; + client.query(config); + client.query("INSERT INTO peep(name) VALUES ($1)", ["aaron"]); + + client.query("SELECT * FROM peep ORDER BY name", (err, res) => { + assert(!err); + assert.equal(res.rowCount, 3); + assert.deepEqual(res.rows, [ + { + name: "aaron" + }, + { + name: "brian" + }, + { + name: "brianc" + } + ]); + done(); + }); + client.connect(err => { + assert(!err); + client.once("drain", () => client.end()); + }); +}); -test('executing nested queries', function() { - pg.connect(helper.config, assert.calls(function(err, client, done) { - assert.isNull(err); - log("connected for nested queriese") - client.query('select now as now from NOW()', assert.calls(function(err, result) { - assert.equal(new Date().getYear(), result.rows[0].now.getYear()) - client.query('select now as now_again FROM NOW()', assert.calls(function() { - client.query('select * FROM NOW()', assert.calls(function() { - log('all nested queries recieved') - assert.ok('all queries hit') - sink.add(); - done(); - })) - })) - })) - })) -}) +suite.test("executing nested queries", function(done) { + const pool = new pg.Pool(); + pool.connect( + assert.calls(function(err, client, release) { + assert.isNull(err); + client.query( + "select now as now from NOW()", + assert.calls(function(err, result) { + assert.equal(new Date().getYear(), result.rows[0].now.getYear()); + client.query( + "select now as now_again FROM NOW()", + assert.calls(function() { + client.query( + "select * FROM NOW()", + assert.calls(function() { + assert.ok("all queries hit"); + release(); + pool.end(done); + }) + ); + }) + ); + }) + ); + }) + ); +}); -test('raises error if cannot connect', function() { +suite.test("raises error if cannot connect", function() { var connectionString = "pg://sfalsdkf:asdf@localhost/ieieie"; - log("trying to connect to invalid place for error") - pg.connect(connectionString, assert.calls(function(err, client, done) { - assert.ok(err, 'should have raised an error') - log("invalid connection supplied error to callback") - sink.add(); - done(); - })) -}) - -test("query errors are handled and do not bubble if callback is provded", function() { - pg.connect(helper.config, assert.calls(function(err, client, done) { - assert.isNull(err) - log("checking for query error") - client.query("SELECT OISDJF FROM LEIWLISEJLSE", assert.calls(function(err, result) { - assert.ok(err); - log("query error supplied error to callback") - sink.add(); + const pool = new pg.Pool({ connectionString: connectionString }); + pool.connect( + assert.calls(function(err, client, done) { + assert.ok(err, "should have raised an error"); done(); - })) - })) -}) + }) + ); +}); -test('callback is fired once and only once', function() { - pg.connect(helper.config, assert.calls(function(err, client, done) { - assert.isNull(err); - client.query("CREATE TEMP TABLE boom(name varchar(10))"); - var callCount = 0; - client.query([ - "INSERT INTO boom(name) VALUES('hai')", - "INSERT INTO boom(name) VALUES('boom')", - "INSERT INTO boom(name) VALUES('zoom')", - ].join(";"), function(err, callback) { - assert.equal(callCount++, 0, "Call count should be 0. More means this callback fired more than once."); - sink.add(); - done(); +suite.test("query errors are handled and do not bubble if callback is provded", function(done) { + const pool = new pg.Pool(); + pool.connect( + assert.calls(function(err, client, release) { + assert.isNull(err); + client.query( + "SELECT OISDJF FROM LEIWLISEJLSE", + assert.calls(function(err, result) { + assert.ok(err); + release() + pool.end(done) + }) + ); + }) + ); + } +); + +suite.test("callback is fired once and only once", function(done) { + const pool = new pg.Pool() + pool.connect( + assert.calls(function(err, client, release) { + assert.isNull(err); + client.query("CREATE TEMP TABLE boom(name varchar(10))"); + var callCount = 0; + client.query( + [ + "INSERT INTO boom(name) VALUES('hai')", + "INSERT INTO boom(name) VALUES('boom')", + "INSERT INTO boom(name) VALUES('zoom')" + ].join(";"), + function(err, callback) { + assert.equal( + callCount++, + 0, + "Call count should be 0. More means this callback fired more than once." + ); + release() + pool.end(done) + } + ); }) - })) -}) + ); +}); -test('can provide callback and config object', function() { - pg.connect(helper.config, assert.calls(function(err, client, done) { - assert.isNull(err); - client.query({ - name: 'boom', - text: 'select NOW()' - }, assert.calls(function(err, result) { +suite.test("can provide callback and config object", function(done) { + const pool = new pg.Pool() + pool.connect( + assert.calls(function(err, client, release) { assert.isNull(err); - assert.equal(result.rows[0].now.getYear(), new Date().getYear()) - done(); - })) - })) -}) + client.query( + { + name: "boom", + text: "select NOW()" + }, + assert.calls(function(err, result) { + assert.isNull(err); + assert.equal(result.rows[0].now.getYear(), new Date().getYear()); + release(); + pool.end(done) + }) + ); + }) + ); +}); -test('can provide callback and config and parameters', function() { - pg.connect(helper.config, assert.calls(function(err, client, done) { - assert.isNull(err); - var config = { - text: 'select $1::text as val' - }; - client.query(config, ['hi'], assert.calls(function(err, result) { +suite.test("can provide callback and config and parameters", function(done) { + const pool = new pg.Pool() + pool.connect( + assert.calls(function(err, client, release) { assert.isNull(err); - assert.equal(result.rows.length, 1); - assert.equal(result.rows[0].val, 'hi'); - done(); - })) - })) -}) + var config = { + text: "select $1::text as val" + }; + client.query( + config, + ["hi"], + assert.calls(function(err, result) { + assert.isNull(err); + assert.equal(result.rows.length, 1); + assert.equal(result.rows[0].val, "hi"); + release() + pool.end(done) + }) + ); + }) + ); +}); -test('null and undefined are both inserted as NULL', function() { - pg.connect(helper.config, assert.calls(function(err, client, done) { - assert.isNull(err); - client.query("CREATE TEMP TABLE my_nulls(a varchar(1), b varchar(1), c integer, d integer, e date, f date)"); - client.query("INSERT INTO my_nulls(a,b,c,d,e,f) VALUES ($1,$2,$3,$4,$5,$6)", [ null, undefined, null, undefined, null, undefined ]); - client.query("SELECT * FROM my_nulls", assert.calls(function(err, result) { - assert.isNull(err); - assert.equal(result.rows.length, 1); - assert.isNull(result.rows[0].a); - assert.isNull(result.rows[0].b); - assert.isNull(result.rows[0].c); - assert.isNull(result.rows[0].d); - assert.isNull(result.rows[0].e); - assert.isNull(result.rows[0].f); - done(); - })) - })) -}) +suite.test("null and undefined are both inserted as NULL", function(done) { + const pool = new pg.Pool() + pool.connect( + assert.calls(function(err, client, release) { + assert.isNull(err); + client.query( + "CREATE TEMP TABLE my_nulls(a varchar(1), b varchar(1), c integer, d integer, e date, f date)" + ); + client.query( + "INSERT INTO my_nulls(a,b,c,d,e,f) VALUES ($1,$2,$3,$4,$5,$6)", + [null, undefined, null, undefined, null, undefined] + ); + client.query( + "SELECT * FROM my_nulls", + assert.calls(function(err, result) { + assert.isNull(err); + assert.equal(result.rows.length, 1); + assert.isNull(result.rows[0].a); + assert.isNull(result.rows[0].b); + assert.isNull(result.rows[0].c); + assert.isNull(result.rows[0].d); + assert.isNull(result.rows[0].e); + assert.isNull(result.rows[0].f); + pool.end(done) + release(); + }) + ); + }) + ); +}); diff --git a/test/integration/client/deprecated-listener-tests.js b/test/integration/client/deprecated-listener-tests.js deleted file mode 100644 index 0687ff648..000000000 --- a/test/integration/client/deprecated-listener-tests.js +++ /dev/null @@ -1,30 +0,0 @@ -const helper = require('./test-helper') -const pg = helper.pg -const suite = new helper.Suite() - -suite.test('Query with a callback should still support event-listeners', (done) => { - const client = new pg.Client() - const sink = new helper.Sink(3, 1000, () => { - client.end() - done() - }) - client.connect() - const query = client.query('SELECT NOW()', (err, res) => { - sink.add() - }) - query.on('row', () => sink.add()) - query.on('end', () => sink.add()) -}) - -suite.test('Query with a promise should still support event-listeners', (done) => { - const client = new pg.Client() - const sink = new helper.Sink(3, 1000, () => { - client.end() - done() - }) - client.connect() - const query = client.query('SELECT NOW()') - query.on('row', () => sink.add()) - query.on('end', () => sink.add()) - query.then(() => sink.add()) -}) From 1bc1758579ef7855b7e08e0bb56998d95cf33bf8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 14:20:55 -0500 Subject: [PATCH 0235/1037] Remove deprecated methods --- Makefile | 2 +- lib/index.js | 69 ------- lib/native/client.js | 15 +- lib/query.js | 17 -- lib/utils.js | 18 -- test/integration/client/array-tests.js | 8 +- test/integration/client/cancel-query-tests.js | 41 ----- test/integration/client/huge-numeric-tests.js | 5 +- .../client/json-type-parsing-tests.js | 5 +- .../integration/client/no-row-result-tests.js | 34 ++-- test/integration/client/parse-int-8-tests.js | 5 +- .../client/query-as-promise-tests.js | 43 +++-- .../client/query-column-names-tests.js | 15 +- .../client/result-metadata-tests.js | 9 +- test/integration/client/timezone-tests.js | 32 ++-- test/integration/client/transaction-tests.js | 92 +++++----- .../integration/client/type-coercion-tests.js | 172 +++++++++--------- .../client/type-parser-override-tests.js | 14 +- .../connection-pool-size-tests.js | 9 + .../double-connection-tests.js | 2 - .../ending-empty-pool-tests.js | 15 -- .../connection-pool/ending-pool-tests.js | 30 --- .../connection-pool/error-tests.js | 68 +++---- .../connection-pool/idle-timeout-tests.js | 19 +- .../connection-pool/max-connection-tests.js | 2 - .../connection-pool/optional-config-tests.js | 20 -- .../single-connection-tests.js | 2 - .../single-pool-on-object-config-tests.js | 13 -- .../connection-pool/test-helper.js | 45 +++-- .../waiting-connection-tests.js | 2 - .../connection-pool/yield-support-tests.js | 21 +-- test/integration/domain-tests.js | 19 +- test/integration/gh-issues/130-tests.js | 5 +- test/integration/gh-issues/131-tests.js | 6 +- test/integration/gh-issues/507-tests.js | 6 +- test/integration/gh-issues/675-tests.js | 5 +- test/integration/gh-issues/699-tests.js | 5 +- test/integration/gh-issues/787-tests.js | 3 +- test/integration/gh-issues/981-tests.js | 28 ++- test/test-helper.js | 2 - 40 files changed, 368 insertions(+), 555 deletions(-) delete mode 100644 test/integration/client/cancel-query-tests.js create mode 100644 test/integration/connection-pool/connection-pool-size-tests.js delete mode 100644 test/integration/connection-pool/double-connection-tests.js delete mode 100644 test/integration/connection-pool/ending-empty-pool-tests.js delete mode 100644 test/integration/connection-pool/ending-pool-tests.js delete mode 100644 test/integration/connection-pool/max-connection-tests.js delete mode 100644 test/integration/connection-pool/optional-config-tests.js delete mode 100644 test/integration/connection-pool/single-connection-tests.js delete mode 100644 test/integration/connection-pool/single-pool-on-object-config-tests.js delete mode 100644 test/integration/connection-pool/waiting-connection-tests.js diff --git a/Makefile b/Makefile index 08c1e10ca..ad8ed3de9 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ help: test: test-unit -test-all: jshint test-missing-native test-unit test-integration test-native test-binary +test-all: jshint test-missing-native test-unit test-integration test-native update-npm: diff --git a/lib/index.js b/lib/index.js index a24397116..ac3fb059e 100644 --- a/lib/index.js +++ b/lib/index.js @@ -15,7 +15,6 @@ var ConnectionParameters = require('./connection-parameters'); var poolFactory = require('./pool-factory'); var PG = function(clientConstructor) { - EventEmitter.call(this); this.defaults = defaults; this.Client = clientConstructor; this.Query = this.Client.Query; @@ -25,74 +24,6 @@ var PG = function(clientConstructor) { this.types = require('pg-types'); }; -util.inherits(PG, EventEmitter); - -PG.prototype.end = util.deprecate(function() { - var self = this; - var keys = Object.keys(this._pools); - var count = keys.length; - if(count === 0) { - self.emit('end'); - } else { - keys.forEach(function(key) { - var pool = self._pools[key]; - delete self._pools[key]; - pool.pool.drain(function() { - pool.pool.destroyAllNow(function() { - count--; - if(count === 0) { - self.emit('end'); - } - }); - }); - }); - } -}, -'pg.end() is deprecated - please construct pools directly via new pg.Pool()'); - -PG.prototype.connect = util.deprecate(function(config, callback) { - if(typeof config == "function") { - callback = config; - config = null; - } - if (typeof config == 'string') { - config = new ConnectionParameters(config); - } - - config = config || {}; - - //for backwards compatibility - config.max = config.max || config.poolSize || defaults.poolSize; - config.idleTimeoutMillis = config.idleTimeoutMillis || config.poolIdleTimeout || defaults.poolIdleTimeout; - config.log = config.log || config.poolLog || defaults.poolLog; - - var poolName = JSON.stringify(config); - this._pools[poolName] = this._pools[poolName] || new this.Pool(config); - var pool = this._pools[poolName]; - if(!pool.listeners('error').length) { - //propagate errors up to pg object - pool.on('error', function(e) { - this.emit('error', e, e.client); - }.bind(this)); - } - return pool.connect(callback); -}, -'pg.connect() is deprecated - please construct pools directly via new pg.Pool()'); - -// cancel the query running on the given client -PG.prototype.cancel = util.deprecate(function(config, client, query) { - if(client.native) { - return client.cancel(query); - } - var c = config; - //allow for no config to be passed - if(typeof c === 'function') { - c = defaults; - } - var cancellingClient = new this.Client(c); - cancellingClient.cancel(client, query); -}, 'pg.cancel() is deprecated - please create your own client instances to cancel queries'); - if(typeof process.env.NODE_PG_FORCE_NATIVE != 'undefined') { module.exports = new PG(require('./native')); } else { diff --git a/lib/native/client.js b/lib/native/client.js index 331f92061..9641d3993 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -109,8 +109,6 @@ Client.prototype.connect = function(cb) { return result }; -const DeprecatedQuery = require('../utils').deprecateEventEmitter(NativeQuery) - //send a query to the server //this method is highly overloaded to take //1) string query, optional array of parameters, optional function callback @@ -132,10 +130,19 @@ Client.prototype.query = function(config, values, callback) { return config; } - var query = new DeprecatedQuery(config, values, callback); + var query = new NativeQuery(config, values, callback); + var result + if (!query.callback) { + let resolve, reject; + result = new Promise((res, rej) => { + resolve = res + reject = rej + }) + query.callback = (err, res) => err ? reject(err) : resolve(res) + } this._queryQueue.push(query); this._pulseQueryQueue(); - return query; + return result; }; //disconnect from the backend server diff --git a/lib/query.js b/lib/query.js index b997091c2..99b5ea8b5 100644 --- a/lib/query.js +++ b/lib/query.js @@ -53,23 +53,6 @@ Query.prototype.requiresPreparation = function() { return this.values.length > 0; }; -Query.prototype.then = function(onSuccess, onFailure) { - return this._getPromise().then(onSuccess, onFailure); -}; - -Query.prototype.catch = function(callback) { - return this._getPromise().catch(callback); -}; - -Query.prototype._getPromise = function() { - if (this._promise) return this._promise; - this._promise = new Promise(function(resolve, reject) { - this._once('end', resolve); - this._once('error', reject); - }.bind(this)); - return this._promise; -}; - //associates row metadata from the supplied //message with this query object //metadata used when parsing row results diff --git a/lib/utils.js b/lib/utils.js index 381775ff6..e658bbd48 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -138,23 +138,6 @@ function normalizeQueryConfig (config, values, callback) { return config; } -const queryEventEmitterOverloadDeprecationMessage = ` -Using the automatically created return value from client.query as an event emitter is deprecated. -Use either the callback or promise interface. -` - -const deprecateEventEmitter = function(Emitter) { - const Result = function () { - Emitter.apply(this, arguments) - } - util.inherits(Result, Emitter) - Result.prototype._on = Result.prototype.on - Result.prototype._once = Result.prototype.once - Result.prototype.on = util.deprecate(Result.prototype.on, queryEventEmitterOverloadDeprecationMessage) - Result.prototype.once = util.deprecate(Result.prototype.once, queryEventEmitterOverloadDeprecationMessage) - return Result -} - module.exports = { prepareValue: function prepareValueWrapper (value) { //this ensures that extra arguments do not get passed into prepareValue @@ -162,5 +145,4 @@ module.exports = { return prepareValue(value); }, normalizeQueryConfig: normalizeQueryConfig, - deprecateEventEmitter: deprecateEventEmitter, }; diff --git a/test/integration/client/array-tests.js b/test/integration/client/array-tests.js index 7512d55bb..a26c76361 100644 --- a/test/integration/client/array-tests.js +++ b/test/integration/client/array-tests.js @@ -3,7 +3,8 @@ var pg = helper.pg; var suite = new helper.Suite() -pg.connect(assert.calls(function(err, client, release) { +const pool = new pg.Pool() +pool.connect(assert.calls(function(err, client, release) { assert.isNull(err); suite.test('nulls', function(done) { @@ -33,7 +34,7 @@ pg.connect(assert.calls(function(err, client, release) { suite.test('cleanup', () => release()) })); -pg.connect(assert.calls(function (err, client, release) { +pool.connect(assert.calls(function (err, client, release) { assert.isNull(err); client.query("CREATE TEMP TABLE why(names text[], numbors integer[])"); client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log); @@ -166,8 +167,7 @@ pg.connect(assert.calls(function (err, client, release) { assert.equal(names[2][0], 3); assert.equal(names[2][1], 100); release(); - pg.end(); - done(); + pool.end(done) })) }) diff --git a/test/integration/client/cancel-query-tests.js b/test/integration/client/cancel-query-tests.js deleted file mode 100644 index 4485b328f..000000000 --- a/test/integration/client/cancel-query-tests.js +++ /dev/null @@ -1,41 +0,0 @@ -var helper = require("./test-helper"); -var Query = helper.pg.Query; - -//before running this test make sure you run the script create-test-tables -new helper.Suite().test("cancellation of a query", function() { - - var client = helper.client(); - - var qry = "select name from person order by name"; - - client.on('drain', client.end.bind(client)); - - var rows3 = 0; - - var query1 = client.query(new Query(qry)); - query1.on('row', function(row) { - throw new Error('Should not emit a row') - }); - var query2 = client.query(new Query(qry)); - query2.on('row', function(row) { - throw new Error('Should not emit a row') - }); - var query3 = client.query(new Query(qry)); - query3.on('row', function(row) { - rows3++; - }); - var query4 = client.query(new Query(qry)); - query4.on('row', function(row) { - throw new Error('Should not emit a row') - }); - - helper.pg.cancel(helper.config, client, query1); - helper.pg.cancel(helper.config, client, query2); - helper.pg.cancel(helper.config, client, query4); - - assert.emits(query3, 'end', function() { - test("returned right number of rows", function() { - assert.equal(rows3, 26); - }); - }); -}); diff --git a/test/integration/client/huge-numeric-tests.js b/test/integration/client/huge-numeric-tests.js index 76b2aac5a..9cd905371 100644 --- a/test/integration/client/huge-numeric-tests.js +++ b/test/integration/client/huge-numeric-tests.js @@ -1,6 +1,7 @@ var helper = require('./test-helper'); +const pool = new helper.pg.Pool() -helper.pg.connect(helper.config, assert.success(function(client, done) { +pool.connect(assert.success(function(client, done) { var types = require('pg-types'); //1231 = numericOID types.setTypeParser(1700, function(){ @@ -14,7 +15,7 @@ helper.pg.connect(helper.config, assert.success(function(client, done) { client.query('INSERT INTO bignumz(id) VALUES ($1)', [bignum]); client.query('SELECT * FROM bignumz', assert.success(function(result) { assert.equal(result.rows[0].id, 'yes') - helper.pg.end(); done(); + pool.end() })) })); diff --git a/test/integration/client/json-type-parsing-tests.js b/test/integration/client/json-type-parsing-tests.js index 1fe21ac53..e3dca3a55 100644 --- a/test/integration/client/json-type-parsing-tests.js +++ b/test/integration/client/json-type-parsing-tests.js @@ -1,7 +1,8 @@ var helper = require('./test-helper'); var assert = require('assert'); -helper.pg.connect(assert.success(function (client, done) { +const pool = new helper.pg.Pool() +pool.connect(assert.success(function (client, done) { helper.versionGTE(client, '9.2.0', assert.success(function (jsonSupported) { if (!jsonSupported) { console.log('skip json test on older versions of postgres'); @@ -20,7 +21,7 @@ helper.pg.connect(assert.success(function (client, done) { assert.strictEqual(row.alive, value.alive); assert.equal(JSON.stringify(row.now), JSON.stringify(value.now)); done(); - helper.pg.end(); + pool.end() })); })); })); diff --git a/test/integration/client/no-row-result-tests.js b/test/integration/client/no-row-result-tests.js index 9081e2330..cc91c647f 100644 --- a/test/integration/client/no-row-result-tests.js +++ b/test/integration/client/no-row-result-tests.js @@ -1,23 +1,27 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require("./test-helper"); var pg = helper.pg; -const suite = new helper.Suite() +const suite = new helper.Suite(); +const pool = new pg.Pool(); -suite.test('can access results when no rows are returned', function() { - var checkResult = function(result) { - assert(result.fields, 'should have fields definition'); +suite.test("can access results when no rows are returned", function (done) { + var checkResult = function (result) { + assert(result.fields, "should have fields definition"); assert.equal(result.fields.length, 1); - assert.equal(result.fields[0].name, 'val'); + assert.equal(result.fields[0].name, "val"); assert.equal(result.fields[0].dataTypeID, 25); - pg.end(); }; - pg.connect(assert.success(function(client, done) { - const q = new pg.Query('select $1::text as val limit 0', ['hi']) - var query = client.query(q, assert.success(function(result) { - checkResult(result); - done(); - })); + pool.connect( + assert.success(function (client, release) { + const q = new pg.Query("select $1::text as val limit 0", ["hi"]); + var query = client.query(q, assert.success(function (result) { + checkResult(result); + release(); + pool.end(done); + }) + ); - assert.emits(query, 'end', checkResult); - })); + assert.emits(query, "end", checkResult); + }) + ); }); diff --git a/test/integration/client/parse-int-8-tests.js b/test/integration/client/parse-int-8-tests.js index 4ece94456..937b41b72 100644 --- a/test/integration/client/parse-int-8-tests.js +++ b/test/integration/client/parse-int-8-tests.js @@ -3,9 +3,10 @@ var helper = require('../test-helper'); var pg = helper.pg; const suite = new helper.Suite() +const pool = new pg.Pool(helper.config) suite.test('ability to turn on and off parser', function() { if(helper.args.binary) return false; - pg.connect(helper.config, assert.success(function(client, done) { + pool.connect(assert.success(function(client, done) { pg.defaults.parseInt8 = true; client.query('CREATE TEMP TABLE asdf(id SERIAL PRIMARY KEY)'); client.query('SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', assert.success(function(res) { @@ -20,7 +21,7 @@ suite.test('ability to turn on and off parser', function() { assert.strictEqual('1', res.rows[0].array[0]); assert.strictEqual('2', res.rows[0].array[1]); assert.strictEqual('3', res.rows[0].array[2]); - pg.end(); + pool.end(); })); })); })); diff --git a/test/integration/client/query-as-promise-tests.js b/test/integration/client/query-as-promise-tests.js index 92eedcc85..95bf73ce4 100644 --- a/test/integration/client/query-as-promise-tests.js +++ b/test/integration/client/query-as-promise-tests.js @@ -6,22 +6,27 @@ process.on('unhandledRejection', function(e) { process.exit(1) }) -pg.connect(helper.config, assert.success(function(client, done) { - client.query('SELECT $1::text as name', ['foo']) - .then(function(result) { - assert.equal(result.rows[0].name, 'foo') - return client - }) - .then(function(client) { - client.query('ALKJSDF') - .catch(function(e) { - assert(e instanceof Error) - client.query('SELECT 1 as num') - .then(function (result) { - assert.equal(result.rows[0].num, 1) - done() - pg.end() - }) - }) - }) -})) +const pool = new pg.Pool() +const suite = new helper.Suite() + +suite.test('promise API', (cb) => { + pool.connect().then((client) => { + client.query('SELECT $1::text as name', ['foo']) + .then(function (result) { + assert.equal(result.rows[0].name, 'foo') + return client + }) + .then(function (client) { + client.query('ALKJSDF') + .catch(function (e) { + assert(e instanceof Error) + client.query('SELECT 1 as num') + .then(function (result) { + assert.equal(result.rows[0].num, 1) + client.release() + pool.end(cb) + }) + }) + }) + }) +}) diff --git a/test/integration/client/query-column-names-tests.js b/test/integration/client/query-column-names-tests.js index 811d673a0..d929b5088 100644 --- a/test/integration/client/query-column-names-tests.js +++ b/test/integration/client/query-column-names-tests.js @@ -1,13 +1,14 @@ var helper = require(__dirname + '/../test-helper'); var pg = helper.pg; -test('support for complex column names', function() { - pg.connect(helper.config, assert.success(function(client, done) { +new helper.Suite().test('support for complex column names', function () { + const pool = new pg.Pool() + pool.connect(assert.success(function (client, done) { client.query("CREATE TEMP TABLE t ( \"complex''column\" TEXT )"); - client.query('SELECT * FROM t', assert.success(function(res) { - done(); - assert.strictEqual(res.fields[0].name, "complex''column"); - pg.end(); + client.query('SELECT * FROM t', assert.success(function (res) { + done(); + assert.strictEqual(res.fields[0].name, "complex''column"); + pool.end(); })); })); -}); \ No newline at end of file +}); diff --git a/test/integration/client/result-metadata-tests.js b/test/integration/client/result-metadata-tests.js index 221db7763..85b7e18c5 100644 --- a/test/integration/client/result-metadata-tests.js +++ b/test/integration/client/result-metadata-tests.js @@ -1,8 +1,9 @@ -var helper = require(__dirname + "/test-helper"); +var helper = require("./test-helper"); var pg = helper.pg; -test('should return insert metadata', function() { - pg.connect(helper.config, assert.calls(function(err, client, done) { +const pool = new pg.Pool() +new helper.Suite().test('should return insert metadata', function() { + pool.connect(assert.calls(function(err, client, done) { assert.isNull(err); helper.versionGTE(client, '9.0.0', assert.success(function(hasRowCount) { @@ -21,7 +22,7 @@ test('should return insert metadata', function() { if(hasRowCount) assert.equal(result.rowCount, 1); assert.equal(result.command, 'SELECT'); done(); - process.nextTick(pg.end.bind(pg)); + process.nextTick(pool.end.bind(pool)); })); })); })); diff --git a/test/integration/client/timezone-tests.js b/test/integration/client/timezone-tests.js index b355550df..298734319 100644 --- a/test/integration/client/timezone-tests.js +++ b/test/integration/client/timezone-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/../test-helper'); +var helper = require('./../test-helper'); var exec = require('child_process').exec; var oldTz = process.env.TZ; @@ -6,24 +6,28 @@ process.env.TZ = 'Europe/Berlin'; var date = new Date(); -helper.pg.connect(helper.config, function(err, client, done) { +const pool = new helper.pg.Pool() +const suite = new helper.Suite() + +pool.connect(function (err, client, done) { assert.isNull(err); - test('timestamp without time zone', function() { - client.query("SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS \"val\"", [ date ], function(err, result) { + suite.test('timestamp without time zone', function (cb) { + client.query("SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS \"val\"", [date], function (err, result) { assert.isNull(err); assert.equal(result.rows[0].val.getTime(), date.getTime()); + cb() + }) + }) - test('timestamp with time zone', function() { - client.query("SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS \"val\"", [ date ], function(err, result) { - assert.isNull(err); - assert.equal(result.rows[0].val.getTime(), date.getTime()); + suite.test('timestamp with time zone', function (cb) { + client.query("SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS \"val\"", [date], function (err, result) { + assert.isNull(err); + assert.equal(result.rows[0].val.getTime(), date.getTime()); - done(); - helper.pg.end(); - process.env.TZ = oldTz; - }); - }); + done(); + pool.end(cb) + process.env.TZ = oldTz; }); }); -}); \ No newline at end of file +}); diff --git a/test/integration/client/transaction-tests.js b/test/integration/client/transaction-tests.js index 85ee7e539..389a70d0c 100644 --- a/test/integration/client/transaction-tests.js +++ b/test/integration/client/transaction-tests.js @@ -1,72 +1,76 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); +const suite = new helper.Suite() +const pg = helper.pg -var sink = new helper.Sink(2, function() { - helper.pg.end(); -}); +const client = new pg.Client() +client.connect(assert.success(function () { -test('a single connection transaction', function() { - helper.pg.connect(helper.config, assert.success(function(client, done) { + client.query('begin'); - client.query('begin'); + var getZed = { + text: 'SELECT * FROM person WHERE name = $1', + values: ['Zed'] + }; - var getZed = { - text: 'SELECT * FROM person WHERE name = $1', - values: ['Zed'] - }; - - test('Zed should not exist in the database', function() { - client.query(getZed, assert.calls(function(err, result) { - assert.isNull(err); - assert.empty(result.rows); - })) - }) + suite.test('name should not exist in the database', function (done) { + client.query(getZed, assert.calls(function (err, result) { + assert.isNull(err); + assert.empty(result.rows); + done() + })) + }) - client.query("INSERT INTO person(name, age) VALUES($1, $2)", ['Zed', 270], assert.calls(function(err, result) { + suite.test('can insert name', (done) => { + client.query("INSERT INTO person(name, age) VALUES($1, $2)", ['Zed', 270], assert.calls(function (err, result) { assert.isNull(err) + done() })); + }) - test('Zed should exist in the database', function() { - client.query(getZed, assert.calls(function(err, result) { - assert.isNull(err); - assert.equal(result.rows[0].name, 'Zed'); - })) - }) + suite.test('name should exist in the database', function (done) { + client.query(getZed, assert.calls(function (err, result) { + assert.isNull(err); + assert.equal(result.rows[0].name, 'Zed'); + done() + })) + }) - client.query('rollback'); + suite.test('rollback', (done) => { + client.query('rollback', done); + }) - test('Zed should not exist in the database', function() { - client.query(getZed, assert.calls(function(err, result) { - assert.isNull(err); - assert.empty(result.rows); - done(); - sink.add(); - })) - }) - })) -}) + suite.test('name should not exist in the database', function (done) { + client.query(getZed, assert.calls(function (err, result) { + assert.isNull(err); + assert.empty(result.rows); + client.end(done) + })) + }) +})) -test('gh#36', function() { - helper.pg.connect(helper.config, assert.success(function(client, done) { +suite.test('gh#36', function (cb) { + const pool = new pg.Pool() + pool.connect(assert.success(function (client, done) { client.query("BEGIN"); client.query({ name: 'X', text: "SELECT $1::INTEGER", values: [0] - }, assert.calls(function(err, result) { - if(err) throw err; + }, assert.calls(function (err, result) { + if (err) throw err; assert.equal(result.rows.length, 1); })) client.query({ name: 'X', text: "SELECT $1::INTEGER", values: [0] - }, assert.calls(function(err, result) { - if(err) throw err; + }, assert.calls(function (err, result) { + if (err) throw err; assert.equal(result.rows.length, 1); })) - client.query("COMMIT", function() { - sink.add(); + client.query("COMMIT", function () { done(); + pool.end(cb) }) })); }) diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index 98f3148ae..dc50732e8 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -1,29 +1,33 @@ var helper = require(__dirname + '/test-helper'); var pg = helper.pg; var sink; +const suite = new helper.Suite() -var testForTypeCoercion = function(type){ - helper.pg.connect(helper.config, function(err, client, done) { - assert.isNull(err); - client.query("create temp table test_type(col " + type.name + ")", assert.calls(function(err, result) { +var testForTypeCoercion = function (type) { + const pool = new pg.Pool() + suite.test(`test type coercion ${type.name}`, (cb) => { + pool.connect(function (err, client, done) { assert.isNull(err); - test("Coerces " + type.name, function() { - type.values.forEach(function(val) { + client.query("create temp table test_type(col " + type.name + ")", assert.calls(function (err, result) { + assert.isNull(err); - var insertQuery = client.query('insert into test_type(col) VALUES($1)',[val],assert.calls(function(err, result) { + type.values.forEach(function (val) { + + var insertQuery = client.query('insert into test_type(col) VALUES($1)', [val], assert.calls(function (err, result) { assert.isNull(err); })); var query = client.query(new pg.Query({ - name: 'get type ' + type.name , + name: 'get type ' + type.name, text: 'select col from test_type' })); - query.on('error', function(err) { + + query.on('error', function (err) { console.log(err); throw err; }); - assert.emits(query, 'row', function(row) { + assert.emits(query, 'row', function (row) { var expected = val + " (" + typeof val + ")"; var returned = row.col + " (" + typeof row.col + ")"; assert.strictEqual(row.col, val, "expected " + type.name + " of " + expected + " but got " + returned); @@ -32,22 +36,23 @@ var testForTypeCoercion = function(type){ client.query('delete from test_type'); }); - client.query('drop table test_type', function() { - sink.add(); + client.query('drop table test_type', function () { done(); + pool.end(cb) }); - }) - })); + })); + }) + }) }; var types = [{ name: 'integer', values: [-2147483648, -1, 0, 1, 2147483647, null] -},{ +}, { name: 'smallint', values: [-32768, -1, 0, 1, 32767, null] -},{ +}, { name: 'bigint', values: [ '-9223372036854775808', @@ -58,16 +63,16 @@ var types = [{ '9223372036854775807', null ] -},{ +}, { name: 'varchar(5)', values: ['yo', '', 'zomg!', null] -},{ +}, { name: 'oid', values: [0, 204410, null] -},{ +}, { name: 'bool', values: [true, false, null] -},{ +}, { name: 'numeric', values: [ '-12.34', @@ -77,52 +82,42 @@ var types = [{ '3141592653589793238462643383279502.1618033988749894848204586834365638', null ] -},{ +}, { name: 'real', values: [-101.3, -1.2, 0, 1.2, 101.1, null] -},{ +}, { name: 'double precision', values: [-101.3, -1.2, 0, 1.2, 101.1, null] -},{ +}, { name: 'timestamptz', values: [null] -},{ +}, { name: 'timestamp', values: [null] -},{ +}, { name: 'timetz', - values: ['13:11:12.1234-05:30',null] -},{ + values: ['13:11:12.1234-05:30', null] +}, { name: 'time', values: ['13:12:12.321', null] }]; // ignore some tests in binary mode if (helper.config.binary) { - types = types.filter(function(type) { - return !(type.name in {'real': 1, 'timetz':1, 'time':1, 'numeric': 1, 'bigint': 1}); + types = types.filter(function (type) { + return !(type.name in { 'real': 1, 'timetz': 1, 'time': 1, 'numeric': 1, 'bigint': 1 }); }); } var valueCount = 0; -types.forEach(function(type) { - valueCount += type.values.length; -}) -sink = new helper.Sink(types.length + 1, function() { - helper.pg.end(); -}) -types.forEach(function(type) { +types.forEach(function (type) { testForTypeCoercion(type) }); -test("timestampz round trip", function() { +suite.test("timestampz round trip", function (cb) { var now = new Date(); var client = helper.client(); - client.on('error', function(err) { - console.log(err); - client.end(); - }); client.query("create temp table date_tests(name varchar(10), tstz timestamptz(3))"); client.query({ text: "insert into date_tests(name, tstz)VALUES($1, $2)", @@ -135,67 +130,66 @@ test("timestampz round trip", function() { values: ['now'] })); - assert.emits(result, 'row', function(row) { + assert.emits(result, 'row', function (row) { var date = row.tstz; - assert.equal(date.getYear(),now.getYear()); + assert.equal(date.getYear(), now.getYear()); assert.equal(date.getMonth(), now.getMonth()); assert.equal(date.getDate(), now.getDate()); assert.equal(date.getHours(), now.getHours()); assert.equal(date.getMinutes(), now.getMinutes()); assert.equal(date.getSeconds(), now.getSeconds()); - test("milliseconds are equal", function() { - assert.equal(date.getMilliseconds(), now.getMilliseconds()); - }); + assert.equal(date.getMilliseconds(), now.getMilliseconds()); }); - client.on('drain', client.end.bind(client)); + client.on('drain', () => { + client.end(cb) + }); }); -if(!helper.config.binary) { - test('date range extremes', function() { - var client = helper.client(); - client.on('error', function(err) { - console.log(err); - client.end(); - }); +suite.test('selecting nulls', cb => { + const pool = new pg.Pool() + pool.connect(assert.calls(function (err, client, done) { + assert.ifError(err); + client.query('select null as res;', assert.calls(function (err, res) { + assert.isNull(err); + assert.strictEqual(res.rows[0].res, null) + })) + client.query('select 7 <> $1 as res;', [null], function (err, res) { + assert.isNull(err); + assert.strictEqual(res.rows[0].res, null); + done(); + pool.end(cb) + }) + })) +}) - // Set the server timeszone to the same as used for the test, - // otherwise (if server's timezone is ahead of GMT) in - // textParsers.js::parseDate() the timezone offest is added to the date; - // in the case of "275760-09-13 00:00:00 GMT" the timevalue overflows. - client.query('SET TIMEZONE TO GMT', assert.success(function(res){ - - // PostgreSQL supports date range of 4713 BCE to 294276 CE - // http://www.postgresql.org/docs/9.2/static/datatype-datetime.html - // ECMAScript supports date range of Apr 20 271821 BCE to Sep 13 275760 CE - // http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1 - client.query('SELECT $1::TIMESTAMPTZ as when', ["275760-09-13 00:00:00 GMT"], assert.success(function(res) { - assert.equal(res.rows[0].when.getFullYear(), 275760); - })); +suite.test('date range extremes', function (done) { + var client = helper.client(); - client.query('SELECT $1::TIMESTAMPTZ as when', ["4713-12-31 12:31:59 BC GMT"], assert.success(function(res) { - assert.equal(res.rows[0].when.getFullYear(), -4713); - })); + // Set the server timeszone to the same as used for the test, + // otherwise (if server's timezone is ahead of GMT) in + // textParsers.js::parseDate() the timezone offest is added to the date; + // in the case of "275760-09-13 00:00:00 GMT" the timevalue overflows. + client.query('SET TIMEZONE TO GMT', assert.success(function (res) { + + // PostgreSQL supports date range of 4713 BCE to 294276 CE + // http://www.postgresql.org/docs/9.2/static/datatype-datetime.html + // ECMAScript supports date range of Apr 20 271821 BCE to Sep 13 275760 CE + // http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1 + client.query('SELECT $1::TIMESTAMPTZ as when', ["275760-09-13 00:00:00 GMT"], assert.success(function (res) { + assert.equal(res.rows[0].when.getFullYear(), 275760); + })); - client.query('SELECT $1::TIMESTAMPTZ as when', ["275760-09-13 00:00:00 -15:00"], assert.success(function(res) { - assert( isNaN(res.rows[0].when.getTime()) ); - })); + client.query('SELECT $1::TIMESTAMPTZ as when', ["4713-12-31 12:31:59 BC GMT"], assert.success(function (res) { + assert.equal(res.rows[0].when.getFullYear(), -4713); + })); - client.on('drain', client.end.bind(client)); + client.query('SELECT $1::TIMESTAMPTZ as when', ["275760-09-13 00:00:00 -15:00"], assert.success(function (res) { + assert(isNaN(res.rows[0].when.getTime())); })); - }); -} -helper.pg.connect(helper.config, assert.calls(function(err, client, done) { - assert.ifError(err); - client.query('select null as res;', assert.calls(function(err, res) { - assert.isNull(err); - assert.strictEqual(res.rows[0].res, null) - })) - client.query('select 7 <> $1 as res;',[null], function(err, res) { - assert.isNull(err); - assert.strictEqual(res.rows[0].res, null); - sink.add(); - done(); - }) -})) + client.on('drain', () => { + client.end(done) + }); + })); +}); diff --git a/test/integration/client/type-parser-override-tests.js b/test/integration/client/type-parser-override-tests.js index 68a5de7f7..3fd52dd28 100644 --- a/test/integration/client/type-parser-override-tests.js +++ b/test/integration/client/type-parser-override-tests.js @@ -1,4 +1,4 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); function testTypeParser(client, expectedResult, done) { var boolValue = true; @@ -6,13 +6,13 @@ function testTypeParser(client, expectedResult, done) { client.query('INSERT INTO parserOverrideTest(id) VALUES ($1)', [boolValue]); client.query('SELECT * FROM parserOverrideTest', assert.success(function(result) { assert.equal(result.rows[0].id, expectedResult); - helper.pg.end(); done(); })); } -helper.pg.connect(helper.config, assert.success(function(client1, done1) { - helper.pg.connect(helper.config, assert.success(function(client2, done2) { +const pool = new helper.pg.Pool(helper.config) +pool.connect(assert.success(function(client1, done1) { + pool.connect(assert.success(function(client2, done2) { var boolTypeOID = 16; client1.setTypeParser(boolTypeOID, function(){ return 'first client'; @@ -28,7 +28,9 @@ helper.pg.connect(helper.config, assert.success(function(client1, done1) { return 'second client binary'; }); - testTypeParser(client1, 'first client', done1); - testTypeParser(client2, 'second client', done2); + testTypeParser(client1, 'first client', () => { + done1() + testTypeParser(client2, 'second client', () => done2(), pool.end()); + }); })); })); diff --git a/test/integration/connection-pool/connection-pool-size-tests.js b/test/integration/connection-pool/connection-pool-size-tests.js new file mode 100644 index 000000000..998bff7e4 --- /dev/null +++ b/test/integration/connection-pool/connection-pool-size-tests.js @@ -0,0 +1,9 @@ +var helper = require("./test-helper") + +helper.testPoolSize(1); + +helper.testPoolSize(2); + +helper.testPoolSize(40); + +helper.testPoolSize(200); diff --git a/test/integration/connection-pool/double-connection-tests.js b/test/integration/connection-pool/double-connection-tests.js deleted file mode 100644 index 421e1f9ea..000000000 --- a/test/integration/connection-pool/double-connection-tests.js +++ /dev/null @@ -1,2 +0,0 @@ -var helper = require("./test-helper") -helper.testPoolSize(2); diff --git a/test/integration/connection-pool/ending-empty-pool-tests.js b/test/integration/connection-pool/ending-empty-pool-tests.js deleted file mode 100644 index d1acc6f20..000000000 --- a/test/integration/connection-pool/ending-empty-pool-tests.js +++ /dev/null @@ -1,15 +0,0 @@ -var helper = require('./test-helper') - -var called = false; -test('disconnects', function() { - called = true; - var eventSink = new helper.Sink(1, function() {}); - helper.pg.on('end', function() { - eventSink.add(); - }); - - //this should exit the process - helper.pg.end(); -}) - - diff --git a/test/integration/connection-pool/ending-pool-tests.js b/test/integration/connection-pool/ending-pool-tests.js deleted file mode 100644 index 3a1ab46f9..000000000 --- a/test/integration/connection-pool/ending-pool-tests.js +++ /dev/null @@ -1,30 +0,0 @@ -var helper = require('./test-helper') - -var called = false; - -test('disconnects', function() { - var sink = new helper.Sink(4, function() { - called = true; - var eventSink = new helper.Sink(1, function() {}); - helper.pg.on('end', function() { - eventSink.add(); - }); - - //this should exit the process, killing each connection pool - helper.pg.end(); - }); - [helper.config, helper.config, helper.config, helper.config].forEach(function(config) { - helper.pg.connect(config, function(err, client, done) { - assert.isNull(err); - client.query("SELECT * FROM NOW()", function(err, result) { - setTimeout(function() { - assert.equal(called, false, "Should not have disconnected yet") - sink.add(); - done(); - }, 0) - }) - }) - }) -}) - - diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index 59121a86e..21f615319 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -1,40 +1,46 @@ -var helper = require("../test-helper"); -var pg = require("../../../lib"); +var helper = require("./test-helper"); +const pg = helper.pg //first make pool hold 2 clients pg.defaults.poolSize = 2; -//get first client -pg.connect(helper.config, assert.success(function(client, done) { - client.id = 1; - client.query('SELECT NOW()', function() { - pg.connect(helper.config, assert.success(function(client2, done2) { - client2.id = 2; - var pidColName = 'procpid'; - helper.versionGTE(client2, '9.2.0', assert.success(function(isGreater) { - var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1'; - var params = ['idle']; - if(!isGreater) { - killIdleQuery = 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE $1'; - params = ['%IDLE%'] - } +const pool = new pg.Pool() - //subscribe to the pg error event - assert.emits(pg, 'error', function(error, brokenClient) { - assert.ok(error); - assert.ok(brokenClient); - assert.equal(client.id, brokenClient.id); - }); +const suite = new helper.Suite() +suite.test('errors emitted on pool', (cb) => { + //get first client + pool.connect(assert.success(function (client, done) { + client.id = 1; + client.query('SELECT NOW()', function () { + pool.connect(assert.success(function (client2, done2) { + client2.id = 2; + var pidColName = 'procpid'; + helper.versionGTE(client2, '9.2.0', assert.success(function (isGreater) { + var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1'; + var params = ['idle']; + if (!isGreater) { + killIdleQuery = 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE $1'; + params = ['%IDLE%'] + } - //kill the connection from client - client2.query(killIdleQuery, params, assert.success(function(res) { - //check to make sure client connection actually was killed - //return client2 to the pool - done2(); - pg.end(); + pool.once('error', (err, brokenClient) => { + assert.ok(err); + assert.ok(brokenClient); + assert.equal(client.id, brokenClient.id); + cb() + }) + + //kill the connection from client + client2.query(killIdleQuery, params, assert.success(function (res) { + //check to make sure client connection actually was killed + //return client2 to the pool + done2(); + pool.end(); + })); })); })); - })); - }) -})); + }) + })); + +}) diff --git a/test/integration/connection-pool/idle-timeout-tests.js b/test/integration/connection-pool/idle-timeout-tests.js index 5a5db0ba9..e8090a09f 100644 --- a/test/integration/connection-pool/idle-timeout-tests.js +++ b/test/integration/connection-pool/idle-timeout-tests.js @@ -1,13 +1,12 @@ -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); -const config = Object.assign({ }, helper.config, { idleTimeoutMillis: 50 }) -test('idle timeout', function() { - helper.pg.connect(config, assert.calls(function(err, client, done) { - assert.isNull(err); - client.query('SELECT NOW()'); - //just let this one time out - //test will hang if pool doesn't timeout - done(); - })); +new helper.Suite().test('idle timeout', function () { + const config = Object.assign({}, helper.config, { idleTimeoutMillis: 50 }) + const pool = new helper.pg.Pool(config) + pool.connect(assert.calls(function (err, client, done) { + assert.isNull(err); + client.query('SELECT NOW()'); + done(); + })); }); diff --git a/test/integration/connection-pool/max-connection-tests.js b/test/integration/connection-pool/max-connection-tests.js deleted file mode 100644 index 944d2fb2e..000000000 --- a/test/integration/connection-pool/max-connection-tests.js +++ /dev/null @@ -1,2 +0,0 @@ -var helper = require("./test-helper") -helper.testPoolSize(40); diff --git a/test/integration/connection-pool/optional-config-tests.js b/test/integration/connection-pool/optional-config-tests.js deleted file mode 100644 index be7063eb8..000000000 --- a/test/integration/connection-pool/optional-config-tests.js +++ /dev/null @@ -1,20 +0,0 @@ -var helper = require('./test-helper'); - -//setup defaults -helper.pg.defaults.user = helper.args.user; -helper.pg.defaults.password = helper.args.password; -helper.pg.defaults.host = helper.args.host; -helper.pg.defaults.port = helper.args.port; -helper.pg.defaults.database = helper.args.database; -helper.pg.defaults.poolSize = 1; - -helper.pg.connect(assert.calls(function(err, client, done) { - assert.isNull(err); - client.query('SELECT NOW()'); - client.once('drain', function() { - setTimeout(function() { - helper.pg.end(); - done(); - }, 10); - }); -})); diff --git a/test/integration/connection-pool/single-connection-tests.js b/test/integration/connection-pool/single-connection-tests.js deleted file mode 100644 index 89f6f069e..000000000 --- a/test/integration/connection-pool/single-connection-tests.js +++ /dev/null @@ -1,2 +0,0 @@ -var helper = require("./test-helper") -helper.testPoolSize(1); diff --git a/test/integration/connection-pool/single-pool-on-object-config-tests.js b/test/integration/connection-pool/single-pool-on-object-config-tests.js deleted file mode 100644 index 81cdf8e45..000000000 --- a/test/integration/connection-pool/single-pool-on-object-config-tests.js +++ /dev/null @@ -1,13 +0,0 @@ -var helper = require("../test-helper"); -var pg = require("../../../lib"); - -pg.connect(helper.config, assert.success(function(client, done) { - assert.equal(Object.keys(pg._pools).length, 1); - pg.connect(helper.config, assert.success(function(client2, done2) { - assert.equal(Object.keys(pg._pools).length, 1); - - done(); - done2(); - pg.end(); - })); -})); diff --git a/test/integration/connection-pool/test-helper.js b/test/integration/connection-pool/test-helper.js index e4a3e4259..b66bcba51 100644 --- a/test/integration/connection-pool/test-helper.js +++ b/test/integration/connection-pool/test-helper.js @@ -1,32 +1,31 @@ -var helper = require(__dirname + "/../test-helper"); +var helper = require("./../test-helper"); -helper.testPoolSize = function(max) { - var sink = new helper.Sink(max, function() { - helper.pg.end(); - }); +const suite = new helper.Suite() - test("can pool " + max + " times", function() { - for(var i = 0; i < max; i++) { - helper.pg.poolSize = 10; - test("connection #" + i + " executes", function() { - helper.pg.connect(helper.config, function(err, client, done) { - assert.isNull(err); - client.query("select * from person", function(err, result) { - assert.lengthIs(result.rows, 26) - }) - client.query("select count(*) as c from person", function(err, result) { - assert.equal(result.rows[0].c, 26) - }) - var query = client.query("SELECT * FROM NOW()", (err) => { - assert(!err) - sink.add(); - done(); - }) +helper.testPoolSize = function (max) { + suite.test(`test ${max} queries executed on a pool rapidly`, (cb) => { + const pool = new helper.pg.Pool({ max: 10 }) + + var sink = new helper.Sink(max, function () { + pool.end(cb) + }); + + for (var i = 0; i < max; i++) { + pool.connect(function (err, client, done) { + assert.isNull(err); + client.query("SELECT * FROM NOW()") + client.query("select generate_series(0, 25)", function (err, result) { + assert.equal(result.rows.length, 26) + }) + var query = client.query("SELECT * FROM NOW()", (err) => { + assert(!err) + sink.add(); + done(); }) }) } }) } -module.exports = helper; +module.exports = Object.assign({}, helper, { suite: suite }) diff --git a/test/integration/connection-pool/waiting-connection-tests.js b/test/integration/connection-pool/waiting-connection-tests.js deleted file mode 100644 index 82572d1e4..000000000 --- a/test/integration/connection-pool/waiting-connection-tests.js +++ /dev/null @@ -1,2 +0,0 @@ -var helper = require("./test-helper") -helper.testPoolSize(200); diff --git a/test/integration/connection-pool/yield-support-tests.js b/test/integration/connection-pool/yield-support-tests.js index 943ab3a2e..c56d9851b 100644 --- a/test/integration/connection-pool/yield-support-tests.js +++ b/test/integration/connection-pool/yield-support-tests.js @@ -1,28 +1,19 @@ var helper = require('./test-helper') var co = require('co') -var tid = setTimeout(function() { - throw new Error('Tests did not complete in time') -}, 1000) - -co(function * () { - var client = yield helper.pg.connect() +const pool = new helper.pg.Pool() +new helper.Suite().test('using coroutines works with promises', co.wrap(function* () { + var client = yield pool.connect() var res = yield client.query('SELECT $1::text as name', ['foo']) assert.equal(res.rows[0].name, 'foo') var threw = false try { yield client.query('SELECT LKDSJDSLKFJ') - } catch(e) { + } catch (e) { threw = true } assert(threw) client.release() - helper.pg.end() - clearTimeout(tid) -}) -.catch(function(e) { - setImmediate(function() { - throw e - }) -}) + yield pool.end() +})) diff --git a/test/integration/domain-tests.js b/test/integration/domain-tests.js index dbd71c186..ce87335e2 100644 --- a/test/integration/domain-tests.js +++ b/test/integration/domain-tests.js @@ -4,22 +4,26 @@ var helper = require('./test-helper') var Query = helper.pg.Query var suite = new helper.Suite() +const Pool = helper.pg.Pool + suite.test('no domain', function (cb) { assert(!process.domain) - helper.pg.connect(assert.success(function (client, done) { + const pool = new Pool() + pool.connect(assert.success(function (client, done) { assert(!process.domain) done() - cb() + pool.end(cb) })) }) suite.test('with domain', function (cb) { assert(!process.domain) + const pool = new Pool() var domain = require('domain').create() domain.run(function () { var startingDomain = process.domain assert(startingDomain) - helper.pg.connect(helper.config, assert.success(function (client, done) { + pool.connect(assert.success(function (client, done) { assert(process.domain, 'no domain exists in connect callback') assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') var query = client.query('SELECT NOW()', assert.success(function () { @@ -27,7 +31,7 @@ suite.test('with domain', function (cb) { assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') done(true) process.domain.exit() - cb() + pool.end(cb) })) })) }) @@ -35,15 +39,14 @@ suite.test('with domain', function (cb) { suite.test('error on domain', function (cb) { var domain = require('domain').create() + const pool = new Pool() domain.on('error', function () { - cb() + pool.end(cb) }) domain.run(function () { - helper.pg.connect(helper.config, assert.success(function (client, done) { + pool.connect(assert.success(function (client, done) { client.query(new Query('SELECT SLDKJFLSKDJF')) client.on('drain', done) })) }) }) - -suite.test('cleanup', () => helper.pg.end()) diff --git a/test/integration/gh-issues/130-tests.js b/test/integration/gh-issues/130-tests.js index fba9d4b45..0fed550bb 100644 --- a/test/integration/gh-issues/130-tests.js +++ b/test/integration/gh-issues/130-tests.js @@ -3,7 +3,8 @@ var exec = require('child_process').exec; helper.pg.defaults.poolIdleTimeout = 1000; -helper.pg.connect(helper.config, function(err,client) { +const pool = new helper.pg.Pool() +pool.connect(function(err,client) { client.query("SELECT pg_backend_pid()", function(err, result) { var pid = result.rows[0].pg_backend_pid; var psql = 'psql'; @@ -16,6 +17,6 @@ helper.pg.connect(helper.config, function(err,client) { }); }); -helper.pg.on('error', function(err, client) { +pool.on('error', function(err, client) { //swallow errors }); diff --git a/test/integration/gh-issues/131-tests.js b/test/integration/gh-issues/131-tests.js index ff5c03444..41e71b5c3 100644 --- a/test/integration/gh-issues/131-tests.js +++ b/test/integration/gh-issues/131-tests.js @@ -4,7 +4,8 @@ var pg = helper.pg; var suite = new helper.Suite() suite.test('parsing array decimal results', function (done) { - pg.connect(helper.config, assert.calls(function (err, client, release) { + const pool = new pg.Pool() + pool.connect(assert.calls(function (err, client, release) { assert.isNull(err); client.query("CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])"); client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log); @@ -14,8 +15,7 @@ suite.test('parsing array decimal results', function (done) { assert.equal(result.rows[0].decimals[1], 0.05); assert.equal(result.rows[0].decimals[2], 3.654); release() - pg.end(); - done() + pool.end(done) })) })) }) diff --git a/test/integration/gh-issues/507-tests.js b/test/integration/gh-issues/507-tests.js index 097e3be11..57e0f7692 100644 --- a/test/integration/gh-issues/507-tests.js +++ b/test/integration/gh-issues/507-tests.js @@ -2,15 +2,15 @@ var helper = require(__dirname + "/../test-helper"); var pg = helper.pg; new helper.Suite().test('parsing array results', function(cb) { - pg.connect(helper.config, assert.success(function(client, done) { + const pool = new pg.Pool() + pool.connect(assert.success(function(client, done) { client.query('CREATE TEMP TABLE test_table(bar integer, "baz\'s" integer)') client.query('INSERT INTO test_table(bar, "baz\'s") VALUES(1, 1), (2, 2)') client.query('SELECT * FROM test_table', function(err, res) { assert.equal(res.rows[0]["baz's"], 1) assert.equal(res.rows[1]["baz's"], 2) done() - pg.end() - cb() + pool.end(cb) }) })) }) diff --git a/test/integration/gh-issues/675-tests.js b/test/integration/gh-issues/675-tests.js index f7fbf01bf..e1bc0a551 100644 --- a/test/integration/gh-issues/675-tests.js +++ b/test/integration/gh-issues/675-tests.js @@ -1,7 +1,8 @@ var helper = require('../test-helper'); var assert = require('assert'); -helper.pg.connect(function(err, client, done) { +const pool = new helper.pg.Pool() +pool.connect(function(err, client, done) { if (err) throw err; var c = 'CREATE TEMP TABLE posts (body TEXT)'; @@ -21,7 +22,7 @@ helper.pg.connect(function(err, client, done) { if (err) throw err; assert.equal(res.rows[0].body, '') - helper.pg.end(); + pool.end(); }); }); }); diff --git a/test/integration/gh-issues/699-tests.js b/test/integration/gh-issues/699-tests.js index 8e92ff221..6f47ffca5 100644 --- a/test/integration/gh-issues/699-tests.js +++ b/test/integration/gh-issues/699-tests.js @@ -4,7 +4,8 @@ var copyFrom = require('pg-copy-streams').from; if(helper.args.native) return; -helper.pg.connect(function (err, client, done) { +const pool = new helper.pg.Pool() +pool.connect(function (err, client, done) { if (err) throw err; var c = 'CREATE TEMP TABLE employee (id integer, fname varchar(400), lname varchar(400))'; @@ -16,7 +17,7 @@ helper.pg.connect(function (err, client, done) { stream.on('end', function () { done(); setTimeout(() => { - helper.pg.end(); + pool.end() }, 50) }); diff --git a/test/integration/gh-issues/787-tests.js b/test/integration/gh-issues/787-tests.js index df90cc542..773a033da 100644 --- a/test/integration/gh-issues/787-tests.js +++ b/test/integration/gh-issues/787-tests.js @@ -1,6 +1,7 @@ var helper = require('../test-helper'); +const pool = new helper.pg.Pool() -helper.pg.connect(function(err,client) { +pool.connect(function(err,client) { var q = { name: 'This is a super long query name just so I can test that an error message is properly spit out to console.error without throwing an exception or anything', text: 'SELECT NOW()' diff --git a/test/integration/gh-issues/981-tests.js b/test/integration/gh-issues/981-tests.js index ed3c3123a..4ba2f5ad4 100644 --- a/test/integration/gh-issues/981-tests.js +++ b/test/integration/gh-issues/981-tests.js @@ -1,7 +1,7 @@ -var helper = require(__dirname + '/../test-helper'); +var helper = require('./../test-helper'); //native bindings are only installed for native tests -if(!helper.args.native) { +if (!helper.args.native) { return; } @@ -15,13 +15,23 @@ var NativeClient = require('../../../lib/native') assert(pg.Client === JsClient); assert(native.Client === NativeClient); -pg.connect(function(err, client, done) { - assert(client instanceof JsClient); - client.end(); +const jsPool = new pg.Pool() +const nativePool = new native.Pool() - native.connect(function(err, client, done) { +const suite = new helper.Suite() +suite.test('js pool returns js client', cb => { + jsPool.connect(function (err, client, done) { + assert(client instanceof JsClient); + done() + jsPool.end(cb) + }) + +}) + +suite.test('native pool returns native client', cb => { + nativePool.connect(function (err, client, done) { assert(client instanceof NativeClient); - client.end(); + done() + nativePool.end(cb) }); -}); - +}) diff --git a/test/test-helper.js b/test/test-helper.js index 7fab5ad62..802d19c06 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -3,8 +3,6 @@ assert = require('assert'); var EventEmitter = require('events').EventEmitter; var sys = require('util'); -process.noDeprecation = true; - var BufferList = require('./buffer-list') const Suite = require('./suite') const args = require('./cli'); From 2300445646db264fe03a6194e2e7a77887204027 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 14:30:39 -0500 Subject: [PATCH 0236/1037] Cleanup a bit of dead code --- lib/client.js | 10 +++------- lib/index.js | 17 ++++++++++++++++- lib/native/index.js | 2 +- lib/pool-factory.js | 17 ----------------- lib/promise.js | 12 ------------ lib/utils.js | 10 +++++++++- test/unit/client/md5-password-tests.js | 9 +++++---- 7 files changed, 34 insertions(+), 43 deletions(-) delete mode 100644 lib/pool-factory.js delete mode 100644 lib/promise.js diff --git a/lib/client.js b/lib/client.js index 22026c1f4..b11a0f394 100644 --- a/lib/client.js +++ b/lib/client.js @@ -6,9 +6,9 @@ * README.md file in the root directory of this source tree. */ -var crypto = require('crypto'); var EventEmitter = require('events').EventEmitter; var util = require('util'); +var utils = require('./utils') var pgPass = require('pgpass'); var TypeOverrides = require('./type-overrides'); @@ -97,8 +97,8 @@ Client.prototype.connect = function(callback) { //password request handling con.on('authenticationMD5Password', checkPgPass(function(msg) { - var inner = Client.md5(self.password + self.user); - var outer = Client.md5(Buffer.concat([Buffer.from(inner), msg.salt])); + var inner = utils.md5(self.password + self.user); + var outer = utils.md5(Buffer.concat([Buffer.from(inner), msg.salt])); var md5password = "md5" + outer; con.password(md5password); })); @@ -406,10 +406,6 @@ Client.prototype.end = function (cb) { } }; -Client.md5 = function (string) { - return crypto.createHash('md5').update(string, 'utf-8').digest('hex'); -}; - // expose a Query constructor Client.Query = Query; diff --git a/lib/index.js b/lib/index.js index ac3fb059e..d12ea45a9 100644 --- a/lib/index.js +++ b/lib/index.js @@ -12,7 +12,22 @@ var Client = require('./client'); var defaults = require('./defaults'); var Connection = require('./connection'); var ConnectionParameters = require('./connection-parameters'); -var poolFactory = require('./pool-factory'); +var Pool = require('pg-pool'); + +const poolFactory = (Client) => { + var BoundPool = function(options) { + var config = { Client: Client }; + for (var key in options) { + config[key] = options[key]; + } + Pool.call(this, config); + }; + + util.inherits(BoundPool, Pool); + + return BoundPool; +}; + var PG = function(clientConstructor) { this.defaults = defaults; diff --git a/lib/native/index.js b/lib/native/index.js index ccf987e3a..a35a27334 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -1 +1 @@ -module.exports = require('./client'); +module.exports = require('./client') diff --git a/lib/pool-factory.js b/lib/pool-factory.js deleted file mode 100644 index 85f0e6a50..000000000 --- a/lib/pool-factory.js +++ /dev/null @@ -1,17 +0,0 @@ -var Client = require('./client'); -var util = require('util'); -var Pool = require('pg-pool'); - -module.exports = function(Client) { - var BoundPool = function(options) { - var config = { Client: Client }; - for (var key in options) { - config[key] = options[key]; - } - Pool.call(this, config); - }; - - util.inherits(BoundPool, Pool); - - return BoundPool; -}; diff --git a/lib/promise.js b/lib/promise.js deleted file mode 100644 index 4d308cb90..000000000 --- a/lib/promise.js +++ /dev/null @@ -1,12 +0,0 @@ -const util = require('util') -const deprecationMessage = 'Using the promise result as an event emitter is deprecated and will be removed in pg@8.0' -module.exports = function(emitter, callback) { - const promise = new global.Promise(callback) - promise.on = util.deprecate(function () { - emitter.on.apply(emitter, arguments) - }, deprecationMessage); - - promise.once = util.deprecate(function () { - emitter.once.apply(emitter, arguments) - }, deprecationMessage) -} diff --git a/lib/utils.js b/lib/utils.js index e658bbd48..7ecf4b295 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -7,7 +7,9 @@ */ const util = require('util') -var defaults = require('./defaults'); +const crypto = require('crypto'); + +const defaults = require('./defaults'); function escapeElement(elementRepresentation) { var escaped = elementRepresentation @@ -138,6 +140,11 @@ function normalizeQueryConfig (config, values, callback) { return config; } + +const md5 = function (string) { + return crypto.createHash('md5').update(string, 'utf-8').digest('hex'); +}; + module.exports = { prepareValue: function prepareValueWrapper (value) { //this ensures that extra arguments do not get passed into prepareValue @@ -145,4 +152,5 @@ module.exports = { return prepareValue(value); }, normalizeQueryConfig: normalizeQueryConfig, + md5: md5, }; diff --git a/test/unit/client/md5-password-tests.js b/test/unit/client/md5-password-tests.js index 315ef197b..78c826021 100644 --- a/test/unit/client/md5-password-tests.js +++ b/test/unit/client/md5-password-tests.js @@ -1,4 +1,5 @@ -require(__dirname + '/test-helper'); +require('./test-helper'); +var utils = require('../../../lib/utils') test('md5 authentication', function() { var client = createClient(); @@ -9,8 +10,8 @@ test('md5 authentication', function() { test('responds', function() { assert.lengthIs(client.connection.stream.packets, 1); test('should have correct encrypted data', function() { - var encrypted = Client.md5(client.password + client.user); - encrypted = Client.md5(encrypted + salt.toString('binary')); + var encrypted = utils.md5(client.password + client.user); + encrypted = utils.md5(encrypted + salt.toString('binary')); var password = "md5" + encrypted //how do we want to test this? assert.equalBuffers(client.connection.stream.packets[0], new BufferList() @@ -20,5 +21,5 @@ test('md5 authentication', function() { }); test('md5 of utf-8 strings', function() { - assert.equal(Client.md5('😊'), '5deda34cd95f304948d2bc1b4a62c11e'); + assert.equal(utils.md5('😊'), '5deda34cd95f304948d2bc1b4a62c11e'); }); From ed9a33d3d14cd5ad1e432476979d36a3c4bd10f6 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 14:54:42 -0500 Subject: [PATCH 0237/1037] Fix test for older version of postgres --- test/integration/client/json-type-parsing-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/client/json-type-parsing-tests.js b/test/integration/client/json-type-parsing-tests.js index e3dca3a55..b3ec40744 100644 --- a/test/integration/client/json-type-parsing-tests.js +++ b/test/integration/client/json-type-parsing-tests.js @@ -7,7 +7,7 @@ pool.connect(assert.success(function (client, done) { if (!jsonSupported) { console.log('skip json test on older versions of postgres'); done(); - return helper.pg.end(); + return pool.end(); } client.query('CREATE TEMP TABLE stuff(id SERIAL PRIMARY KEY, data JSON)'); var value = { name: 'Brian', age: 250, alive: true, now: new Date() }; From 49c5976947fa8d23722bd88de20fb699c1ce669b Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 15:14:20 -0500 Subject: [PATCH 0238/1037] Tweak travis node versions --- .travis.yml | 32 +++++++------------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/.travis.yml b/.travis.yml index ec0b7e3d6..46e3a3424 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,47 +8,29 @@ env: matrix: include: - - node_js: "4" + - node_js: "lts/argon" addons: postgresql: "9.6" - - node_js: "5" - addons: - postgresql: "9.6" - - node_js: "6" + - node_js: "lts/boron" addons: postgresql: "9.1" dist: precise - - node_js: "6" + - node_js: "lts/boron" addons: postgresql: "9.2" - - node_js: "6" + - node_js: "lts/boron" addons: postgresql: "9.3" - - node_js: "6" + - node_js: "lts/boron" addons: postgresql: "9.4" - - node_js: "6" + - node_js: "lts/boron" addons: postgresql: "9.5" - - node_js: "6" + - node_js: "lts/boron" addons: postgresql: "9.6" - - node_js: "8" - addons: - postgresql: "9.1" dist: precise - - node_js: "8" - addons: - postgresql: "9.2" - - node_js: "8" - addons: - postgresql: "9.3" - - node_js: "8" - addons: - postgresql: "9.4" - - node_js: "8" - addons: - postgresql: "9.5" - node_js: "8" addons: postgresql: "9.6" From 0f1f8626cf1e681f016ae844c3e1184fac67d2aa Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 15:34:30 -0500 Subject: [PATCH 0239/1037] Add use strict to every file --- lib/client.js | 1 + lib/connection-parameters.js | 1 + lib/connection.js | 1 + lib/defaults.js | 1 + lib/index.js | 1 + lib/native/client.js | 1 + lib/native/index.js | 1 + lib/native/query.js | 1 + lib/native/result.js | 1 + lib/query.js | 1 + lib/result.js | 1 + lib/type-overrides.js | 1 + lib/utils.js | 1 + script/create-test-tables.js | 1 + script/dump-db-types.js | 1 + script/list-db-types.js | 1 + test/buffer-list.js | 3 ++- test/cli.js | 1 + test/integration/client/api-tests.js | 1 + test/integration/client/appname-tests.js | 1 + test/integration/client/array-tests.js | 1 + test/integration/client/big-simple-query-tests.js | 1 + test/integration/client/configuration-tests.js | 1 + test/integration/client/custom-types-tests.js | 1 + test/integration/client/empty-query-tests.js | 1 + test/integration/client/error-handling-tests.js | 1 + test/integration/client/huge-numeric-tests.js | 1 + test/integration/client/json-type-parsing-tests.js | 1 + test/integration/client/network-partition-tests.js | 1 + test/integration/client/no-data-tests.js | 1 + test/integration/client/no-row-result-tests.js | 1 + test/integration/client/notice-tests.js | 1 + test/integration/client/parse-int-8-tests.js | 1 + test/integration/client/prepared-statement-tests.js | 1 + test/integration/client/promise-api-tests.js | 1 + test/integration/client/query-as-promise-tests.js | 1 + test/integration/client/query-column-names-tests.js | 1 + .../query-error-handling-prepared-statement-tests.js | 1 + test/integration/client/query-error-handling-tests.js | 1 + test/integration/client/quick-disconnect-tests.js | 1 + test/integration/client/result-metadata-tests.js | 1 + test/integration/client/results-as-array-tests.js | 1 + .../client/row-description-on-results-tests.js | 1 + test/integration/client/simple-query-tests.js | 3 ++- test/integration/client/ssl-tests.js | 1 + test/integration/client/test-helper.js | 3 ++- test/integration/client/timezone-tests.js | 1 + test/integration/client/transaction-tests.js | 1 + test/integration/client/type-coercion-tests.js | 1 + test/integration/client/type-parser-override-tests.js | 1 + .../connection-pool/connection-pool-size-tests.js | 1 + test/integration/connection-pool/error-tests.js | 1 + test/integration/connection-pool/idle-timeout-tests.js | 1 + .../integration/connection-pool/native-instance-tests.js | 1 + test/integration/connection-pool/test-helper.js | 1 + test/integration/connection-pool/yield-support-tests.js | 1 + test/integration/connection/bound-command-tests.js | 1 + test/integration/connection/copy-tests.js | 1 + test/integration/connection/notification-tests.js | 1 + test/integration/connection/query-tests.js | 1 + test/integration/connection/test-helper.js | 1 + test/integration/domain-tests.js | 1 + test/integration/gh-issues/130-tests.js | 1 + test/integration/gh-issues/131-tests.js | 1 + test/integration/gh-issues/199-tests.js | 1 + test/integration/gh-issues/507-tests.js | 1 + test/integration/gh-issues/600-tests.js | 1 + test/integration/gh-issues/675-tests.js | 1 + test/integration/gh-issues/699-tests.js | 1 + test/integration/gh-issues/787-tests.js | 1 + test/integration/gh-issues/882-tests.js | 1 + test/integration/gh-issues/981-tests.js | 1 + test/integration/test-helper.js | 1 + test/native/callback-api-tests.js | 1 + test/native/error-tests.js | 1 + test/native/evented-api-tests.js | 1 + test/native/missing-native.js | 1 + test/native/native-vs-js-error-tests.js | 1 + test/native/stress-tests.js | 1 + test/suite.js | 1 + test/test-buffers.js | 1 + test/test-helper.js | 7 ++++--- test/unit/client/cleartext-password-tests.js | 4 +++- test/unit/client/configuration-tests.js | 1 + test/unit/client/early-disconnect-tests.js | 1 + test/unit/client/escape-tests.js | 1 + test/unit/client/md5-password-tests.js | 5 +++-- test/unit/client/notification-tests.js | 1 + test/unit/client/prepared-statement-tests.js | 1 + test/unit/client/query-queue-tests.js | 1 + test/unit/client/result-metadata-tests.js | 1 + test/unit/client/simple-query-tests.js | 1 + .../client/stream-and-query-error-interaction-tests.js | 1 + test/unit/client/test-helper.js | 1 + test/unit/client/throw-in-type-parser-tests.js | 1 + test/unit/connection-parameters/creation-tests.js | 5 +++-- .../connection-parameters/environment-variable-tests.js | 1 + test/unit/connection/error-tests.js | 1 + test/unit/connection/inbound-parser-tests.js | 1 + test/unit/connection/outbound-sending-tests.js | 1 + test/unit/connection/startup-tests.js | 1 + test/unit/connection/test-helper.js | 1 + test/unit/test-helper.js | 9 ++++++--- test/unit/utils-tests.js | 7 ++++--- 104 files changed, 124 insertions(+), 17 deletions(-) diff --git a/lib/client.js b/lib/client.js index b11a0f394..dafa5a49a 100644 --- a/lib/client.js +++ b/lib/client.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index e6efa158e..a675e5856 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/connection.js b/lib/connection.js index 8e57ff46e..18aaf6f85 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/defaults.js b/lib/defaults.js index b94d33f3c..de8898eeb 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/index.js b/lib/index.js index d12ea45a9..ad0c7172a 100644 --- a/lib/index.js +++ b/lib/index.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/native/client.js b/lib/native/client.js index 9641d3993..9614cd14b 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/native/index.js b/lib/native/index.js index a35a27334..53f10c4aa 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -1 +1,2 @@ +"use strict"; module.exports = require('./client') diff --git a/lib/native/query.js b/lib/native/query.js index 4fb501f18..f9dacfa19 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/native/result.js b/lib/native/result.js index 519037316..62075b657 100644 --- a/lib/native/result.js +++ b/lib/native/result.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/query.js b/lib/query.js index 99b5ea8b5..e294a4f0b 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/result.js b/lib/result.js index 093a73c37..21b649a93 100644 --- a/lib/result.js +++ b/lib/result.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/type-overrides.js b/lib/type-overrides.js index 905260898..53be35ef9 100644 --- a/lib/type-overrides.js +++ b/lib/type-overrides.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/lib/utils.js b/lib/utils.js index 7ecf4b295..05c6f0b4c 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,3 +1,4 @@ +"use strict"; /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. diff --git a/script/create-test-tables.js b/script/create-test-tables.js index 6a569f2a2..4881daf87 100644 --- a/script/create-test-tables.js +++ b/script/create-test-tables.js @@ -1,3 +1,4 @@ +"use strict"; var args = require(__dirname + '/../test/cli'); var pg = require(__dirname + '/../lib'); diff --git a/script/dump-db-types.js b/script/dump-db-types.js index aa23825cb..cd2041535 100644 --- a/script/dump-db-types.js +++ b/script/dump-db-types.js @@ -1,3 +1,4 @@ +"use strict"; var pg = require(__dirname + '/../lib'); var args = require(__dirname + '/../test/cli'); diff --git a/script/list-db-types.js b/script/list-db-types.js index 748d32f28..b2db8403e 100644 --- a/script/list-db-types.js +++ b/script/list-db-types.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/../test/integration/test-helper"); var pg = helper.pg; pg.connect(helper.config, assert.success(function(client) { diff --git a/test/buffer-list.js b/test/buffer-list.js index 2b1ac73e1..3ebffe9da 100644 --- a/test/buffer-list.js +++ b/test/buffer-list.js @@ -1,4 +1,5 @@ -BufferList = function() { +"use strict"; +global.BufferList = function() { this.buffers = []; }; var p = BufferList.prototype; diff --git a/test/cli.js b/test/cli.js index bec0f3fb3..388b8acf7 100644 --- a/test/cli.js +++ b/test/cli.js @@ -1,3 +1,4 @@ +"use strict"; var ConnectionParameters = require(__dirname + '/../lib/connection-parameters'); var config = new ConnectionParameters(process.argv[2]); diff --git a/test/integration/client/api-tests.js b/test/integration/client/api-tests.js index 5f999482e..e51a363a3 100644 --- a/test/integration/client/api-tests.js +++ b/test/integration/client/api-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/../test-helper"); var pg = helper.pg; diff --git a/test/integration/client/appname-tests.js b/test/integration/client/appname-tests.js index 55673eff9..98c41776b 100644 --- a/test/integration/client/appname-tests.js +++ b/test/integration/client/appname-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var Client = helper.Client; diff --git a/test/integration/client/array-tests.js b/test/integration/client/array-tests.js index a26c76361..e56b5e634 100644 --- a/test/integration/client/array-tests.js +++ b/test/integration/client/array-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/test-helper"); var pg = helper.pg; diff --git a/test/integration/client/big-simple-query-tests.js b/test/integration/client/big-simple-query-tests.js index 0065772cf..7db183f41 100644 --- a/test/integration/client/big-simple-query-tests.js +++ b/test/integration/client/big-simple-query-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./test-helper"); var Query = helper.pg.Query diff --git a/test/integration/client/configuration-tests.js b/test/integration/client/configuration-tests.js index 8cde4cea9..8bd065e91 100644 --- a/test/integration/client/configuration-tests.js +++ b/test/integration/client/configuration-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var pg = helper.pg; diff --git a/test/integration/client/custom-types-tests.js b/test/integration/client/custom-types-tests.js index 9305dbbd1..db1433569 100644 --- a/test/integration/client/custom-types-tests.js +++ b/test/integration/client/custom-types-tests.js @@ -1,3 +1,4 @@ +"use strict"; const helper = require('./test-helper'); const Client = helper.pg.Client; const suite = new helper.Suite() diff --git a/test/integration/client/empty-query-tests.js b/test/integration/client/empty-query-tests.js index 8251088ab..443c37d67 100644 --- a/test/integration/client/empty-query-tests.js +++ b/test/integration/client/empty-query-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); const suite = new helper.Suite() diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 69d43085b..32ee58baf 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -1,4 +1,5 @@ "use strict"; +"use strict"; var helper = require('./test-helper'); var util = require('util'); diff --git a/test/integration/client/huge-numeric-tests.js b/test/integration/client/huge-numeric-tests.js index 9cd905371..a5bdbc8a0 100644 --- a/test/integration/client/huge-numeric-tests.js +++ b/test/integration/client/huge-numeric-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); const pool = new helper.pg.Pool() diff --git a/test/integration/client/json-type-parsing-tests.js b/test/integration/client/json-type-parsing-tests.js index b3ec40744..77c5469a7 100644 --- a/test/integration/client/json-type-parsing-tests.js +++ b/test/integration/client/json-type-parsing-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var assert = require('assert'); diff --git a/test/integration/client/network-partition-tests.js b/test/integration/client/network-partition-tests.js index 8e9d8af85..704f7fdfe 100644 --- a/test/integration/client/network-partition-tests.js +++ b/test/integration/client/network-partition-tests.js @@ -1,3 +1,4 @@ +"use strict"; var buffers = require('../../test-buffers') var helper = require('./test-helper') var suite = new helper.Suite() diff --git a/test/integration/client/no-data-tests.js b/test/integration/client/no-data-tests.js index 28a4999ab..a4ab36fb5 100644 --- a/test/integration/client/no-data-tests.js +++ b/test/integration/client/no-data-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); const suite = new helper.Suite() diff --git a/test/integration/client/no-row-result-tests.js b/test/integration/client/no-row-result-tests.js index cc91c647f..4ff289951 100644 --- a/test/integration/client/no-row-result-tests.js +++ b/test/integration/client/no-row-result-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./test-helper"); var pg = helper.pg; const suite = new helper.Suite(); diff --git a/test/integration/client/notice-tests.js b/test/integration/client/notice-tests.js index f226de8f9..9c682050a 100644 --- a/test/integration/client/notice-tests.js +++ b/test/integration/client/notice-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); const suite = new helper.Suite() diff --git a/test/integration/client/parse-int-8-tests.js b/test/integration/client/parse-int-8-tests.js index 937b41b72..920f5558f 100644 --- a/test/integration/client/parse-int-8-tests.js +++ b/test/integration/client/parse-int-8-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('../test-helper'); var pg = helper.pg; diff --git a/test/integration/client/prepared-statement-tests.js b/test/integration/client/prepared-statement-tests.js index 0d037b009..9b00f9d8c 100644 --- a/test/integration/client/prepared-statement-tests.js +++ b/test/integration/client/prepared-statement-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var Query = helper.pg.Query; diff --git a/test/integration/client/promise-api-tests.js b/test/integration/client/promise-api-tests.js index ee088f94d..45083a1bb 100644 --- a/test/integration/client/promise-api-tests.js +++ b/test/integration/client/promise-api-tests.js @@ -1,3 +1,4 @@ +"use strict"; 'use strict'; const helper = require('./test-helper') diff --git a/test/integration/client/query-as-promise-tests.js b/test/integration/client/query-as-promise-tests.js index 95bf73ce4..52487a7d4 100644 --- a/test/integration/client/query-as-promise-tests.js +++ b/test/integration/client/query-as-promise-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/../test-helper'); var pg = helper.pg; diff --git a/test/integration/client/query-column-names-tests.js b/test/integration/client/query-column-names-tests.js index d929b5088..a670bae3b 100644 --- a/test/integration/client/query-column-names-tests.js +++ b/test/integration/client/query-column-names-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/../test-helper'); var pg = helper.pg; diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index 7aa68f595..f16f96f66 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var Query = helper.pg.Query; var util = require('util'); diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js index d5ecd7bde..6c1b3b7cc 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var util = require('util'); var Query = helper.pg.Query; diff --git a/test/integration/client/quick-disconnect-tests.js b/test/integration/client/quick-disconnect-tests.js index a1b6bab61..76a825ac1 100644 --- a/test/integration/client/quick-disconnect-tests.js +++ b/test/integration/client/quick-disconnect-tests.js @@ -1,3 +1,4 @@ +"use strict"; //test for issue #320 // var helper = require('./test-helper'); diff --git a/test/integration/client/result-metadata-tests.js b/test/integration/client/result-metadata-tests.js index 85b7e18c5..bb7aeff74 100644 --- a/test/integration/client/result-metadata-tests.js +++ b/test/integration/client/result-metadata-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./test-helper"); var pg = helper.pg; diff --git a/test/integration/client/results-as-array-tests.js b/test/integration/client/results-as-array-tests.js index 1a1d8edfc..45398c05c 100644 --- a/test/integration/client/results-as-array-tests.js +++ b/test/integration/client/results-as-array-tests.js @@ -1,3 +1,4 @@ +"use strict"; var util = require('util'); var helper = require('./test-helper'); diff --git a/test/integration/client/row-description-on-results-tests.js b/test/integration/client/row-description-on-results-tests.js index 22c929653..3d146bd6a 100644 --- a/test/integration/client/row-description-on-results-tests.js +++ b/test/integration/client/row-description-on-results-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var Client = helper.Client; diff --git a/test/integration/client/simple-query-tests.js b/test/integration/client/simple-query-tests.js index 9453f159d..6ae957dc3 100644 --- a/test/integration/client/simple-query-tests.js +++ b/test/integration/client/simple-query-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./test-helper"); var Query = helper.pg.Query; @@ -18,7 +19,7 @@ test("simple query interface", function() { query.once('row', function(row) { test('Can iterate through columns', function () { var columnCount = 0; - for (column in row) { + for (var column in row) { columnCount++; } if ('length' in row) { diff --git a/test/integration/client/ssl-tests.js b/test/integration/client/ssl-tests.js index 0458d6b0a..7523dfd36 100644 --- a/test/integration/client/ssl-tests.js +++ b/test/integration/client/ssl-tests.js @@ -1,3 +1,4 @@ +"use strict"; var pg = require(__dirname + '/../../../lib'); var config = require(__dirname + '/test-helper').config; test('can connect with ssl', function() { diff --git a/test/integration/client/test-helper.js b/test/integration/client/test-helper.js index 24cddf615..027477a1f 100644 --- a/test/integration/client/test-helper.js +++ b/test/integration/client/test-helper.js @@ -1,3 +1,4 @@ -var helper = require(__dirname+'/../test-helper'); +"use strict"; +var helper = require('./../test-helper'); module.exports = helper; diff --git a/test/integration/client/timezone-tests.js b/test/integration/client/timezone-tests.js index 298734319..c1baa7982 100644 --- a/test/integration/client/timezone-tests.js +++ b/test/integration/client/timezone-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./../test-helper'); var exec = require('child_process').exec; diff --git a/test/integration/client/transaction-tests.js b/test/integration/client/transaction-tests.js index 389a70d0c..c9af7eabb 100644 --- a/test/integration/client/transaction-tests.js +++ b/test/integration/client/transaction-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); const suite = new helper.Suite() const pg = helper.pg diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index dc50732e8..080dd9ada 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); var pg = helper.pg; var sink; diff --git a/test/integration/client/type-parser-override-tests.js b/test/integration/client/type-parser-override-tests.js index 3fd52dd28..f12e40054 100644 --- a/test/integration/client/type-parser-override-tests.js +++ b/test/integration/client/type-parser-override-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); function testTypeParser(client, expectedResult, done) { diff --git a/test/integration/connection-pool/connection-pool-size-tests.js b/test/integration/connection-pool/connection-pool-size-tests.js index 998bff7e4..51051c242 100644 --- a/test/integration/connection-pool/connection-pool-size-tests.js +++ b/test/integration/connection-pool/connection-pool-size-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./test-helper") helper.testPoolSize(1); diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index 21f615319..e01d598f8 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./test-helper"); const pg = helper.pg diff --git a/test/integration/connection-pool/idle-timeout-tests.js b/test/integration/connection-pool/idle-timeout-tests.js index e8090a09f..0531ae80a 100644 --- a/test/integration/connection-pool/idle-timeout-tests.js +++ b/test/integration/connection-pool/idle-timeout-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); diff --git a/test/integration/connection-pool/native-instance-tests.js b/test/integration/connection-pool/native-instance-tests.js index 314920c4d..caaa2b67a 100644 --- a/test/integration/connection-pool/native-instance-tests.js +++ b/test/integration/connection-pool/native-instance-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./../test-helper") var pg = helper.pg var native = helper.args.native diff --git a/test/integration/connection-pool/test-helper.js b/test/integration/connection-pool/test-helper.js index b66bcba51..85ecd899d 100644 --- a/test/integration/connection-pool/test-helper.js +++ b/test/integration/connection-pool/test-helper.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./../test-helper"); const suite = new helper.Suite() diff --git a/test/integration/connection-pool/yield-support-tests.js b/test/integration/connection-pool/yield-support-tests.js index c56d9851b..149266996 100644 --- a/test/integration/connection-pool/yield-support-tests.js +++ b/test/integration/connection-pool/yield-support-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper') var co = require('co') diff --git a/test/integration/connection/bound-command-tests.js b/test/integration/connection/bound-command-tests.js index 9d40e5bce..40da4b5a2 100644 --- a/test/integration/connection/bound-command-tests.js +++ b/test/integration/connection/bound-command-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); //http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY diff --git a/test/integration/connection/copy-tests.js b/test/integration/connection/copy-tests.js index ee4a71c59..2dfbc6070 100644 --- a/test/integration/connection/copy-tests.js +++ b/test/integration/connection/copy-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname+"/test-helper"); var assert = require('assert'); diff --git a/test/integration/connection/notification-tests.js b/test/integration/connection/notification-tests.js index e0cf13826..dd11904d6 100644 --- a/test/integration/connection/notification-tests.js +++ b/test/integration/connection/notification-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); //http://www.postgresql.org/docs/8.3/static/libpq-notify.html test('recieves notification from same connection with no payload', function() { diff --git a/test/integration/connection/query-tests.js b/test/integration/connection/query-tests.js index f308546d7..6216c55aa 100644 --- a/test/integration/connection/query-tests.js +++ b/test/integration/connection/query-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname+"/test-helper"); var assert = require('assert'); diff --git a/test/integration/connection/test-helper.js b/test/integration/connection/test-helper.js index 0bc650466..d053e39ab 100644 --- a/test/integration/connection/test-helper.js +++ b/test/integration/connection/test-helper.js @@ -1,3 +1,4 @@ +"use strict"; var net = require('net'); var helper = require(__dirname+'/../test-helper'); var Connection = require(__dirname + '/../../../lib/connection'); diff --git a/test/integration/domain-tests.js b/test/integration/domain-tests.js index ce87335e2..5d4db53c2 100644 --- a/test/integration/domain-tests.js +++ b/test/integration/domain-tests.js @@ -1,3 +1,4 @@ +"use strict"; var async = require('async') var helper = require('./test-helper') diff --git a/test/integration/gh-issues/130-tests.js b/test/integration/gh-issues/130-tests.js index 0fed550bb..bc1f3b742 100644 --- a/test/integration/gh-issues/130-tests.js +++ b/test/integration/gh-issues/130-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/../test-helper'); var exec = require('child_process').exec; diff --git a/test/integration/gh-issues/131-tests.js b/test/integration/gh-issues/131-tests.js index 41e71b5c3..164f94e90 100644 --- a/test/integration/gh-issues/131-tests.js +++ b/test/integration/gh-issues/131-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('../test-helper'); var pg = helper.pg; diff --git a/test/integration/gh-issues/199-tests.js b/test/integration/gh-issues/199-tests.js index b60477fdc..60637fb19 100644 --- a/test/integration/gh-issues/199-tests.js +++ b/test/integration/gh-issues/199-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('../test-helper'); var client = helper.client(); diff --git a/test/integration/gh-issues/507-tests.js b/test/integration/gh-issues/507-tests.js index 57e0f7692..62bec47ce 100644 --- a/test/integration/gh-issues/507-tests.js +++ b/test/integration/gh-issues/507-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/../test-helper"); var pg = helper.pg; diff --git a/test/integration/gh-issues/600-tests.js b/test/integration/gh-issues/600-tests.js index b64f19fae..263e48d0c 100644 --- a/test/integration/gh-issues/600-tests.js +++ b/test/integration/gh-issues/600-tests.js @@ -1,3 +1,4 @@ +"use strict"; var async = require('async'); var helper = require('../test-helper'); const suite = new helper.Suite() diff --git a/test/integration/gh-issues/675-tests.js b/test/integration/gh-issues/675-tests.js index e1bc0a551..b162b9df8 100644 --- a/test/integration/gh-issues/675-tests.js +++ b/test/integration/gh-issues/675-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('../test-helper'); var assert = require('assert'); diff --git a/test/integration/gh-issues/699-tests.js b/test/integration/gh-issues/699-tests.js index 6f47ffca5..d4c9eab75 100644 --- a/test/integration/gh-issues/699-tests.js +++ b/test/integration/gh-issues/699-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('../test-helper'); var assert = require('assert'); var copyFrom = require('pg-copy-streams').from; diff --git a/test/integration/gh-issues/787-tests.js b/test/integration/gh-issues/787-tests.js index 773a033da..83ea85f3c 100644 --- a/test/integration/gh-issues/787-tests.js +++ b/test/integration/gh-issues/787-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('../test-helper'); const pool = new helper.pg.Pool() diff --git a/test/integration/gh-issues/882-tests.js b/test/integration/gh-issues/882-tests.js index 1818b0c6b..154f9e96a 100644 --- a/test/integration/gh-issues/882-tests.js +++ b/test/integration/gh-issues/882-tests.js @@ -1,3 +1,4 @@ +"use strict"; //client should not hang on an empty query var helper = require('../test-helper'); var client = helper.client(); diff --git a/test/integration/gh-issues/981-tests.js b/test/integration/gh-issues/981-tests.js index 4ba2f5ad4..6348d05a9 100644 --- a/test/integration/gh-issues/981-tests.js +++ b/test/integration/gh-issues/981-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./../test-helper'); //native bindings are only installed for native tests diff --git a/test/integration/test-helper.js b/test/integration/test-helper.js index ceed87d56..9dba636db 100644 --- a/test/integration/test-helper.js +++ b/test/integration/test-helper.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/../test-helper'); if(helper.args.native) { diff --git a/test/native/callback-api-tests.js b/test/native/callback-api-tests.js index 6193ba743..fa57dbdea 100644 --- a/test/native/callback-api-tests.js +++ b/test/native/callback-api-tests.js @@ -1,3 +1,4 @@ +"use strict"; var domain = require('domain'); var helper = require("./../test-helper"); var Client = require("./../../lib/native"); diff --git a/test/native/error-tests.js b/test/native/error-tests.js index 2edf34215..a6f876449 100644 --- a/test/native/error-tests.js +++ b/test/native/error-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/../test-helper"); var Client = require(__dirname + "/../../lib/native"); diff --git a/test/native/evented-api-tests.js b/test/native/evented-api-tests.js index 122dc47e0..8a7c19b42 100644 --- a/test/native/evented-api-tests.js +++ b/test/native/evented-api-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("../test-helper"); var Client = require("../../lib/native"); var Query = Client.Query; diff --git a/test/native/missing-native.js b/test/native/missing-native.js index 775c6186e..d8474287f 100644 --- a/test/native/missing-native.js +++ b/test/native/missing-native.js @@ -1,3 +1,4 @@ +"use strict"; //this test assumes it has been run from the Makefile //and that node_modules/pg-native has been deleted diff --git a/test/native/native-vs-js-error-tests.js b/test/native/native-vs-js-error-tests.js index ee192ddc3..59c6bb94d 100644 --- a/test/native/native-vs-js-error-tests.js +++ b/test/native/native-vs-js-error-tests.js @@ -1,3 +1,4 @@ +"use strict"; var assert = require('assert') var Client = require('../../lib/client'); var NativeClient = require('../../lib/native'); diff --git a/test/native/stress-tests.js b/test/native/stress-tests.js index 08fab97ed..32477cb8c 100644 --- a/test/native/stress-tests.js +++ b/test/native/stress-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/../test-helper"); var Client = require(__dirname + "/../../lib/native"); var Query = Client.Query; diff --git a/test/suite.js b/test/suite.js index 22d1a9cc7..da6492fb6 100644 --- a/test/suite.js +++ b/test/suite.js @@ -1,3 +1,4 @@ +"use strict"; 'use strict'; const async = require('async') diff --git a/test/test-buffers.js b/test/test-buffers.js index b16a7ab62..0351559a9 100644 --- a/test/test-buffers.js +++ b/test/test-buffers.js @@ -1,3 +1,4 @@ +"use strict"; require(__dirname+'/test-helper'); //http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html diff --git a/test/test-helper.js b/test/test-helper.js index 802d19c06..3bfc5177b 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -1,5 +1,6 @@ +"use strict"; //make assert a global... -assert = require('assert'); +global.assert = require('assert'); var EventEmitter = require('events').EventEmitter; var sys = require('util'); @@ -9,7 +10,7 @@ const args = require('./cli'); var Connection = require('./../lib/connection'); -Client = require('./../lib').Client; +global.Client = require('./../lib').Client; process.on('uncaughtException', function(d) { if ('stack' in d && 'message' in d) { @@ -172,7 +173,7 @@ const getMode = () => { return '' } -test = function(name, action) { +global.test = function(name, action) { test.testCount ++; test[name] = action; var result = test[name](); diff --git a/test/unit/client/cleartext-password-tests.js b/test/unit/client/cleartext-password-tests.js index e880908be..67e7c67b8 100644 --- a/test/unit/client/cleartext-password-tests.js +++ b/test/unit/client/cleartext-password-tests.js @@ -1,4 +1,6 @@ -require(__dirname+'/test-helper'); +"use strict"; + +const createClient = require('./test-helper').createClient; /* * TODO: Add _some_ comments to explain what it is we're testing, and how the diff --git a/test/unit/client/configuration-tests.js b/test/unit/client/configuration-tests.js index 5548e5fb1..bf007ee74 100644 --- a/test/unit/client/configuration-tests.js +++ b/test/unit/client/configuration-tests.js @@ -1,3 +1,4 @@ +"use strict"; require(__dirname+'/test-helper'); var pguser = process.env['PGUSER'] || process.env.USER; diff --git a/test/unit/client/early-disconnect-tests.js b/test/unit/client/early-disconnect-tests.js index a4c38be95..f3884c7b2 100644 --- a/test/unit/client/early-disconnect-tests.js +++ b/test/unit/client/early-disconnect-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); var net = require('net'); var pg = require('../../..//lib/index.js'); diff --git a/test/unit/client/escape-tests.js b/test/unit/client/escape-tests.js index e3f638ac1..7ea640fcb 100644 --- a/test/unit/client/escape-tests.js +++ b/test/unit/client/escape-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); function createClient(callback) { diff --git a/test/unit/client/md5-password-tests.js b/test/unit/client/md5-password-tests.js index 78c826021..63a0398d1 100644 --- a/test/unit/client/md5-password-tests.js +++ b/test/unit/client/md5-password-tests.js @@ -1,8 +1,9 @@ -require('./test-helper'); +"use strict"; +var helper = require('./test-helper'); var utils = require('../../../lib/utils') test('md5 authentication', function() { - var client = createClient(); + var client = helper.createClient(); client.password = "!"; var salt = Buffer.from([1, 2, 3, 4]); client.connection.emit('authenticationMD5Password', {salt: salt}); diff --git a/test/unit/client/notification-tests.js b/test/unit/client/notification-tests.js index e6b0dff13..dab8f6087 100644 --- a/test/unit/client/notification-tests.js +++ b/test/unit/client/notification-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/test-helper"); test('passes connection notification', function() { diff --git a/test/unit/client/prepared-statement-tests.js b/test/unit/client/prepared-statement-tests.js index 460cbf95d..50327bf44 100644 --- a/test/unit/client/prepared-statement-tests.js +++ b/test/unit/client/prepared-statement-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('./test-helper'); var Query = require('../../../lib/query') diff --git a/test/unit/client/query-queue-tests.js b/test/unit/client/query-queue-tests.js index 62b38bd58..2aa3b6b0a 100644 --- a/test/unit/client/query-queue-tests.js +++ b/test/unit/client/query-queue-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); var Connection = require(__dirname + '/../../../lib/connection'); diff --git a/test/unit/client/result-metadata-tests.js b/test/unit/client/result-metadata-tests.js index 5f349b57f..c3f26620b 100644 --- a/test/unit/client/result-metadata-tests.js +++ b/test/unit/client/result-metadata-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/test-helper") var testForTag = function(tagText, callback) { diff --git a/test/unit/client/simple-query-tests.js b/test/unit/client/simple-query-tests.js index df71faed5..29ab00123 100644 --- a/test/unit/client/simple-query-tests.js +++ b/test/unit/client/simple-query-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + "/test-helper"); var Query = require('../../../lib/query') diff --git a/test/unit/client/stream-and-query-error-interaction-tests.js b/test/unit/client/stream-and-query-error-interaction-tests.js index a60e1f734..0815fccd1 100644 --- a/test/unit/client/stream-and-query-error-interaction-tests.js +++ b/test/unit/client/stream-and-query-error-interaction-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); var Connection = require(__dirname + '/../../../lib/connection'); var Client = require(__dirname + '/../../../lib/client'); diff --git a/test/unit/client/test-helper.js b/test/unit/client/test-helper.js index 7c0bb31b4..fe1765d68 100644 --- a/test/unit/client/test-helper.js +++ b/test/unit/client/test-helper.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require('../test-helper'); var Connection = require('../../../lib/connection'); diff --git a/test/unit/client/throw-in-type-parser-tests.js b/test/unit/client/throw-in-type-parser-tests.js index 2f1845438..06580eb0e 100644 --- a/test/unit/client/throw-in-type-parser-tests.js +++ b/test/unit/client/throw-in-type-parser-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require("./test-helper"); var Query = require("../../../lib/query"); var types = require("pg-types"); diff --git a/test/unit/connection-parameters/creation-tests.js b/test/unit/connection-parameters/creation-tests.js index 85c2bd037..36e17a934 100644 --- a/test/unit/connection-parameters/creation-tests.js +++ b/test/unit/connection-parameters/creation-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/../test-helper'); var assert = require('assert'); var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters'); @@ -67,12 +68,12 @@ test('ConnectionParameters initializing from config', function() { }); test('escape spaces if present', function() { - subject = new ConnectionParameters('postgres://localhost/post gres'); + var subject = new ConnectionParameters('postgres://localhost/post gres'); assert.equal(subject.database, 'post gres'); }); test('do not double escape spaces', function() { - subject = new ConnectionParameters('postgres://localhost/post%20gres'); + var subject = new ConnectionParameters('postgres://localhost/post%20gres'); assert.equal(subject.database, 'post gres'); }); diff --git a/test/unit/connection-parameters/environment-variable-tests.js b/test/unit/connection-parameters/environment-variable-tests.js index 5481915fd..2f41fecdc 100644 --- a/test/unit/connection-parameters/environment-variable-tests.js +++ b/test/unit/connection-parameters/environment-variable-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/../test-helper'); var assert = require('assert'); var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters'); diff --git a/test/unit/connection/error-tests.js b/test/unit/connection/error-tests.js index 98eb20a8a..20952a693 100644 --- a/test/unit/connection/error-tests.js +++ b/test/unit/connection/error-tests.js @@ -1,3 +1,4 @@ +"use strict"; var helper = require(__dirname + '/test-helper'); var Connection = require(__dirname + '/../../../lib/connection'); test("connection emits stream errors", function() { diff --git a/test/unit/connection/inbound-parser-tests.js b/test/unit/connection/inbound-parser-tests.js index 2b822e440..86266b22e 100644 --- a/test/unit/connection/inbound-parser-tests.js +++ b/test/unit/connection/inbound-parser-tests.js @@ -1,3 +1,4 @@ +"use strict"; require(__dirname+'/test-helper'); var Connection = require(__dirname + '/../../../lib/connection'); var buffers = require(__dirname + '/../../test-buffers'); diff --git a/test/unit/connection/outbound-sending-tests.js b/test/unit/connection/outbound-sending-tests.js index 353c073bf..69642957d 100644 --- a/test/unit/connection/outbound-sending-tests.js +++ b/test/unit/connection/outbound-sending-tests.js @@ -1,3 +1,4 @@ +"use strict"; require(__dirname + "/test-helper"); var Connection = require(__dirname + '/../../../lib/connection'); var stream = new MemoryStream(); diff --git a/test/unit/connection/startup-tests.js b/test/unit/connection/startup-tests.js index 622f47374..ee20d679a 100644 --- a/test/unit/connection/startup-tests.js +++ b/test/unit/connection/startup-tests.js @@ -1,3 +1,4 @@ +"use strict"; require(__dirname+'/test-helper'); var Connection = require(__dirname + '/../../../lib/connection'); test('connection can take existing stream', function() { diff --git a/test/unit/connection/test-helper.js b/test/unit/connection/test-helper.js index 88cced6d8..03d95a699 100644 --- a/test/unit/connection/test-helper.js +++ b/test/unit/connection/test-helper.js @@ -1 +1,2 @@ +"use strict"; require(__dirname+'/../test-helper') diff --git a/test/unit/test-helper.js b/test/unit/test-helper.js index ad6485be8..1dcac733e 100644 --- a/test/unit/test-helper.js +++ b/test/unit/test-helper.js @@ -1,9 +1,10 @@ +"use strict"; var EventEmitter = require('events').EventEmitter; var helper = require('../test-helper'); var Connection = require('../../lib/connection'); -MemoryStream = function() { +global.MemoryStream = function() { EventEmitter.call(this); this.packets = []; }; @@ -21,7 +22,7 @@ p.setKeepAlive = function(){}; p.writable = true; -createClient = function() { +const createClient = function() { var stream = new MemoryStream(); stream.readyState = "open"; var client = new Client({ @@ -31,4 +32,6 @@ createClient = function() { return client; }; -module.exports = helper; +module.exports = Object.assign({}, helper, { + createClient: createClient, +}); diff --git a/test/unit/utils-tests.js b/test/unit/utils-tests.js index 82b11715a..893cf5b5d 100644 --- a/test/unit/utils-tests.js +++ b/test/unit/utils-tests.js @@ -1,6 +1,7 @@ -var helper = require(__dirname + '/test-helper'); -var utils = require(__dirname + "/../../lib/utils"); -var defaults = require(__dirname + "/../../lib").defaults; +"use strict"; +var helper = require('./test-helper'); +var utils = require("./../../lib/utils"); +var defaults = require("./../../lib").defaults; test('ensure types is exported on root object', function() { From 729d4e9c4737b8c0cfe75719e24f7ebb879f828f Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 15:41:30 -0500 Subject: [PATCH 0240/1037] Tweak travis.yml --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 46e3a3424..3abcf8a98 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,6 @@ matrix: - node_js: "lts/boron" addons: postgresql: "9.6" - dist: precise - node_js: "8" addons: postgresql: "9.6" From bd87cddc72bbf49e7a83921644df0f2fede14341 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 16:26:13 -0500 Subject: [PATCH 0241/1037] Fix connection / disconnection issues --- lib/client.js | 70 +++++++++---------- .../client/error-handling-tests.js | 19 ++++- .../connection-pool/error-tests.js | 5 ++ test/integration/test-helper.js | 4 +- test/unit/client/early-disconnect-tests.js | 4 +- 5 files changed, 62 insertions(+), 40 deletions(-) diff --git a/lib/client.js b/lib/client.js index dafa5a49a..ae5a176df 100644 --- a/lib/client.js +++ b/lib/client.js @@ -109,12 +109,35 @@ Client.prototype.connect = function(callback) { self.secretKey = msg.secretKey; }); + const connectingErrorHandler = (err) => { + if (this._connectionError) { + return; + } + this._connectionError = true + if (callback) { + return callback(err) + } + this.emit('error', err) + } + + const connectedErrorHandler = (err) => { + if(this.activeQuery) { + var activeQuery = self.activeQuery; + this.activeQuery = null; + return activeQuery.handleError(err, con); + } + this.emit('error', err) + } + + con.on('error', connectingErrorHandler) + //hook up query handling events to connection //after the connection initially becomes ready for queries con.once('readyForQuery', function() { self._connecting = false; self._attachListeners(con); - + con.removeListener('error', connectingErrorHandler); + con.on('error', connectedErrorHandler) //process possible callback argument to Client#connect if (callback) { @@ -136,37 +159,7 @@ Client.prototype.connect = function(callback) { self._pulseQueryQueue(); }); - con.on('error', function(error) { - if(this.activeQuery) { - var activeQuery = self.activeQuery; - this.activeQuery = null; - return activeQuery.handleError(error, con); - } - - if (this._connecting) { - // set a flag indicating we've seen an error during connection - // the backend will terminate the connection and we don't want - // to throw a second error when the connection is terminated - this._connectionError = true; - } - - if(!callback) { - return this.emit('error', error); - } - - con.end(); // make sure ECONNRESET errors don't cause error events - callback(error); - callback = null; - }.bind(this)); - - con.once('end', function() { - if (callback) { - // haven't received a connection message yet! - var err = new Error('Connection terminated'); - callback(err); - callback = null; - return; - } + con.once('end', () => { if(this.activeQuery) { var disconnectError = new Error('Connection terminated'); this.activeQuery.handleError(disconnectError, con); @@ -177,12 +170,19 @@ Client.prototype.connect = function(callback) { // on this client then we have an unexpected disconnection // treat this as an error unless we've already emitted an error // during connection. - if (!this._connectionError) { - this.emit('error', new Error('Connection terminated unexpectedly')); + const error = new Error('Connection terminated unexpectedly') + if (this._connecting && !this._connectionError) { + if (callback) { + callback(error) + } else { + this.emit('error', error) + } + } else if (!this._connectionError) { + this.emit('error', error); } } this.emit('end'); - }.bind(this)); + }); con.on('notice', function(msg) { diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 32ee58baf..89c181a5c 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -1,10 +1,10 @@ "use strict"; -"use strict"; var helper = require('./test-helper'); var util = require('util'); var pg = helper.pg +const Client = pg.Client var createErorrClient = function() { var client = helper.client(); @@ -84,6 +84,7 @@ suite.test('non-query error with callback', function(done) { user:'asldkfjsadlfkj' }); client.connect(assert.calls(function(error, client) { + console.log('error!', error.stack) assert(error instanceof Error) done() })); @@ -142,3 +143,19 @@ suite.test('within a simple query', (done) => { done(); }); }); + +suite.test('connected, idle client error', (done) => { + const client = new Client() + client.connect((err) => { + if (err) { + throw new Error('Should not receive error callback after connection') + } + setImmediate(() => { + (client.connection || client.native).emit('error', new Error('expected')) + }) + }) + client.on('error', (err) => { + assert.equal(err.message, 'expected') + client.end(done) + }) +}) diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index e01d598f8..4098ba9d8 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -8,6 +8,11 @@ pg.defaults.poolSize = 2; const pool = new pg.Pool() const suite = new helper.Suite() +suite.test('connecting to invalid port', (cb) => { + const pool = new pg.Pool({ port: 13801 }) + pool.connect().catch(e => cb()) +}) + suite.test('errors emitted on pool', (cb) => { //get first client pool.connect(assert.success(function (client, done) { diff --git a/test/integration/test-helper.js b/test/integration/test-helper.js index 9dba636db..56ea43ed5 100644 --- a/test/integration/test-helper.js +++ b/test/integration/test-helper.js @@ -1,8 +1,8 @@ "use strict"; -var helper = require(__dirname + '/../test-helper'); +var helper = require('./../test-helper'); if(helper.args.native) { - Client = require(__dirname + '/../../lib/native'); + Client = require('./../../lib/native'); helper.Client = Client; helper.pg = helper.pg.native; } diff --git a/test/unit/client/early-disconnect-tests.js b/test/unit/client/early-disconnect-tests.js index f3884c7b2..c8d7fbc59 100644 --- a/test/unit/client/early-disconnect-tests.js +++ b/test/unit/client/early-disconnect-tests.js @@ -1,7 +1,7 @@ "use strict"; -var helper = require(__dirname + '/test-helper'); +var helper = require('./test-helper'); var net = require('net'); -var pg = require('../../..//lib/index.js'); +var pg = require('../../../lib/index.js'); /* console.log() messages show up in `make test` output. TODO: fix it. */ var server = net.createServer(function(c) { From da71ea58f67ef088dd80e4b22984ada8efea56b2 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 17:06:46 -0500 Subject: [PATCH 0242/1037] Add query validity check Passing nothing for both the query.text and query.name is unsupported but previously crashed with an impossible to catch error. --- lib/query.js | 6 ++++++ test/integration/client/error-handling-tests.js | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/query.js b/lib/query.js index e294a4f0b..a8e76547d 100644 --- a/lib/query.js +++ b/lib/query.js @@ -127,6 +127,12 @@ Query.prototype.handleError = function(err, connection) { }; Query.prototype.submit = function(connection) { + if (typeof this.text != 'string' && typeof this.name != 'string') { + const err = new Error('A query must have either text or a name. Supplying neither is unsupported.') + connection.emit('error', err) + connection.emit('readyForQuery') + return + } if(this.requiresPreparation()) { this.prepare(connection); } else { diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 89c181a5c..c929dd7b8 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -159,3 +159,16 @@ suite.test('connected, idle client error', (done) => { client.end(done) }) }) + +suite.test('cannot pass non-string values to query as text', (done) => { + const client = new Client() + client.connect() + client.query({ text: { } }, (err) => { + assert(err) + client.query({ }, (err) => { + client.on('drain', () => { + client.end(done) + }) + }) + }) +}) From a83655a396309521aed72cb02ecce87409034e83 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 17:23:58 -0500 Subject: [PATCH 0243/1037] Remove console.log statement --- test/integration/client/error-handling-tests.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index c929dd7b8..e18cc9009 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -84,7 +84,6 @@ suite.test('non-query error with callback', function(done) { user:'asldkfjsadlfkj' }); client.connect(assert.calls(function(error, client) { - console.log('error!', error.stack) assert(error instanceof Error) done() })); From b5b49eb895727e01290e90d08292c0d61ab86322 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 18 Jun 2017 11:48:22 -0500 Subject: [PATCH 0244/1037] Add deprecations This adds deprecations in preparation for `pg@7.0` - deprecate using event emitters on automatically created results from client.query. - deprecate query.promise() - it should never have been a public method and it's not documented. I need to do better about using _ prefix on private methods in the future. - deprecate singleton pool on the `pg` object. `pg.connect`, `pg.end`, and `pg.cancel`. --- lib/client.js | 5 ++++- lib/index.js | 12 ++++++------ lib/native/index.js | 31 +++++++++++++++++++++++++++++++ lib/native/query.js | 32 ++++++++++++++++++++++---------- lib/query.js | 20 +++++++++++++++----- lib/utils.js | 19 ++++++++++++++++++- test/test-helper.js | 2 ++ 7 files changed, 98 insertions(+), 23 deletions(-) diff --git a/lib/client.js b/lib/client.js index 78d8bd7b9..bbda1ddf5 100644 --- a/lib/client.js +++ b/lib/client.js @@ -13,6 +13,7 @@ var pgPass = require('pgpass'); var TypeOverrides = require('./type-overrides'); var ConnectionParameters = require('./connection-parameters'); +var utils = require('./utils'); var Query = require('./query'); var defaults = require('./defaults'); var Connection = require('./connection'); @@ -348,10 +349,12 @@ Client.prototype.copyTo = function (text) { throw new Error("For PostgreSQL COPY TO/COPY FROM support npm install pg-copy-streams"); }; +var DeprecatedEmitterQuery = utils.deprecateEventEmitter(Query); + Client.prototype.query = function(config, values, callback) { //can take in strings, config object or query object var query = (typeof config.submit == 'function') ? config : - new Query(config, values, callback); + new DeprecatedEmitterQuery(config, values, callback); if(this.binary && !query.binary) { query.binary = true; } diff --git a/lib/index.js b/lib/index.js index a2c2792f4..17abb5bc8 100644 --- a/lib/index.js +++ b/lib/index.js @@ -27,7 +27,7 @@ var PG = function(clientConstructor) { util.inherits(PG, EventEmitter); -PG.prototype.end = function() { +PG.prototype.end = util.deprecate(function() { var self = this; var keys = Object.keys(this._pools); var count = keys.length; @@ -47,9 +47,9 @@ PG.prototype.end = function() { }); }); } -}; +}, 'PG.end is deprecated - please see the upgrade guide at https://node-postgres.com/guides/upgrading'); -PG.prototype.connect = function(config, callback) { +PG.prototype.connect = util.deprecate(function(config, callback) { if(typeof config == "function") { callback = config; config = null; @@ -75,10 +75,10 @@ PG.prototype.connect = function(config, callback) { }.bind(this)); } return pool.connect(callback); -}; +}, 'PG.connect is deprecated - please see the upgrade guide at https://node-postgres.com/guides/upgrading'); // cancel the query running on the given client -PG.prototype.cancel = function(config, client, query) { +PG.prototype.cancel = util.deprecate(function(config, client, query) { if(client.native) { return client.cancel(query); } @@ -89,7 +89,7 @@ PG.prototype.cancel = function(config, client, query) { } var cancellingClient = new this.Client(c); cancellingClient.cancel(client, query); -}; +}, 'PG.cancel is deprecated - use client.cancel instead'); if(typeof process.env.NODE_PG_FORCE_NATIVE != 'undefined') { module.exports = new PG(require('./native')); diff --git a/lib/native/index.js b/lib/native/index.js index 1e192e8bf..99c029fbc 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -46,6 +46,8 @@ var Client = module.exports = function(config) { this.namedQueries = {}; }; +Client.Query = NativeQuery; + util.inherits(Client, EventEmitter); //connect to the backend @@ -139,6 +141,35 @@ Client.prototype.query = function(config, values, callback) { return query; }; +var DeprecatedQuery = require('../utils').deprecateEventEmitter(NativeQuery); + +//send a query to the server +//this method is highly overloaded to take +//1) string query, optional array of parameters, optional function callback +//2) object query with { +// string query +// optional array values, +// optional function callback instead of as a separate parameter +// optional string name to name & cache the query plan +// optional string rowMode = 'array' for an array of results +// } +Client.prototype.query = function(config, values, callback) { + if (typeof config.submit == 'function') { + // accept query(new Query(...), (err, res) => { }) style + if (typeof values == 'function') { + config.callback = values; + } + this._queryQueue.push(config); + this._pulseQueryQueue(); + return config; + } + + var query = new DeprecatedQuery(config, values, callback); + this._queryQueue.push(query); + this._pulseQueryQueue(); + return query; +}; + //disconnect from the backend server Client.prototype.end = function(cb) { var self = this; diff --git a/lib/native/query.js b/lib/native/query.js index fcb1eff4f..3d6b3c032 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -11,15 +11,15 @@ var util = require('util'); var utils = require('../utils'); var NativeResult = require('./result'); -var NativeQuery = module.exports = function(native) { +var NativeQuery = module.exports = function(config, values, callback) { EventEmitter.call(this); - this.native = native; - this.text = null; - this.values = null; - this.name = null; - this.callback = null; + config = utils.normalizeQueryConfig(config, values, callback); + this.text = config.text; + this.values = config.values; + this.name = config.name; + this.callback = config.callback; this.state = 'new'; - this._arrayMode = false; + this._arrayMode = config.rowMode == 'array'; //if the 'row' event is listened for //then emit them as they come in @@ -34,6 +34,13 @@ var NativeQuery = module.exports = function(native) { util.inherits(NativeQuery, EventEmitter); +// TODO - remove in 7.0 +// this maintains backwards compat so someone could instantiate a query +// manually: `new Query().then()`... +NativeQuery._on = NativeQuery.on; +NativeQuery._once = NativeQuery.once; + + NativeQuery.prototype.then = function(onSuccess, onFailure) { return this.promise().then(onSuccess, onFailure); }; @@ -42,15 +49,19 @@ NativeQuery.prototype.catch = function(callback) { return this.promise().catch(callback); }; -NativeQuery.prototype.promise = function() { +NativeQuery.prototype._getPromise = function() { if (this._promise) return this._promise; this._promise = new Promise(function(resolve, reject) { - this.once('end', resolve); - this.once('error', reject); + this._once('end', resolve); + this._once('error', reject); }.bind(this)); return this._promise; }; +NativeQuery.prototype.promise = util.deprecate(function() { + return this._getPromise(); +}, 'Query.promise() is deprecated - see the upgrade guide at https://node-postgres.com/guides/upgrading'); + NativeQuery.prototype.handleError = function(err) { var self = this; //copy pq error fields into the error object @@ -71,6 +82,7 @@ NativeQuery.prototype.handleError = function(err) { NativeQuery.prototype.submit = function(client) { this.state = 'running'; var self = this; + self.native = client.native; client.native.arrayMode = this._arrayMode; var after = function(err, rows) { diff --git a/lib/query.js b/lib/query.js index 4d49dafd3..652db38e7 100644 --- a/lib/query.js +++ b/lib/query.js @@ -40,23 +40,33 @@ var Query = function(config, values, callback) { util.inherits(Query, EventEmitter); +// TODO - remove in 7.0 +// this maintains backwards compat so someone could instantiate a query +// manually: `new Query().then()`... +Query._on = Query.on; +Query._once = Query.once; + Query.prototype.then = function(onSuccess, onFailure) { - return this.promise().then(onSuccess, onFailure); + return this._getPromise().then(onSuccess, onFailure); }; Query.prototype.catch = function(callback) { - return this.promise().catch(callback); + return this._getPromise().catch(callback); }; -Query.prototype.promise = function() { +Query.prototype._getPromise = function () { if (this._promise) return this._promise; this._promise = new Promise(function(resolve, reject) { - this.once('end', resolve); - this.once('error', reject); + this._once('end', resolve); + this._once('error', reject); }.bind(this)); return this._promise; }; +Query.prototype.promise = util.deprecate(function() { + return this._getPromise(); +}, 'Query.promise() is deprecated - see the upgrade guide at https://node-postgres.com/guides/upgrading'); + Query.prototype.requiresPreparation = function() { //named queries must always be prepared if(this.name) { return true; } diff --git a/lib/utils.js b/lib/utils.js index 82d1aefd5..5049b5afd 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -6,6 +6,8 @@ * README.md file in the root directory of this source tree. */ +var util = require('util'); + var defaults = require('./defaults'); function escapeElement(elementRepresentation) { @@ -137,11 +139,26 @@ function normalizeQueryConfig (config, values, callback) { return config; } +var queryEventEmitterOverloadDeprecationMessage = 'Using the automatically created return value from client.query as an event emitter is deprecated. Please see the upgrade guide at https://node-postgres.com/guides/upgrading'; + +var deprecateEventEmitter = function(Emitter) { + var Result = function () { + Emitter.apply(this, arguments); + }; + util.inherits(Result, Emitter); + Result.prototype._on = Result.prototype.on; + Result.prototype._once = Result.prototype.once; + Result.prototype.on = util.deprecate(Result.prototype.on, queryEventEmitterOverloadDeprecationMessage); + Result.prototype.once = util.deprecate(Result.prototype.once, queryEventEmitterOverloadDeprecationMessage); + return Result; +}; + module.exports = { prepareValue: function prepareValueWrapper (value) { //this ensures that extra arguments do not get passed into prepareValue //by accident, eg: from calling values.map(utils.prepareValue) return prepareValue(value); }, - normalizeQueryConfig: normalizeQueryConfig + normalizeQueryConfig: normalizeQueryConfig, + deprecateEventEmitter: deprecateEventEmitter, }; diff --git a/test/test-helper.js b/test/test-helper.js index d8e068764..3bb4b6c9f 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -1,6 +1,8 @@ //make assert a global... assert = require('assert'); +process.noDeprecation = true + //support for node@0.10.x if (typeof Promise == 'undefined') { global.Promise = require('promise-polyfill') From 1e04fdb7e01031f91872f5f1300b9e1d13ce7cc3 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 19 Jun 2017 16:07:12 -0500 Subject: [PATCH 0245/1037] Add changes for v6.3.0 --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56b294133..09c1f89da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### v6.3.0 + +- Deprecate `pg.connect` `pg.end` and `pg.cancel` - favor using `new pg.Pool()` instead of pg singleton. +- Deprecate undocumented but possibly used `query.promise()` method. Use the promise returned directly from `client.query` / `pool.query`. +- Deprecate returning an automatically created query result from `client.query`. Instead return more idomatic responses for callback/promise methods. + ### v6.2.0 - Add support for [parsing `replicationStart` messages](https://github.com/brianc/node-postgres/pull/1271/files). From f7a946155f78b1b05adda1c4e57857716eed82d9 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 19 Jun 2017 16:08:23 -0500 Subject: [PATCH 0246/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 40a2c6efa..87d2c2fa4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.2.4", + "version": "6.3.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 842803c7efd5a811a2e96b432e610b9acf98d0af Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 20 Jun 2017 08:59:07 -0500 Subject: [PATCH 0247/1037] Fix over-eager deprecation warnings (#1333) * WIP * Remove console.log messages --- lib/query.js | 14 +++++++++++-- lib/utils.js | 2 +- test/integration/client/deprecation-tests.js | 22 ++++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 test/integration/client/deprecation-tests.js diff --git a/lib/query.js b/lib/query.js index 652db38e7..b8f6d77eb 100644 --- a/lib/query.js +++ b/lib/query.js @@ -57,8 +57,18 @@ Query.prototype.catch = function(callback) { Query.prototype._getPromise = function () { if (this._promise) return this._promise; this._promise = new Promise(function(resolve, reject) { - this._once('end', resolve); - this._once('error', reject); + var onEnd = function (result) { + this.removeListener('error', onError); + this.removeListener('end', onEnd); + resolve(result); + }; + var onError = function (err) { + this.removeListener('error', onError); + this.removeListener('end', onEnd); + reject(err); + }; + this._on('end', onEnd); + this._on('error', onError); }.bind(this)); return this._promise; }; diff --git a/lib/utils.js b/lib/utils.js index 5049b5afd..eccf5069d 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -139,7 +139,7 @@ function normalizeQueryConfig (config, values, callback) { return config; } -var queryEventEmitterOverloadDeprecationMessage = 'Using the automatically created return value from client.query as an event emitter is deprecated. Please see the upgrade guide at https://node-postgres.com/guides/upgrading'; +var queryEventEmitterOverloadDeprecationMessage = 'Using the automatically created return value from client.query as an event emitter is deprecated and will be removed in pg@7.0. Please see the upgrade guide at https://node-postgres.com/guides/upgrading'; var deprecateEventEmitter = function(Emitter) { var Result = function () { diff --git a/test/integration/client/deprecation-tests.js b/test/integration/client/deprecation-tests.js new file mode 100644 index 000000000..39160d5a5 --- /dev/null +++ b/test/integration/client/deprecation-tests.js @@ -0,0 +1,22 @@ +var helper = require('./test-helper') +process.noDeprecation = false +process.on('warning', function () { + throw new Error('Should not emit deprecation warning') +}) + +var client = new helper.pg.Client() + +client.connect(function (err) { + if (err) throw err + client.query('SELECT NOW()') + .then(function (res) { + client.query('SELECT NOW()', function () { + client.end(function () { + }) + }) + }).catch(function (err) { + setImmediate(function () { + throw err + }) + }) +}) From e4469340aee6703eaa9f1879b82d7eeab99a441e Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Tue, 20 Jun 2017 09:17:27 -0500 Subject: [PATCH 0248/1037] Fix deprecation warnings in native driver --- lib/native/index.js | 6 ++++-- lib/native/query.js | 20 +++++++++++++++----- test/integration/client/deprecation-tests.js | 5 +++-- test/test-helper.js | 2 -- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/native/index.js b/lib/native/index.js index 99c029fbc..473500984 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -209,9 +209,11 @@ Client.prototype._pulseQueryQueue = function(initialConnection) { this._activeQuery = query; query.submit(this); var self = this; - query.once('_done', function() { + var pulseOnDone = function() { self._pulseQueryQueue(); - }); + query.removeListener('_done', pulseOnDone); + }; + query._on('_done', pulseOnDone); }; //attempt to cancel an in-progress query diff --git a/lib/native/query.js b/lib/native/query.js index 3d6b3c032..88e19f5f9 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -27,7 +27,7 @@ var NativeQuery = module.exports = function(config, values, callback) { //this has almost no meaning because libpq //reads all rows into memory befor returning any this._emitRowEvents = false; - this.on('newListener', function(event) { + this._on('newListener', function(event) { if(event === 'row') this._emitRowEvents = true; }.bind(this)); }; @@ -42,18 +42,28 @@ NativeQuery._once = NativeQuery.once; NativeQuery.prototype.then = function(onSuccess, onFailure) { - return this.promise().then(onSuccess, onFailure); + return this._getPromise().then(onSuccess, onFailure); }; NativeQuery.prototype.catch = function(callback) { - return this.promise().catch(callback); + return this._getPromise().catch(callback); }; NativeQuery.prototype._getPromise = function() { if (this._promise) return this._promise; this._promise = new Promise(function(resolve, reject) { - this._once('end', resolve); - this._once('error', reject); + var onEnd = function (result) { + this.removeListener('error', onError); + this.removeListener('end', onEnd); + resolve(result); + }; + var onError = function (err) { + this.removeListener('error', onError); + this.removeListener('end', onEnd); + reject(err); + }; + this._on('end', onEnd); + this._on('error', onError); }.bind(this)); return this._promise; }; diff --git a/test/integration/client/deprecation-tests.js b/test/integration/client/deprecation-tests.js index 39160d5a5..21decc46f 100644 --- a/test/integration/client/deprecation-tests.js +++ b/test/integration/client/deprecation-tests.js @@ -1,6 +1,7 @@ var helper = require('./test-helper') -process.noDeprecation = false -process.on('warning', function () { + +process.on('warning', function (warning) { + console.log(warning) throw new Error('Should not emit deprecation warning') }) diff --git a/test/test-helper.js b/test/test-helper.js index 3bb4b6c9f..d8e068764 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -1,8 +1,6 @@ //make assert a global... assert = require('assert'); -process.noDeprecation = true - //support for node@0.10.x if (typeof Promise == 'undefined') { global.Promise = require('promise-polyfill') From afe249896fb2b98373004c433b6d18b74ba7946e Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Tue, 20 Jun 2017 09:30:59 -0500 Subject: [PATCH 0249/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 87d2c2fa4..635b49fb9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.3.0", + "version": "6.3.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 860cccd53105f7bc32fed8b1de69805f0ecd12eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eder=20=C3=81vila=20Prado?= Date: Tue, 20 Jun 2017 17:22:29 -0300 Subject: [PATCH 0250/1037] fix for server enconding when using SQL_ASCII and latin1 enconding --- lib/client.js | 5 +++-- lib/connection.js | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/client.js b/lib/client.js index bbda1ddf5..a031eb3e3 100644 --- a/lib/client.js +++ b/lib/client.js @@ -39,11 +39,12 @@ var Client = function(config) { this.connection = c.connection || new Connection({ stream: c.stream, ssl: this.connectionParameters.ssl, - keepAlive: c.keepAlive || false + keepAlive: c.keepAlive || false, + client_encoding: this.connectionParameters.client_encoding || 'utf8', }); this.queryQueue = []; this.binary = c.binary || defaults.binary; - this.encoding = 'utf8'; + this.encoding = this.connectionParameters.client_encoding || 'utf8'; this.processID = null; this.secretKey = null; this.ssl = this.connectionParameters.ssl || false; diff --git a/lib/connection.js b/lib/connection.js index b031ece16..0fb874cf5 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -39,7 +39,7 @@ var Connection = function(config) { this.lastOffset = 0; this.buffer = null; this.offset = null; - this.encoding = 'utf8'; + this.encoding = config.client_encoding || 'utf8'; this.parsedStatements = {}; this.writer = new Writer(); this.ssl = config.ssl || false; From 055e708dc614b1d54605cecfa73aa75e18195f73 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 21 Jun 2017 12:29:57 -0500 Subject: [PATCH 0251/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 635b49fb9..3659c7616 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.3.1", + "version": "6.3.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 7636f3630bb5d59f65ee7b89726dff63cd4768e2 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 21 Jun 2017 12:33:33 -0500 Subject: [PATCH 0252/1037] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09c1f89da..e955bb523 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### v6.4.0 + +- Add support for passing `client_encoding` as a connection parameter. Used when decoding strings in the JavaScript driver. The default is still `utf8`. + ### v6.3.0 - Deprecate `pg.connect` `pg.end` and `pg.cancel` - favor using `new pg.Pool()` instead of pg singleton. From a0a050702e2aa6cbda2bf7068f765ea9a0943588 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 21 Jun 2017 12:33:43 -0500 Subject: [PATCH 0253/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3659c7616..f48a9bf40 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.3.2", + "version": "6.4.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From dbf3bd3304a41d759f5c5c0bf86a2f4b6ac8d7db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20B=C3=B6hlmark?= Date: Mon, 26 Jun 2017 12:52:09 +0200 Subject: [PATCH 0254/1037] use consistent syntax for semver ranges --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f48a9bf40..bb6aac1a2 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "pg-connection-string": "0.1.3", "pg-pool": "1.*", "pg-types": "1.*", - "pgpass": "1.x", + "pgpass": "1.*", "semver": "4.3.2" }, "devDependencies": { From c2af53a24e6a6bf61fe0f40e5448540dbe9e2d56 Mon Sep 17 00:00:00 2001 From: 2Pacalypse- Date: Sat, 27 May 2017 21:06:37 +0200 Subject: [PATCH 0255/1037] Properly insert buffers in arrays. Before this commit, when someone tried to insert a Buffer into an array, the library would try to escape it (by calling the `escapeElement` on it), which would fail because buffers don't have a `replace` method. --- lib/utils.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/utils.js b/lib/utils.js index eccf5069d..56a45cb06 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -33,6 +33,9 @@ function arrayString(val) { else if(Array.isArray(val[i])) { result = result + arrayString(val[i]); } + else if(val[i] instanceof Buffer) { + result += '\\\\x' + val[i].toString('hex'); + } else { result += escapeElement(prepareValue(val[i])); From e44d83f02ffe1ec5b7907d3e62268af01f701291 Mon Sep 17 00:00:00 2001 From: 2Pacalypse- Date: Sat, 10 Jun 2017 17:08:10 +0200 Subject: [PATCH 0256/1037] Add the test for arrays of buffers. --- test/unit/utils-tests.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/unit/utils-tests.js b/test/unit/utils-tests.js index d640f9880..685b59e38 100644 --- a/test/unit/utils-tests.js +++ b/test/unit/utils-tests.js @@ -126,6 +126,13 @@ test('prepareValue: date array prepared properly', function() { helper.resetTimezoneOffset(); }); +test('prepareValue: buffer array prepared properly', function() { + var buffer1 = Buffer.from('dead', 'hex'); + var buffer2 = Buffer.from('beef', 'hex'); + var out = utils.prepareValue([buffer1, buffer2]); + assert.strictEqual(out, '{\\\\xdead,\\\\xbeef}'); +}); + test('prepareValue: arbitrary objects prepared properly', function() { var out = utils.prepareValue({ x: 42 }); assert.strictEqual(out, '{"x":42}'); From e52512cedbd72a0be48c2a02ea30753fb964c854 Mon Sep 17 00:00:00 2001 From: 2Pacalypse- Date: Mon, 12 Jun 2017 22:12:06 +0200 Subject: [PATCH 0257/1037] Adjust the test for arrays of buffers to work across all node versions. --- test/unit/utils-tests.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/utils-tests.js b/test/unit/utils-tests.js index 685b59e38..19c0b8db7 100644 --- a/test/unit/utils-tests.js +++ b/test/unit/utils-tests.js @@ -127,8 +127,8 @@ test('prepareValue: date array prepared properly', function() { }); test('prepareValue: buffer array prepared properly', function() { - var buffer1 = Buffer.from('dead', 'hex'); - var buffer2 = Buffer.from('beef', 'hex'); + var buffer1 = Buffer.from ? Buffer.from('dead', 'hex') : new Buffer('dead', 'hex'); + var buffer2 = Buffer.from ? Buffer.from('beef', 'hex') : new Buffer('beef', 'hex'); var out = utils.prepareValue([buffer1, buffer2]); assert.strictEqual(out, '{\\\\xdead,\\\\xbeef}'); }); From bc0b03e0b058a211bedd5c78b87491e153640a5b Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Thu, 13 Jul 2017 22:29:42 -0500 Subject: [PATCH 0258/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bb6aac1a2..7bd05f7f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.4.0", + "version": "6.4.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From a0eb36d81938e488b3bc5369faee74fe22f36949 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 13 Jul 2017 22:37:08 -0500 Subject: [PATCH 0259/1037] 2.0 (#67) * Initial work * Make progress on custom pool * Make all original tests pass * Fix test race * Fix test when DNS is missing * Test more error conditions * Add test for byop * Add BYOP tests for errors * Add test for idle client error expunging * Fix typo * Replace var with const/let * Remove var usage * Fix linting * Work on connection timeout * Work on error condition tests * Remove logging * Add connection timeout * Add idle timeout * Test for returning to client to pool after error fixes #48 * Add idleTimeout support to native client * Add pg as peer dependency fixes #45 * Rename properties * Fix lint * use strict * Add draining to pool.end * Ensure ending pools drain properly * Remove yarn.lock * Remove object-assign * Remove node 8 * Remove closure for waiter construction * Ensure client.connect is never sync * Fix lint * Change to es6 class * Code cleanup & lint fixes --- .travis.yml | 3 - index.js | 364 ++++++++++++++++++++------------- package.json | 9 +- test/bring-your-own-promise.js | 36 ++++ test/connection-strings.js | 12 +- test/connection-timeout.js | 62 ++++++ test/ending.js | 34 +++ test/error-handling.js | 135 ++++++++++++ test/events.js | 48 ++--- test/idle-timeout.js | 54 +++++ test/index.js | 173 ++++++++-------- test/logging.js | 14 +- test/mocha.opts | 2 + test/setup.js | 10 + test/sizing.js | 44 ++++ test/timeout.js | 0 test/verify.js | 25 +++ 17 files changed, 748 insertions(+), 277 deletions(-) create mode 100644 test/bring-your-own-promise.js create mode 100644 test/connection-timeout.js create mode 100644 test/ending.js create mode 100644 test/error-handling.js create mode 100644 test/idle-timeout.js create mode 100644 test/setup.js create mode 100644 test/sizing.js create mode 100644 test/timeout.js create mode 100644 test/verify.js diff --git a/.travis.yml b/.travis.yml index 47358a12a..e1a0ce70c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,3 @@ matrix: - node_js: "6" addons: postgresql: "9.4" - - node_js: "8" - addons: - postgresql: "9.4" diff --git a/index.js b/index.js index 7e0f0ce59..c317e5311 100644 --- a/index.js +++ b/index.js @@ -1,174 +1,248 @@ -var genericPool = require('generic-pool') -var util = require('util') -var EventEmitter = require('events').EventEmitter -var objectAssign = require('object-assign') - -// there is a bug in the generic pool where it will not recreate -// destroyed workers (even if there is waiting work to do) unless -// there is a min specified. Make sure we keep some connections -// SEE: https://github.com/coopernurse/node-pool/pull/186 -// SEE: https://github.com/brianc/node-pg-pool/issues/48 -// SEE: https://github.com/strongloop/loopback-connector-postgresql/issues/231 -function _ensureMinimum () { - var i, diff, waiting - if (this._draining) return - waiting = this._waitingClients.size() - if (this._factory.min > 0) { // we have positive specified minimum - diff = this._factory.min - this._count - } else if (waiting > 0) { // we have no minimum, but we do have work to do - diff = Math.min(waiting, this._factory.max - this._count) - } - for (i = 0; i < diff; i++) { - this._createResource() - } -}; - -var Pool = module.exports = function (options, Client) { - if (!(this instanceof Pool)) { - return new Pool(options, Client) - } - EventEmitter.call(this) - this.options = objectAssign({}, options) - this.log = this.options.log || function () { } - this.Client = this.options.Client || Client || require('pg').Client - this.Promise = this.options.Promise || global.Promise - - this.options.max = this.options.max || this.options.poolSize || 10 - this.options.create = this.options.create || this._create.bind(this) - this.options.destroy = this.options.destroy || this._destroy.bind(this) - this.pool = new genericPool.Pool(this.options) - // Monkey patch to ensure we always finish our work - // - There is a bug where callbacks go uncalled if min is not set - // - We might still not want a connection to *always* exist - // - but we do want to create up to max connections if we have work - // - still waiting - // This should be safe till the version of pg-pool is upgraded - // SEE: https://github.com/coopernurse/node-pool/pull/186 - this.pool._ensureMinimum = _ensureMinimum - this.onCreate = this.options.onCreate -} +'use strict' +const EventEmitter = require('events').EventEmitter -util.inherits(Pool, EventEmitter) +const NOOP = function () { } -Pool.prototype._promise = function (cb, executor) { - if (!cb) { - return new this.Promise(executor) +class IdleItem { + constructor (client, timeoutId) { + this.client = client + this.timeoutId = timeoutId } +} - function resolved (value) { - process.nextTick(function () { - cb(null, value) - }) +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._remove(client) + this._pulseQueue() + return } - function rejected (error) { - process.nextTick(function () { - cb(error) - }) + // idle timeout + let tid + if (this.options.idleTimeoutMillis) { + tid = setTimeout(() => { + this.log('remove idle client') + this._remove(client) + }, this.idleTimeoutMillis) } - executor(resolved, rejected) + if (this.ending) { + this._remove(client) + } else { + this._idle.push(new IdleItem(client, tid)) + } + this._pulseQueue() } -Pool.prototype._promiseNoCallback = function (callback, executor) { - return callback - ? executor() - : new this.Promise(executor) +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 } } -Pool.prototype._destroy = function (client) { - if (client._destroying) return - client._destroying = true - client.end() -} +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 + + this._clients = [] + this._idle = [] + this._pendingQueue = [] + this._endCallback = undefined + this.ending = false + } -Pool.prototype._create = function (cb) { - this.log('connecting new client') - var client = new this.Client(this.options) - - client.on('error', function (e) { - this.log('connected client error:', e) - this.pool.destroy(client) - e.client = client - this.emit('error', e, client) - }.bind(this)) - - client.connect(function (err) { - if (err) { - this.log('client connection error:', err) - cb(err, null) - } else { - this.log('client connected') - this.emit('connect', client) - cb(null, client) - } - }.bind(this)) -} + _isFull () { + return this._clients.length >= this.options.max + } -Pool.prototype.connect = function (cb) { - return this._promiseNoCallback(cb, function (resolve, reject) { - this.log('acquire client begin') - this.pool.acquire(function (err, client) { - if (err) { - this.log('acquire client. error:', err) - if (cb) { - cb(err, null, function () {}) - } else { - reject(err) - } - return + _pulseQueue () { + this.log('pulse queue') + if (this.ending) { + this.log('pulse queue on ending') + if (this._idle.length) { + this._idle.map(item => { + this._remove(item.client) + }) } - - this.log('acquire 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') + } - client.release = function (err) { - delete client.release - if (err) { - this.log('destroy client. error:', err) - this.pool.destroy(client) - } else { - this.log('release client') - this.pool.release(client) - } - }.bind(this) + _remove (client) { + this._idle = this._idle.filter(item => item.client !== client) + this._clients = this._clients.filter(c => c !== client) + client.end() + this.emit('remove', client) + } - if (cb) { - cb(null, client, client.release) - } else { - resolve(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 (this._clients.length >= this.options.max || this._idle.length) { + const response = promisify(this.Promise, cb) + const result = response.result + this._pendingQueue.push(response.callback) + // if we have idle clients schedule a pulse immediately + if (this._idle.length) { + process.nextTick(() => this._pulseQueue()) } - }.bind(this)) - }.bind(this)) -} + 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) + } -Pool.prototype.take = Pool.prototype.connect + const response = promisify(this.Promise, cb) + cb = response.callback -Pool.prototype.query = function (text, values, cb) { - if (typeof values === 'function') { - cb = values - values = undefined + 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 } - return this._promise(cb, function (resolve, reject) { - this.connect(function (err, client, done) { + query (text, values, cb) { + if (typeof values === 'function') { + cb = values + values = undefined + } + const response = promisify(this.Promise, cb) + cb = response.callback + this.connect((err, client) => { if (err) { - return reject(err) + return cb(err) } - client.query(text, values, function (err, res) { - done(err) - err ? reject(err) : resolve(res) + 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) + } }) }) - }.bind(this)) -} + return response.result + } -Pool.prototype.end = function (cb) { - this.log('draining pool') - return this._promise(cb, function (resolve, reject) { - this.pool.drain(function () { - this.log('pool drained, calling destroy all now') - this.pool.destroyAllNow(resolve) - }.bind(this)) - }.bind(this)) + 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 diff --git a/package.json b/package.json index b3424f1e4..392375bbd 100644 --- a/package.json +++ b/package.json @@ -27,15 +27,16 @@ "homepage": "https://github.com/brianc/node-pg-pool#readme", "devDependencies": { "bluebird": "3.4.1", + "co": "4.6.0", "expect.js": "0.3.1", "lodash": "4.13.1", "mocha": "^2.3.3", - "pg": "5.1.0", + "pg": "*", "standard": "7.1.2", "standard-format": "2.2.1" }, - "dependencies": { - "generic-pool": "2.4.3", - "object-assign": "4.1.0" + "dependencies": {}, + "peerDependencies": { + "pg": ">5.0" } } diff --git a/test/bring-your-own-promise.js b/test/bring-your-own-promise.js new file mode 100644 index 000000000..f7fe3bde9 --- /dev/null +++ b/test/bring-your-own-promise.js @@ -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()) + })) +}) diff --git a/test/connection-strings.js b/test/connection-strings.js index 8ee3d074b..7013f28da 100644 --- a/test/connection-strings.js +++ b/test/connection-strings.js @@ -1,13 +1,13 @@ -var expect = require('expect.js') -var describe = require('mocha').describe -var it = require('mocha').it -var Pool = require('../') +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) { - var connectionString = 'postgres://foo:bar@baz:1234/xur' + const connectionString = 'postgres://foo:bar@baz:1234/xur' - var pool = new Pool({ + 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) diff --git a/test/connection-timeout.js b/test/connection-timeout.js new file mode 100644 index 000000000..0671b1120 --- /dev/null +++ b/test/connection-timeout.js @@ -0,0 +1,62 @@ +'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))) +}) + diff --git a/test/ending.js b/test/ending.js new file mode 100644 index 000000000..1956b13f6 --- /dev/null +++ b/test/ending.js @@ -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') + })) +}) diff --git a/test/error-handling.js b/test/error-handling.js new file mode 100644 index 000000000..de68fad32 --- /dev/null +++ b/test/error-handling.js @@ -0,0 +1,135 @@ +'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('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() + })) + }) +}) diff --git a/test/events.js b/test/events.js index 759dff02d..3d4405e28 100644 --- a/test/events.js +++ b/test/events.js @@ -1,14 +1,15 @@ -var expect = require('expect.js') -var EventEmitter = require('events').EventEmitter -var describe = require('mocha').describe -var it = require('mocha').it -var objectAssign = require('object-assign') -var Pool = require('../') +'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) { - var pool = new Pool() - var emittedClient = false + const pool = new Pool() + let emittedClient = false pool.on('connect', function (client) { emittedClient = client }) @@ -23,48 +24,47 @@ describe('events', function () { }) it('emits "connect" only with a successful connection', function (done) { - var pool = new Pool({ + const pool = new Pool({ // This client will always fail to connect Client: mockClient({ connect: function (cb) { - process.nextTick(function () { cb(new Error('bad news')) }) + process.nextTick(() => { + cb(new Error('bad news')) + setImmediate(done) + }) } }) }) pool.on('connect', function () { throw new Error('should never get here') }) - pool._create(function (err) { - if (err) done() - else done(new Error('expected failure')) - }) + return pool.connect().catch(e => expect(e.message).to.equal('bad news')) }) it('emits acquire every time a client is acquired', function (done) { - var pool = new Pool() - var acquireCount = 0 + const pool = new Pool() + let acquireCount = 0 pool.on('acquire', function (client) { expect(client).to.be.ok() acquireCount++ }) - for (var i = 0; i < 10; i++) { + for (let i = 0; i < 10; i++) { pool.connect(function (err, client, release) { - err ? done(err) : release() - release() if (err) return done(err) + release() }) pool.query('SELECT now()') } setTimeout(function () { expect(acquireCount).to.be(20) pool.end(done) - }, 40) + }, 100) }) it('emits error and client if an idle client in the pool hits an error', function (done) { - var pool = new Pool() + const pool = new Pool() pool.connect(function (err, client) { - expect(err).to.equal(null) + expect(err).to.equal(undefined) client.release() setImmediate(function () { client.emit('error', new Error('problem')) @@ -80,8 +80,8 @@ describe('events', function () { function mockClient (methods) { return function () { - var client = new EventEmitter() - objectAssign(client, methods) + const client = new EventEmitter() + Object.assign(client, methods) return client } } diff --git a/test/idle-timeout.js b/test/idle-timeout.js new file mode 100644 index 000000000..68a2b78a0 --- /dev/null +++ b/test/idle-timeout.js @@ -0,0 +1,54 @@ +'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('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() + })) +}) diff --git a/test/index.js b/test/index.js index 3f2b99d95..010d99c56 100644 --- a/test/index.js +++ b/test/index.js @@ -1,26 +1,16 @@ -var expect = require('expect.js') -var _ = require('lodash') +'use strict' +const expect = require('expect.js') +const _ = require('lodash') -var describe = require('mocha').describe -var it = require('mocha').it -var Promise = require('bluebird') +const describe = require('mocha').describe +const it = require('mocha').it -var Pool = require('../') - -if (typeof global.Promise === 'undefined') { - global.Promise = Promise -} +const Pool = require('../') describe('pool', function () { - it('can be used as a factory function', function () { - var pool = Pool() - expect(pool instanceof Pool).to.be.ok() - expect(typeof pool.connect).to.be('function') - }) - describe('with callbacks', function () { it('works totally unconfigured', function (done) { - var pool = new Pool() + const pool = new Pool() pool.connect(function (err, client, release) { if (err) return done(err) client.query('SELECT NOW()', function (err, res) { @@ -33,7 +23,7 @@ describe('pool', function () { }) it('passes props to clients', function (done) { - var pool = new Pool({ binary: true }) + const pool = new Pool({ binary: true }) pool.connect(function (err, client, release) { release() if (err) return done(err) @@ -43,7 +33,7 @@ describe('pool', function () { }) it('can run a query with a callback without parameters', function (done) { - var pool = new Pool() + const pool = new Pool() pool.query('SELECT 1 as num', function (err, res) { expect(res.rows[0]).to.eql({ num: 1 }) pool.end(function () { @@ -53,7 +43,7 @@ describe('pool', function () { }) it('can run a query with a callback', function (done) { - var pool = new Pool() + 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 () { @@ -63,18 +53,30 @@ describe('pool', function () { }) it('passes connection errors to callback', function (done) { - var pool = new Pool({host: 'no-postgres-server-here.com'}) + 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) { - var pool = new Pool() + const pool = new Pool() pool.connect(function (err, client, release) { release() if (err) return done(err) @@ -94,8 +96,8 @@ describe('pool', function () { }) it('should not change given options', function (done) { - var options = { max: 10 } - var pool = new Pool(options) + const options = { max: 10 } + const pool = new Pool(options) pool.connect(function (err, client, release) { release() if (err) return done(err) @@ -105,8 +107,8 @@ describe('pool', function () { }) it('does not create promises when connecting', function (done) { - var pool = new Pool() - var returnValue = pool.connect(function (err, client, release) { + const pool = new Pool() + const returnValue = pool.connect(function (err, client, release) { release() if (err) return done(err) pool.end(done) @@ -115,8 +117,8 @@ describe('pool', function () { }) it('does not create promises when querying', function (done) { - var pool = new Pool() - var returnValue = pool.query('SELECT 1 as num', function (err) { + const pool = new Pool() + const returnValue = pool.query('SELECT 1 as num', function (err) { pool.end(function () { done(err) }) @@ -125,67 +127,99 @@ describe('pool', function () { }) it('does not create promises when ending', function (done) { - var pool = new Pool() - var returnValue = pool.end(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 and disconnects', function () { - var pool = new Pool() + it('connects, queries, and disconnects', function () { + const pool = new Pool() return pool.connect().then(function (client) { - expect(pool.pool.availableObjectsCount()).to.be(0) return client.query('select $1::text as name', ['hi']).then(function (res) { expect(res.rows).to.eql([{ name: 'hi' }]) client.release() - expect(pool.pool.getPoolSize()).to.be(1) - expect(pool.pool.availableObjectsCount()).to.be(1) 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 () { - var pool = new Pool({ poolSize: 9 }) - return Promise.map(_.times(30), 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 }) }) - }).then(function (res) { + }) + return Promise.all(promises).then(function (res) { expect(res).to.have.length(30) - expect(pool.pool.getPoolSize()).to.be(9) + expect(pool.totalCount).to.be(9) return pool.end() }) }) it('supports just running queries', function () { - var pool = new Pool({ poolSize: 9 }) - return Promise.map(_.times(30), function () { - return pool.query('SELECT $1::text as name', ['hi']) - }).then(function (queries) { + 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) - expect(pool.pool.getPoolSize()).to.be(9) - expect(pool.pool.availableObjectsCount()).to.be(9) return pool.end() }) }) - it('recovers from all errors', function () { - var pool = new Pool() + it('recovers from query errors', function () { + const pool = new Pool() - var errors = [] - return Promise.mapSeries(_.times(30), function () { + const errors = [] + const promises = _.times(30, () => { return pool.query('SELECT asldkfjasldkf') .catch(function (e) { errors.push(e) }) - }).then(function () { + }) + 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(errors).to.have.length(30) expect(res.rows).to.eql([{ name: 'hi' }]) return pool.end() }) @@ -193,40 +227,3 @@ describe('pool', function () { }) }) }) - -describe('pool error handling', function () { - it('Should complete these queries without dying', function (done) { - var pgPool = new Pool() - var pool = pgPool.pool - pool._factory.max = 1 - pool._factory.min = null - var errors = 0 - var shouldGet = 0 - function runErrorQuery () { - shouldGet++ - return new Promise(function (resolve, reject) { - pgPool.query("SELECT 'asd'+1 ").then(function (res) { - reject(res) // this should always error - }).catch(function (err) { - errors++ - resolve(err) - }) - }) - } - var ps = [] - for (var i = 0; i < 5; i++) { - ps.push(runErrorQuery()) - } - Promise.all(ps).then(function () { - expect(shouldGet).to.eql(errors) - done() - }) - }) -}) - -process.on('unhandledRejection', function (e) { - console.error(e.message, e.stack) - setImmediate(function () { - throw e - }) -}) diff --git a/test/logging.js b/test/logging.js index 47389a5aa..839603b78 100644 --- a/test/logging.js +++ b/test/logging.js @@ -1,17 +1,17 @@ -var expect = require('expect.js') +const expect = require('expect.js') -var describe = require('mocha').describe -var it = require('mocha').it +const describe = require('mocha').describe +const it = require('mocha').it -var Pool = require('../') +const Pool = require('../') describe('logging', function () { it('logs to supplied log function if given', function () { - var messages = [] - var log = function (msg) { + const messages = [] + const log = function (msg) { messages.push(msg) } - var pool = new Pool({ log: log }) + const pool = new Pool({ log: log }) return pool.query('SELECT NOW()').then(function () { expect(messages.length).to.be.greaterThan(0) return pool.end() diff --git a/test/mocha.opts b/test/mocha.opts index 46e8e69d9..590fb8628 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1,2 +1,4 @@ +--require test/setup.js --no-exit --bail +--timeout 10000 diff --git a/test/setup.js b/test/setup.js new file mode 100644 index 000000000..cf75b7a67 --- /dev/null +++ b/test/setup.js @@ -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') diff --git a/test/sizing.js b/test/sizing.js new file mode 100644 index 000000000..9e926877d --- /dev/null +++ b/test/sizing.js @@ -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() + })) +}) diff --git a/test/timeout.js b/test/timeout.js new file mode 100644 index 000000000..e69de29bb diff --git a/test/verify.js b/test/verify.js new file mode 100644 index 000000000..667dea9ff --- /dev/null +++ b/test/verify.js @@ -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() + }) + }) +}) From 139cbdea16e5b54c2e8b65a971710965d143ea3e Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Thu, 13 Jul 2017 22:37:45 -0500 Subject: [PATCH 0260/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 392375bbd..be1eb1420 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "1.8.0", + "version": "2.0.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From 2421a769cb03b13430706d884a13cd5dc86b98fd Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 13 Jul 2017 22:40:26 -0500 Subject: [PATCH 0261/1037] Update README.md --- README.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index b86447b40..a02fa32cc 100644 --- a/README.md +++ b/README.md @@ -17,23 +17,24 @@ 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 +// 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 +// 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 + 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 From 40f5126b6ef16d80c03a3001b0802824dbbe2af5 Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 14 Jul 2017 14:07:07 -0500 Subject: [PATCH 0262/1037] Fix idle client teardown on error (#68) - Re-add default idleTimeoutMillis = 10000 by default - Fix idle timeout clearing on shutdown - Ensure idleTimeoutMillis is used in timeout --- index.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index c317e5311..49d797be2 100644 --- a/index.js +++ b/index.js @@ -16,7 +16,7 @@ function throwOnRelease () { function release (client, err) { client.release = throwOnRelease - if (err) { + if (err || this.ending) { this._remove(client) this._pulseQueue() return @@ -28,14 +28,10 @@ function release (client, err) { tid = setTimeout(() => { this.log('remove idle client') this._remove(client) - }, this.idleTimeoutMillis) + }, this.options.idleTimeoutMillis) } - if (this.ending) { - this._remove(client) - } else { - this._idle.push(new IdleItem(client, tid)) - } + this._idle.push(new IdleItem(client, tid)) this._pulseQueue() } @@ -64,6 +60,10 @@ class Pool extends EventEmitter { 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 = [] @@ -114,7 +114,10 @@ class Pool extends EventEmitter { } _remove (client) { - this._idle = this._idle.filter(item => item.client !== client) + this._idle = this._idle.filter(item => { + clearTimeout(item.timeoutId) + return item.client !== client + }) this._clients = this._clients.filter(c => c !== client) client.end() this.emit('remove', client) From a446537377d7157be60f59f4684b69632051d501 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 14 Jul 2017 14:07:19 -0500 Subject: [PATCH 0263/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index be1eb1420..a0ebd92bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "2.0.0", + "version": "2.0.1", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From 27450d07e6fb4eb0eb7a14754963c8bf9d2a3be9 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 14 Jul 2017 14:57:48 -0500 Subject: [PATCH 0264/1037] Throw on reconnect attempt Clients are not reusable. This changes the client to raise errors whenever you try to reconnect a client that's already been used. They're cheap to create: just instantiate a new one (or use the pool) :wink:. Closes #1352 --- lib/client.js | 10 + lib/index.js | 2 +- lib/native/client.js | 8 + package.json | 2 +- test/integration/client/api-tests.js | 20 +- test/integration/client/array-tests.js | 284 +++++++++--------- test/integration/client/empty-query-tests.js | 2 +- .../client/error-handling-tests.js | 20 ++ .../client/result-metadata-tests.js | 8 +- test/integration/client/timezone-tests.js | 6 +- test/integration/client/transaction-tests.js | 8 +- .../integration/client/type-coercion-tests.js | 10 +- .../connection-pool/idle-timeout-tests.js | 2 +- .../connection-pool/test-helper.js | 2 +- test/integration/gh-issues/131-tests.js | 2 +- test/native/callback-api-tests.js | 4 +- .../connection-parameters/creation-tests.js | 10 +- 17 files changed, 219 insertions(+), 181 deletions(-) diff --git a/lib/client.js b/lib/client.js index ae5a176df..25a9d66c0 100644 --- a/lib/client.js +++ b/lib/client.js @@ -34,6 +34,7 @@ var Client = function(config) { this._types = new TypeOverrides(c.types); this._ending = false; this._connecting = false; + this._connected = false; this._connectionError = false; this.connection = c.connection || new Connection({ @@ -54,6 +55,14 @@ util.inherits(Client, EventEmitter); Client.prototype.connect = function(callback) { var self = this; var con = this.connection; + if (this._connecting || this._connected) { + const err = new Error('Client has already been connected. You cannot reuse a client.') + if (callback) { + callback(err) + return undefined + } + return Promise.reject(err) + } this._connecting = true; if(this.host && this.host.indexOf('/') === 0) { @@ -135,6 +144,7 @@ Client.prototype.connect = function(callback) { //after the connection initially becomes ready for queries con.once('readyForQuery', function() { self._connecting = false; + self._connected = true; self._attachListeners(con); con.removeListener('error', connectingErrorHandler); con.on('error', connectedErrorHandler) diff --git a/lib/index.js b/lib/index.js index ad0c7172a..b74cbdeb1 100644 --- a/lib/index.js +++ b/lib/index.js @@ -21,7 +21,7 @@ const poolFactory = (Client) => { for (var key in options) { config[key] = options[key]; } - Pool.call(this, config); + return new Pool(config) }; util.inherits(BoundPool, Pool); diff --git a/lib/native/client.js b/lib/native/client.js index 9614cd14b..d8f20fe7c 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -33,6 +33,7 @@ var Client = module.exports = function(config) { this._queryQueue = []; this._connected = false; + this._connecting = false; //keep these on the object for legacy reasons //for the time being. TODO: deprecate all this jazz @@ -74,6 +75,13 @@ Client.prototype.connect = function(cb) { }) } + if (this._connecting) { + process.nextTick(() => cb(new Error('Client has already been connected. You cannot reuse a client.'))) + return result + } + + this._connecting = true + this.connectionParameters.getLibpqConnectionString(function(err, conString) { if(err) return onError(err); self.native.connect(conString, function(err) { diff --git a/package.json b/package.json index 0fee6bf44..537570d04 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "buffer-writer": "1.0.1", "packet-reader": "0.3.1", "pg-connection-string": "0.1.3", - "pg-pool": "1.*", + "pg-pool": "2.*", "pg-types": "1.*", "pgpass": "1.x", "semver": "4.3.2" diff --git a/test/integration/client/api-tests.js b/test/integration/client/api-tests.js index e51a363a3..668c6a743 100644 --- a/test/integration/client/api-tests.js +++ b/test/integration/client/api-tests.js @@ -8,7 +8,7 @@ suite.test("pool callback behavior", done => { //test weird callback behavior with node-pool const pool = new pg.Pool(); pool.connect(function(err) { - assert.isNull(err); + assert(!err); arguments[1].emit("drain"); arguments[2](); pool.end(done); @@ -52,7 +52,7 @@ suite.test("executing nested queries", function(done) { const pool = new pg.Pool(); pool.connect( assert.calls(function(err, client, release) { - assert.isNull(err); + assert(!err); client.query( "select now as now from NOW()", assert.calls(function(err, result) { @@ -91,7 +91,7 @@ suite.test("query errors are handled and do not bubble if callback is provded", const pool = new pg.Pool(); pool.connect( assert.calls(function(err, client, release) { - assert.isNull(err); + assert(!err); client.query( "SELECT OISDJF FROM LEIWLISEJLSE", assert.calls(function(err, result) { @@ -109,7 +109,7 @@ suite.test("callback is fired once and only once", function(done) { const pool = new pg.Pool() pool.connect( assert.calls(function(err, client, release) { - assert.isNull(err); + assert(!err); client.query("CREATE TEMP TABLE boom(name varchar(10))"); var callCount = 0; client.query( @@ -136,14 +136,14 @@ suite.test("can provide callback and config object", function(done) { const pool = new pg.Pool() pool.connect( assert.calls(function(err, client, release) { - assert.isNull(err); + assert(!err); client.query( { name: "boom", text: "select NOW()" }, assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows[0].now.getYear(), new Date().getYear()); release(); pool.end(done) @@ -157,7 +157,7 @@ suite.test("can provide callback and config and parameters", function(done) { const pool = new pg.Pool() pool.connect( assert.calls(function(err, client, release) { - assert.isNull(err); + assert(!err); var config = { text: "select $1::text as val" }; @@ -165,7 +165,7 @@ suite.test("can provide callback and config and parameters", function(done) { config, ["hi"], assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows.length, 1); assert.equal(result.rows[0].val, "hi"); release() @@ -180,7 +180,7 @@ suite.test("null and undefined are both inserted as NULL", function(done) { const pool = new pg.Pool() pool.connect( assert.calls(function(err, client, release) { - assert.isNull(err); + assert(!err); client.query( "CREATE TEMP TABLE my_nulls(a varchar(1), b varchar(1), c integer, d integer, e date, f date)" ); @@ -191,7 +191,7 @@ suite.test("null and undefined are both inserted as NULL", function(done) { client.query( "SELECT * FROM my_nulls", assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows.length, 1); assert.isNull(result.rows[0].a); assert.isNull(result.rows[0].b); diff --git a/test/integration/client/array-tests.js b/test/integration/client/array-tests.js index e56b5e634..3185ad2c3 100644 --- a/test/integration/client/array-tests.js +++ b/test/integration/client/array-tests.js @@ -5,8 +5,9 @@ var pg = helper.pg; var suite = new helper.Suite() const pool = new pg.Pool() + pool.connect(assert.calls(function(err, client, release) { - assert.isNull(err); + assert(!err); suite.test('nulls', function(done) { client.query('SELECT $1::text[] as array', [[null]], assert.success(function(result) { @@ -33,145 +34,144 @@ pool.connect(assert.calls(function(err, client, release) { }); suite.test('cleanup', () => release()) -})); - -pool.connect(assert.calls(function (err, client, release) { - assert.isNull(err); - client.query("CREATE TEMP TABLE why(names text[], numbors integer[])"); - client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log); - suite.test('numbers', function (done) { - // client.connection.on('message', console.log) - client.query('SELECT numbors FROM why', assert.success(function (result) { - assert.lengthIs(result.rows[0].numbors, 3); - assert.equal(result.rows[0].numbors[0], 1); - assert.equal(result.rows[0].numbors[1], 2); - assert.equal(result.rows[0].numbors[2], 3); - done() - })) - }) - - suite.test('parses string arrays', function (done) { - client.query('SELECT names FROM why', assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 'aaron'); - assert.equal(names[1], 'brian'); - assert.equal(names[2], "a b c"); - done() - })) - }) - - suite.test('empty array', function (done) { - client.query("SELECT '{}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 0); - done() - })) - }) - - suite.test('element containing comma', function (done) { - client.query("SELECT '{\"joe,bob\",jim}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - assert.equal(names[0], 'joe,bob'); - assert.equal(names[1], 'jim'); - done() - })) - }) - - suite.test('bracket in quotes', function (done) { - client.query("SELECT '{\"{\",\"}\"}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - assert.equal(names[0], '{'); - assert.equal(names[1], '}'); - done() - })) - }) - - suite.test('null value', function (done) { - client.query("SELECT '{joe,null,bob,\"NULL\"}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 4); - assert.equal(names[0], 'joe'); - assert.equal(names[1], null); - assert.equal(names[2], 'bob'); - assert.equal(names[3], 'NULL'); - done() - })) - }) - - suite.test('element containing quote char', function (done) { - client.query("SELECT ARRAY['joe''', 'jim', 'bob\"'] AS names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 'joe\''); - assert.equal(names[1], 'jim'); - assert.equal(names[2], 'bob"'); - done() - })) - }) - - suite.test('nested array', function (done) { - client.query("SELECT '{{1,joe},{2,bob}}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - - assert.lengthIs(names[0], 2); - assert.equal(names[0][0], '1'); - assert.equal(names[0][1], 'joe'); - - assert.lengthIs(names[1], 2); - assert.equal(names[1][0], '2'); - assert.equal(names[1][1], 'bob'); - done() - })) - }) - - suite.test('integer array', function (done) { - client.query("SELECT '{1,2,3}'::integer[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 1); - assert.equal(names[1], 2); - assert.equal(names[2], 3); - done() - })) - }) - - suite.test('integer nested array', function (done) { - client.query("SELECT '{{1,100},{2,100},{3,100}}'::integer[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0][0], 1); - assert.equal(names[0][1], 100); - - assert.equal(names[1][0], 2); - assert.equal(names[1][1], 100); - - assert.equal(names[2][0], 3); - assert.equal(names[2][1], 100); - done() - })) - }) - - suite.test('JS array parameter', function (done) { - client.query("SELECT $1::integer[] as names", [[[1, 100], [2, 100], [3, 100]]], assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0][0], 1); - assert.equal(names[0][1], 100); - - assert.equal(names[1][0], 2); - assert.equal(names[1][1], 100); - - assert.equal(names[2][0], 3); - assert.equal(names[2][1], 100); - release(); - pool.end(done) - })) - }) - -})) - + pool.connect(assert.calls(function (err, client, release) { + assert(!err); + client.query("CREATE TEMP TABLE why(names text[], numbors integer[])"); + client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log); + suite.test('numbers', function (done) { + // client.connection.on('message', console.log) + client.query('SELECT numbors FROM why', assert.success(function (result) { + assert.lengthIs(result.rows[0].numbors, 3); + assert.equal(result.rows[0].numbors[0], 1); + assert.equal(result.rows[0].numbors[1], 2); + assert.equal(result.rows[0].numbors[2], 3); + done() + })) + }) + + suite.test('parses string arrays', function (done) { + client.query('SELECT names FROM why', assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0], 'aaron'); + assert.equal(names[1], 'brian'); + assert.equal(names[2], "a b c"); + done() + })) + }) + + suite.test('empty array', function (done) { + client.query("SELECT '{}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 0); + done() + })) + }) + + suite.test('element containing comma', function (done) { + client.query("SELECT '{\"joe,bob\",jim}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 2); + assert.equal(names[0], 'joe,bob'); + assert.equal(names[1], 'jim'); + done() + })) + }) + + suite.test('bracket in quotes', function (done) { + client.query("SELECT '{\"{\",\"}\"}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 2); + assert.equal(names[0], '{'); + assert.equal(names[1], '}'); + done() + })) + }) + + suite.test('null value', function (done) { + client.query("SELECT '{joe,null,bob,\"NULL\"}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 4); + assert.equal(names[0], 'joe'); + assert.equal(names[1], null); + assert.equal(names[2], 'bob'); + assert.equal(names[3], 'NULL'); + done() + })) + }) + + suite.test('element containing quote char', function (done) { + client.query("SELECT ARRAY['joe''', 'jim', 'bob\"'] AS names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0], 'joe\''); + assert.equal(names[1], 'jim'); + assert.equal(names[2], 'bob"'); + done() + })) + }) + + suite.test('nested array', function (done) { + client.query("SELECT '{{1,joe},{2,bob}}'::text[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 2); + + assert.lengthIs(names[0], 2); + assert.equal(names[0][0], '1'); + assert.equal(names[0][1], 'joe'); + + assert.lengthIs(names[1], 2); + assert.equal(names[1][0], '2'); + assert.equal(names[1][1], 'bob'); + done() + })) + }) + + suite.test('integer array', function (done) { + client.query("SELECT '{1,2,3}'::integer[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0], 1); + assert.equal(names[1], 2); + assert.equal(names[2], 3); + done() + })) + }) + + suite.test('integer nested array', function (done) { + client.query("SELECT '{{1,100},{2,100},{3,100}}'::integer[] as names", assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0][0], 1); + assert.equal(names[0][1], 100); + + assert.equal(names[1][0], 2); + assert.equal(names[1][1], 100); + + assert.equal(names[2][0], 3); + assert.equal(names[2][1], 100); + done() + })) + }) + + suite.test('JS array parameter', function (done) { + client.query("SELECT $1::integer[] as names", [[[1, 100], [2, 100], [3, 100]]], assert.success(function (result) { + var names = result.rows[0].names; + assert.lengthIs(names, 3); + assert.equal(names[0][0], 1); + assert.equal(names[0][1], 100); + + assert.equal(names[1][0], 2); + assert.equal(names[1][1], 100); + + assert.equal(names[2][0], 3); + assert.equal(names[2][1], 100); + release(); + pool.end(() => { + done() + }) + })) + }) + })) +})); diff --git a/test/integration/client/empty-query-tests.js b/test/integration/client/empty-query-tests.js index 443c37d67..d02c142df 100644 --- a/test/integration/client/empty-query-tests.js +++ b/test/integration/client/empty-query-tests.js @@ -13,7 +13,7 @@ suite.test("empty query message handling", function(done) { suite.test('callback supported', function(done) { const client = helper.client(); client.query("", function(err, result) { - assert.isNull(err); + assert(!err); assert.empty(result.rows); client.end(done) }) diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index e18cc9009..a798a6590 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -17,6 +17,26 @@ var createErorrClient = function() { const suite = new helper.Suite('error handling') +suite.test('re-using connections results in error callback', (done) => { + const client = new Client() + client.connect(() => { + client.connect(err => { + assert(err instanceof Error) + client.end(done) + }) + }) +}) + +suite.test('re-using connections results in promise rejection', (done) => { + const client = new Client() + client.connect().then(() => { + client.connect().catch(err => { + assert(err instanceof Error) + client.end().then(done) + }) + }) +}) + suite.test('query receives error on client shutdown', function(done) { var client = new Client(); client.connect(assert.success(function() { diff --git a/test/integration/client/result-metadata-tests.js b/test/integration/client/result-metadata-tests.js index bb7aeff74..5b683a3ad 100644 --- a/test/integration/client/result-metadata-tests.js +++ b/test/integration/client/result-metadata-tests.js @@ -5,21 +5,21 @@ var pg = helper.pg; const pool = new pg.Pool() new helper.Suite().test('should return insert metadata', function() { pool.connect(assert.calls(function(err, client, done) { - assert.isNull(err); + assert(!err); helper.versionGTE(client, '9.0.0', assert.success(function(hasRowCount) { client.query("CREATE TEMP TABLE zugzug(name varchar(10))", assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.oid, null); assert.equal(result.command, 'CREATE'); var q = client.query("INSERT INTO zugzug(name) VALUES('more work?')", assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.command, "INSERT"); assert.equal(result.rowCount, 1); client.query('SELECT * FROM zugzug', assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); if(hasRowCount) assert.equal(result.rowCount, 1); assert.equal(result.command, 'SELECT'); done(); diff --git a/test/integration/client/timezone-tests.js b/test/integration/client/timezone-tests.js index c1baa7982..1f0e06989 100644 --- a/test/integration/client/timezone-tests.js +++ b/test/integration/client/timezone-tests.js @@ -11,11 +11,11 @@ const pool = new helper.pg.Pool() const suite = new helper.Suite() pool.connect(function (err, client, done) { - assert.isNull(err); + assert(!err); suite.test('timestamp without time zone', function (cb) { client.query("SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS \"val\"", [date], function (err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows[0].val.getTime(), date.getTime()); cb() }) @@ -23,7 +23,7 @@ pool.connect(function (err, client, done) { suite.test('timestamp with time zone', function (cb) { client.query("SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS \"val\"", [date], function (err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows[0].val.getTime(), date.getTime()); done(); diff --git a/test/integration/client/transaction-tests.js b/test/integration/client/transaction-tests.js index c9af7eabb..4668a427f 100644 --- a/test/integration/client/transaction-tests.js +++ b/test/integration/client/transaction-tests.js @@ -15,7 +15,7 @@ client.connect(assert.success(function () { suite.test('name should not exist in the database', function (done) { client.query(getZed, assert.calls(function (err, result) { - assert.isNull(err); + assert(!err); assert.empty(result.rows); done() })) @@ -23,14 +23,14 @@ client.connect(assert.success(function () { suite.test('can insert name', (done) => { client.query("INSERT INTO person(name, age) VALUES($1, $2)", ['Zed', 270], assert.calls(function (err, result) { - assert.isNull(err) + assert(!err) done() })); }) suite.test('name should exist in the database', function (done) { client.query(getZed, assert.calls(function (err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows[0].name, 'Zed'); done() })) @@ -42,7 +42,7 @@ client.connect(assert.success(function () { suite.test('name should not exist in the database', function (done) { client.query(getZed, assert.calls(function (err, result) { - assert.isNull(err); + assert(!err); assert.empty(result.rows); client.end(done) })) diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index 080dd9ada..2aaffbc44 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -8,14 +8,14 @@ var testForTypeCoercion = function (type) { const pool = new pg.Pool() suite.test(`test type coercion ${type.name}`, (cb) => { pool.connect(function (err, client, done) { - assert.isNull(err); + assert(!err); client.query("create temp table test_type(col " + type.name + ")", assert.calls(function (err, result) { - assert.isNull(err); + assert(!err); type.values.forEach(function (val) { var insertQuery = client.query('insert into test_type(col) VALUES($1)', [val], assert.calls(function (err, result) { - assert.isNull(err); + assert(!err); })); var query = client.query(new pg.Query({ @@ -152,11 +152,11 @@ suite.test('selecting nulls', cb => { pool.connect(assert.calls(function (err, client, done) { assert.ifError(err); client.query('select null as res;', assert.calls(function (err, res) { - assert.isNull(err); + assert(!err); assert.strictEqual(res.rows[0].res, null) })) client.query('select 7 <> $1 as res;', [null], function (err, res) { - assert.isNull(err); + assert(!err); assert.strictEqual(res.rows[0].res, null); done(); pool.end(cb) diff --git a/test/integration/connection-pool/idle-timeout-tests.js b/test/integration/connection-pool/idle-timeout-tests.js index 0531ae80a..63956b641 100644 --- a/test/integration/connection-pool/idle-timeout-tests.js +++ b/test/integration/connection-pool/idle-timeout-tests.js @@ -6,7 +6,7 @@ new helper.Suite().test('idle timeout', function () { const config = Object.assign({}, helper.config, { idleTimeoutMillis: 50 }) const pool = new helper.pg.Pool(config) pool.connect(assert.calls(function (err, client, done) { - assert.isNull(err); + assert(!err); client.query('SELECT NOW()'); done(); })); diff --git a/test/integration/connection-pool/test-helper.js b/test/integration/connection-pool/test-helper.js index 85ecd899d..2fde015ee 100644 --- a/test/integration/connection-pool/test-helper.js +++ b/test/integration/connection-pool/test-helper.js @@ -13,7 +13,7 @@ helper.testPoolSize = function (max) { for (var i = 0; i < max; i++) { pool.connect(function (err, client, done) { - assert.isNull(err); + assert(!err); client.query("SELECT * FROM NOW()") client.query("select generate_series(0, 25)", function (err, result) { assert.equal(result.rows.length, 26) diff --git a/test/integration/gh-issues/131-tests.js b/test/integration/gh-issues/131-tests.js index 164f94e90..f56834e26 100644 --- a/test/integration/gh-issues/131-tests.js +++ b/test/integration/gh-issues/131-tests.js @@ -7,7 +7,7 @@ var suite = new helper.Suite() suite.test('parsing array decimal results', function (done) { const pool = new pg.Pool() pool.connect(assert.calls(function (err, client, release) { - assert.isNull(err); + assert(!err); client.query("CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])"); client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log); client.query('SELECT decimals FROM why', assert.success(function (result) { diff --git a/test/native/callback-api-tests.js b/test/native/callback-api-tests.js index fa57dbdea..a0a77795b 100644 --- a/test/native/callback-api-tests.js +++ b/test/native/callback-api-tests.js @@ -8,11 +8,11 @@ suite.test('fires callback with results', function(done) { var client = new Client(helper.config); client.connect(); client.query('SELECT 1 as num', assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows[0].num, 1); assert.strictEqual(result.rowCount, 1); client.query('SELECT * FROM person WHERE name = $1', ['Brian'], assert.calls(function(err, result) { - assert.isNull(err); + assert(!err); assert.equal(result.rows[0].name, 'Brian'); client.end(done); })) diff --git a/test/unit/connection-parameters/creation-tests.js b/test/unit/connection-parameters/creation-tests.js index 36e17a934..f0268a137 100644 --- a/test/unit/connection-parameters/creation-tests.js +++ b/test/unit/connection-parameters/creation-tests.js @@ -122,7 +122,7 @@ test('libpq connection string building', function() { } var subject = new ConnectionParameters(config); subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert.isNull(err); + assert(!err); var parts = constring.split(" "); checkForPart(parts, "user='brian'"); checkForPart(parts, "password='xyz'"); @@ -141,7 +141,7 @@ test('libpq connection string building', function() { }; var subject = new ConnectionParameters(config); subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert.isNull(err); + assert(!err); var parts = constring.split(" "); checkForPart(parts, "user='brian'"); checkForPart(parts, "hostaddr='127.0.0.1'"); @@ -171,7 +171,7 @@ test('libpq connection string building', function() { }; var subject = new ConnectionParameters(config); subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert.isNull(err); + assert(!err); var parts = constring.split(" "); checkForPart(parts, "user='brian'"); checkForPart(parts, "host='/tmp/'"); @@ -187,7 +187,7 @@ test('libpq connection string building', function() { }; var subject = new ConnectionParameters(config); subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert.isNull(err); + assert(!err); var parts = constring.split(" "); checkForPart(parts, "user='not\\\\brian'"); checkForPart(parts, "password='bad\\'chars'"); @@ -200,7 +200,7 @@ test('libpq connection string building', function() { } var subject = new ConnectionParameters(config); subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert.isNull(err); + assert(!err); var parts = constring.split(" "); checkForPart(parts, "client_encoding='utf-8'"); })); From f7de9ce820715146644c076f31959b68a323cf30 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 15 Jul 2017 11:14:15 -0500 Subject: [PATCH 0265/1037] Non-array query values cause query to end with an error. This is a small change and is _kinda_ backwards compatible since the old behavior was to throw an error, but if someone was relying on anything with `.map` working as values it would break them, so it's in a major semver bump. --- lib/native/query.js | 7 +++- lib/query.js | 6 +++ .../client/error-handling-tests.js | 13 ++++++ test/native/error-tests.js | 41 ------------------- 4 files changed, 24 insertions(+), 43 deletions(-) delete mode 100644 test/native/error-tests.js diff --git a/lib/native/query.js b/lib/native/query.js index f9dacfa19..a35e53040 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -146,8 +146,11 @@ NativeQuery.prototype.submit = function(client) { client.namedQueries[self.name] = true; return self.native.execute(self.name, values, after); }); - } - else if(this.values) { + } else if(this.values) { + if (!Array.isArray(this.values)) { + const err = new Error('Query values must be an array') + return after(err) + } var vals = this.values.map(utils.prepareValue); client.native.query(this.text, vals, after); } else { diff --git a/lib/query.js b/lib/query.js index a8e76547d..26b930fbc 100644 --- a/lib/query.js +++ b/lib/query.js @@ -133,6 +133,12 @@ Query.prototype.submit = function(connection) { connection.emit('readyForQuery') return } + if (this.values && !Array.isArray(this.values)) { + const err = new Error('Query values must be an array') + connection.emit('error', err) + connection.emit('readyForQuery') + return + } if(this.requiresPreparation()) { this.prepare(connection); } else { diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index a798a6590..e4d779031 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -17,6 +17,19 @@ var createErorrClient = function() { const suite = new helper.Suite('error handling') +suite.test('sending non-array argument as values causes an error callback', (done) => { + const client = new Client() + client.connect(() => { + client.query('select $1::text as name', 'foo', (err) => { + assert(err instanceof Error) + client.query('SELECT $1::text as name', ['foo'], (err, res) => { + assert.equal(res.rows[0].name, 'foo') + client.end(done) + }) + }) + }) +}) + suite.test('re-using connections results in error callback', (done) => { const client = new Client() client.connect(() => { diff --git a/test/native/error-tests.js b/test/native/error-tests.js deleted file mode 100644 index a6f876449..000000000 --- a/test/native/error-tests.js +++ /dev/null @@ -1,41 +0,0 @@ -"use strict"; -var helper = require(__dirname + "/../test-helper"); -var Client = require(__dirname + "/../../lib/native"); - - -var connect = function(callback) { - var client = new Client(helper.config); - client.connect(); - assert.emits(client, 'connect', function() { - callback(client); - }) -} - -test('parameterized query with non-array for second value', function() { - test('inline', function() { - connect(function(client) { - client.end(); - assert.emits(client, 'end', function() { - assert.throws(function() { - client.query("SELECT *", "LKSDJF") - }); - }); - }); - }); - - test('config', function() { - connect(function(client) { - client.end(); - assert.emits(client, 'end', function() { - assert.throws(function() { - client.query({ - text: "SELECT *", - values: "ALSDKFJ" - }); - }); - }); - }); - }); -}); - - From 8798e50ad3493fc1e688d41f2c7985be7ff24592 Mon Sep 17 00:00:00 2001 From: Brian C Date: Sat, 15 Jul 2017 12:05:58 -0500 Subject: [PATCH 0266/1037] Re-enable eslint with standard format (#1367) * Work on converting lib to standard * Finish updating lib * Finish linting lib * Format test files * Add .eslintrc with standard format * Supply full path to eslint bin * Move lint command to package.json * Add eslint as dev dependency --- .eslintrc | 6 + .jshintrc | 5 - Makefile | 9 +- lib/client.js | 422 ++++--- lib/connection-parameters.js | 161 ++- lib/connection.js | 1008 ++++++++--------- lib/defaults.js | 56 +- lib/index.js | 73 +- lib/native/client.js | 306 ++--- lib/native/index.js | 2 +- lib/native/query.js | 229 ++-- lib/native/result.js | 36 +- lib/query.js | 278 ++--- lib/result.js | 166 +-- lib/type-overrides.js | 46 +- lib/utils.js | 160 ++- package.json | 10 +- script/create-test-tables.js | 78 +- script/dump-db-types.js | 27 +- script/list-db-types.js | 12 +- test/buffer-list.js | 106 +- test/cli.js | 38 +- test/integration/client/api-tests.js | 266 ++--- test/integration/client/appname-tests.js | 146 ++- test/integration/client/array-tests.js | 176 +-- .../client/big-simple-query-tests.js | 97 +- .../integration/client/configuration-tests.js | 33 +- test/integration/client/custom-types-tests.js | 12 +- test/integration/client/empty-query-tests.js | 29 +- .../client/error-handling-tests.js | 172 ++- test/integration/client/huge-numeric-tests.js | 30 +- .../client/json-type-parsing-tests.js | 40 +- .../client/network-partition-tests.js | 10 +- test/integration/client/no-data-tests.js | 30 +- .../integration/client/no-row-result-tests.js | 38 +- test/integration/client/notice-tests.js | 46 +- test/integration/client/parse-int-8-tests.js | 50 +- .../client/prepared-statement-tests.js | 138 ++- test/integration/client/promise-api-tests.js | 7 +- .../client/query-as-promise-tests.js | 8 +- .../client/query-column-names-tests.js | 20 +- ...error-handling-prepared-statement-tests.js | 125 +- .../client/quick-disconnect-tests.js | 12 +- .../client/result-metadata-tests.js | 54 +- .../client/results-as-array-tests.js | 46 +- .../row-description-on-results-tests.js | 66 +- test/integration/client/simple-query-tests.js | 146 ++- test/integration/client/ssl-tests.js | 26 +- test/integration/client/test-helper.js | 6 +- test/integration/client/timezone-tests.js | 36 +- test/integration/client/transaction-tests.js | 47 +- .../integration/client/type-coercion-tests.js | 131 ++- .../client/type-parser-override-tests.js | 58 +- .../connection-pool-size-tests.js | 12 +- .../connection-pool/error-tests.js | 48 +- .../connection-pool/idle-timeout-tests.js | 15 +- .../connection-pool/native-instance-tests.js | 6 +- .../connection-pool/test-helper.js | 19 +- .../connection-pool/yield-support-tests.js | 4 +- .../connection/bound-command-tests.js | 107 +- test/integration/connection/copy-tests.js | 48 +- .../connection/notification-tests.js | 30 +- test/integration/connection/query-tests.js | 48 +- test/integration/connection/test-helper.js | 74 +- test/integration/domain-tests.js | 2 +- test/integration/gh-issues/130-tests.js | 38 +- test/integration/gh-issues/131-tests.js | 20 +- test/integration/gh-issues/199-tests.js | 28 +- test/integration/gh-issues/507-tests.js | 12 +- test/integration/gh-issues/600-tests.js | 91 +- test/integration/gh-issues/675-tests.js | 42 +- test/integration/gh-issues/787-tests.js | 16 +- test/integration/gh-issues/882-tests.js | 18 +- test/integration/test-helper.js | 45 +- test/native/callback-api-tests.js | 52 +- test/native/evented-api-tests.js | 122 +- test/native/missing-native.js | 10 +- test/native/native-vs-js-error-tests.js | 24 +- test/native/stress-tests.js | 80 +- test/suite.js | 16 +- test/test-buffers.js | 156 +-- test/test-helper.js | 300 +++-- test/unit/client/cleartext-password-tests.js | 30 +- test/unit/client/configuration-tests.js | 254 ++--- test/unit/client/early-disconnect-tests.js | 28 +- test/unit/client/escape-tests.js | 78 +- test/unit/client/md5-password-tests.js | 42 +- test/unit/client/notification-tests.js | 15 +- test/unit/client/prepared-statement-tests.js | 142 +-- test/unit/client/query-queue-tests.js | 90 +- test/unit/client/result-metadata-tests.js | 43 +- test/unit/client/simple-query-tests.js | 228 ++-- ...tream-and-query-error-interaction-tests.js | 52 +- test/unit/client/test-helper.js | 34 +- .../unit/client/throw-in-type-parser-tests.js | 101 +- .../connection-parameters/creation-tests.js | 375 +++--- .../environment-variable-tests.js | 198 ++-- test/unit/connection/error-tests.js | 58 +- test/unit/connection/inbound-parser-tests.js | 573 +++++----- .../unit/connection/outbound-sending-tests.js | 241 ++-- test/unit/connection/startup-tests.js | 142 ++- test/unit/connection/test-helper.js | 4 +- test/unit/test-helper.js | 49 +- test/unit/utils-tests.js | 253 ++--- 104 files changed, 4878 insertions(+), 4970 deletions(-) create mode 100644 .eslintrc delete mode 100644 .jshintrc diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 000000000..6f96eccce --- /dev/null +++ b/.eslintrc @@ -0,0 +1,6 @@ +{ + "extends": "standard", + "rules": { + "no-new-func": "off" + } +} diff --git a/.jshintrc b/.jshintrc deleted file mode 100644 index c6c11efc5..000000000 --- a/.jshintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "trailing": true, - "indent": 2, - "evil": true -} diff --git a/Makefile b/Makefile index ad8ed3de9..f710d846f 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ params := $(connectionString) node-command := xargs -n 1 -I file node file $(params) .PHONY : test test-connection test-integration bench test-native \ - jshint publish test-missing-native update-npm + lint publish test-missing-native update-npm all: npm install @@ -17,7 +17,7 @@ help: test: test-unit -test-all: jshint test-missing-native test-unit test-integration test-native +test-all: lint test-missing-native test-unit test-integration test-native update-npm: @@ -60,5 +60,6 @@ test-binary: test-connection test-pool: @find test/integration/connection-pool -name "*.js" | $(node-command) binary -jshint: - @echo "***Starting jshint***" +lint: + @echo "***Starting lint***" + eslint lib diff --git a/lib/client.js b/lib/client.js index 25a9d66c0..d0052604e 100644 --- a/lib/client.js +++ b/lib/client.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,54 +7,54 @@ * README.md file in the root directory of this source tree. */ -var EventEmitter = require('events').EventEmitter; -var util = require('util'); +var EventEmitter = require('events').EventEmitter +var util = require('util') var utils = require('./utils') -var pgPass = require('pgpass'); -var TypeOverrides = require('./type-overrides'); +var pgPass = require('pgpass') +var TypeOverrides = require('./type-overrides') -var ConnectionParameters = require('./connection-parameters'); -var Query = require('./query'); -var defaults = require('./defaults'); -var Connection = require('./connection'); +var ConnectionParameters = require('./connection-parameters') +var Query = require('./query') +var defaults = require('./defaults') +var Connection = require('./connection') -var Client = function(config) { - EventEmitter.call(this); +var Client = function (config) { + EventEmitter.call(this) - this.connectionParameters = new ConnectionParameters(config); - this.user = this.connectionParameters.user; - this.database = this.connectionParameters.database; - this.port = this.connectionParameters.port; - this.host = this.connectionParameters.host; - this.password = this.connectionParameters.password; - this.replication = this.connectionParameters.replication; + this.connectionParameters = new ConnectionParameters(config) + this.user = this.connectionParameters.user + this.database = this.connectionParameters.database + this.port = this.connectionParameters.port + this.host = this.connectionParameters.host + this.password = this.connectionParameters.password + this.replication = this.connectionParameters.replication - var c = config || {}; + var c = config || {} - this._types = new TypeOverrides(c.types); - this._ending = false; - this._connecting = false; - this._connected = false; - this._connectionError = false; + this._types = new TypeOverrides(c.types) + this._ending = false + this._connecting = false + this._connected = false + this._connectionError = false this.connection = c.connection || new Connection({ stream: c.stream, ssl: this.connectionParameters.ssl, keepAlive: c.keepAlive || false - }); - this.queryQueue = []; - this.binary = c.binary || defaults.binary; - this.encoding = 'utf8'; - this.processID = null; - this.secretKey = null; - this.ssl = this.connectionParameters.ssl || false; -}; - -util.inherits(Client, EventEmitter); - -Client.prototype.connect = function(callback) { - var self = this; - var con = this.connection; + }) + this.queryQueue = [] + this.binary = c.binary || defaults.binary + this.encoding = 'utf8' + this.processID = null + this.secretKey = null + this.ssl = this.connectionParameters.ssl || false +} + +util.inherits(Client, EventEmitter) + +Client.prototype.connect = function (callback) { + var self = this + var con = this.connection if (this._connecting || this._connected) { const err = new Error('Client has already been connected. You cannot reuse a client.') if (callback) { @@ -63,64 +63,63 @@ Client.prototype.connect = function(callback) { } return Promise.reject(err) } - this._connecting = true; + this._connecting = true - if(this.host && this.host.indexOf('/') === 0) { - con.connect(this.host + '/.s.PGSQL.' + this.port); + if (this.host && this.host.indexOf('/') === 0) { + con.connect(this.host + '/.s.PGSQL.' + this.port) } else { - con.connect(this.port, this.host); + con.connect(this.port, this.host) } - - //once connection is established send startup message - con.on('connect', function() { - if(self.ssl) { - con.requestSsl(); + // once connection is established send startup message + con.on('connect', function () { + if (self.ssl) { + con.requestSsl() } else { - con.startup(self.getStartupConf()); + con.startup(self.getStartupConf()) } - }); + }) - con.on('sslconnect', function() { - con.startup(self.getStartupConf()); - }); + con.on('sslconnect', function () { + con.startup(self.getStartupConf()) + }) - function checkPgPass(cb) { - return function(msg) { - if (null !== self.password) { - cb(msg); + function checkPgPass (cb) { + return function (msg) { + if (self.password !== null) { + cb(msg) } else { - pgPass(self.connectionParameters, function(pass){ + pgPass(self.connectionParameters, function (pass) { if (undefined !== pass) { - self.connectionParameters.password = self.password = pass; + self.connectionParameters.password = self.password = pass } - cb(msg); - }); + cb(msg) + }) } - }; + } } - //password request handling - con.on('authenticationCleartextPassword', checkPgPass(function() { - con.password(self.password); - })); + // password request handling + con.on('authenticationCleartextPassword', checkPgPass(function () { + con.password(self.password) + })) - //password request handling - con.on('authenticationMD5Password', checkPgPass(function(msg) { - var inner = utils.md5(self.password + self.user); - var outer = utils.md5(Buffer.concat([Buffer.from(inner), msg.salt])); - var md5password = "md5" + outer; - con.password(md5password); - })); + // password request handling + con.on('authenticationMD5Password', checkPgPass(function (msg) { + var inner = utils.md5(self.password + self.user) + var outer = utils.md5(Buffer.concat([Buffer.from(inner), msg.salt])) + var md5password = 'md5' + outer + con.password(md5password) + })) - con.once('backendKeyData', function(msg) { - self.processID = msg.processID; - self.secretKey = msg.secretKey; - }); + con.once('backendKeyData', function (msg) { + self.processID = msg.processID + self.secretKey = msg.secretKey + }) const connectingErrorHandler = (err) => { if (this._connectionError) { - return; + return } this._connectionError = true if (callback) { @@ -130,50 +129,50 @@ Client.prototype.connect = function(callback) { } const connectedErrorHandler = (err) => { - if(this.activeQuery) { - var activeQuery = self.activeQuery; - this.activeQuery = null; - return activeQuery.handleError(err, con); + if (this.activeQuery) { + var activeQuery = self.activeQuery + this.activeQuery = null + return activeQuery.handleError(err, con) } this.emit('error', err) } con.on('error', connectingErrorHandler) - //hook up query handling events to connection - //after the connection initially becomes ready for queries - con.once('readyForQuery', function() { - self._connecting = false; - self._connected = true; - self._attachListeners(con); - con.removeListener('error', connectingErrorHandler); + // hook up query handling events to connection + // after the connection initially becomes ready for queries + con.once('readyForQuery', function () { + self._connecting = false + self._connected = true + self._attachListeners(con) + con.removeListener('error', connectingErrorHandler) con.on('error', connectedErrorHandler) - //process possible callback argument to Client#connect + // process possible callback argument to Client#connect if (callback) { - callback(null, self); - //remove callback for proper error handling - //after the connect event - callback = null; + callback(null, self) + // remove callback for proper error handling + // after the connect event + callback = null } - self.emit('connect'); - }); - - con.on('readyForQuery', function() { - var activeQuery = self.activeQuery; - self.activeQuery = null; - self.readyForQuery = true; - if(activeQuery) { - activeQuery.handleReadyForQuery(con); + self.emit('connect') + }) + + con.on('readyForQuery', function () { + var activeQuery = self.activeQuery + self.activeQuery = null + self.readyForQuery = true + if (activeQuery) { + activeQuery.handleReadyForQuery(con) } - self._pulseQueryQueue(); - }); + self._pulseQueryQueue() + }) con.once('end', () => { - if(this.activeQuery) { - var disconnectError = new Error('Connection terminated'); - this.activeQuery.handleError(disconnectError, con); - this.activeQuery = null; + if (this.activeQuery) { + var disconnectError = new Error('Connection terminated') + this.activeQuery.handleError(disconnectError, con) + this.activeQuery = null } if (!this._ending) { // if the connection is ended without us calling .end() @@ -188,16 +187,15 @@ Client.prototype.connect = function(callback) { this.emit('error', error) } } else if (!this._connectionError) { - this.emit('error', error); + this.emit('error', error) } } - this.emit('end'); - }); - + this.emit('end') + }) - con.on('notice', function(msg) { - self.emit('notice', msg); - }); + con.on('notice', function (msg) { + self.emit('notice', msg) + }) if (!callback) { return new global.Promise((resolve, reject) => { @@ -208,216 +206,214 @@ Client.prototype.connect = function(callback) { }) }) } -}; +} -Client.prototype._attachListeners = function(con) { +Client.prototype._attachListeners = function (con) { const self = this - //delegate rowDescription to active query + // delegate rowDescription to active query con.on('rowDescription', function (msg) { - self.activeQuery.handleRowDescription(msg); - }); + self.activeQuery.handleRowDescription(msg) + }) - //delegate dataRow to active query + // delegate dataRow to active query con.on('dataRow', function (msg) { - self.activeQuery.handleDataRow(msg); - }); + self.activeQuery.handleDataRow(msg) + }) - //delegate portalSuspended to active query + // delegate portalSuspended to active query con.on('portalSuspended', function (msg) { - self.activeQuery.handlePortalSuspended(con); - }); + self.activeQuery.handlePortalSuspended(con) + }) - //deletagate emptyQuery to active query + // deletagate emptyQuery to active query con.on('emptyQuery', function (msg) { - self.activeQuery.handleEmptyQuery(con); - }); + self.activeQuery.handleEmptyQuery(con) + }) - //delegate commandComplete to active query + // delegate commandComplete to active query con.on('commandComplete', function (msg) { - self.activeQuery.handleCommandComplete(msg, con); - }); + self.activeQuery.handleCommandComplete(msg, con) + }) - //if a prepared statement has a name and properly parses - //we track that its already been executed so we don't parse - //it again on the same client + // if a prepared statement has a name and properly parses + // we track that its already been executed so we don't parse + // it again on the same client con.on('parseComplete', function (msg) { if (self.activeQuery.name) { - con.parsedStatements[self.activeQuery.name] = true; + con.parsedStatements[self.activeQuery.name] = true } - }); + }) con.on('copyInResponse', function (msg) { - self.activeQuery.handleCopyInResponse(self.connection); - }); + self.activeQuery.handleCopyInResponse(self.connection) + }) con.on('copyData', function (msg) { - self.activeQuery.handleCopyData(msg, self.connection); - }); + self.activeQuery.handleCopyData(msg, self.connection) + }) con.on('notification', function (msg) { - self.emit('notification', msg); - }); + self.emit('notification', msg) + }) } Client.prototype.getStartupConf = function () { - var params = this.connectionParameters; + var params = this.connectionParameters var data = { user: params.user, database: params.database - }; + } - var appName = params.application_name || params.fallback_application_name; + var appName = params.application_name || params.fallback_application_name if (appName) { - data.application_name = appName; + data.application_name = appName } if (params.replication) { - data.replication = '' + params.replication; + data.replication = '' + params.replication } - return data; -}; + return data +} Client.prototype.cancel = function (client, query) { - if (client.activeQuery == query) { - var con = this.connection; + if (client.activeQuery === query) { + var con = this.connection if (this.host && this.host.indexOf('/') === 0) { - con.connect(this.host + '/.s.PGSQL.' + this.port); + con.connect(this.host + '/.s.PGSQL.' + this.port) } else { - con.connect(this.port, this.host); + con.connect(this.port, this.host) } - //once connection is established send cancel message + // once connection is established send cancel message con.on('connect', function () { - con.cancel(client.processID, client.secretKey); - }); - } else if (client.queryQueue.indexOf(query) != -1) { - client.queryQueue.splice(client.queryQueue.indexOf(query), 1); + con.cancel(client.processID, client.secretKey) + }) + } else if (client.queryQueue.indexOf(query) !== -1) { + client.queryQueue.splice(client.queryQueue.indexOf(query), 1) } -}; +} Client.prototype.setTypeParser = function (oid, format, parseFn) { - return this._types.setTypeParser(oid, format, parseFn); -}; + return this._types.setTypeParser(oid, format, parseFn) +} Client.prototype.getTypeParser = function (oid, format) { - return this._types.getTypeParser(oid, format); -}; + return this._types.getTypeParser(oid, format) +} // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c Client.prototype.escapeIdentifier = function (str) { - - var escaped = '"'; + var escaped = '"' for (var i = 0; i < str.length; i++) { - var c = str[i]; + var c = str[i] if (c === '"') { - escaped += c + c; + escaped += c + c } else { - escaped += c; + escaped += c } } - escaped += '"'; + escaped += '"' - return escaped; -}; + return escaped +} // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c Client.prototype.escapeLiteral = function (str) { - - var hasBackslash = false; - var escaped = '\''; + var hasBackslash = false + var escaped = '\'' for (var i = 0; i < str.length; i++) { - var c = str[i]; + var c = str[i] if (c === '\'') { - escaped += c + c; + escaped += c + c } else if (c === '\\') { - escaped += c + c; - hasBackslash = true; + escaped += c + c + hasBackslash = true } else { - escaped += c; + escaped += c } } - escaped += '\''; + escaped += '\'' if (hasBackslash === true) { - escaped = ' E' + escaped; + escaped = ' E' + escaped } - return escaped; -}; + return escaped +} Client.prototype._pulseQueryQueue = function () { if (this.readyForQuery === true) { - this.activeQuery = this.queryQueue.shift(); + this.activeQuery = this.queryQueue.shift() if (this.activeQuery) { - this.readyForQuery = false; - this.hasExecuted = true; - this.activeQuery.submit(this.connection); + this.readyForQuery = false + this.hasExecuted = true + this.activeQuery.submit(this.connection) } else if (this.hasExecuted) { - this.activeQuery = null; - this.emit('drain'); + this.activeQuery = null + this.emit('drain') } } -}; +} Client.prototype.query = function (config, values, callback) { - //can take in strings, config object or query object - var query; - var result; - if (typeof config.submit == 'function') { + // can take in strings, config object or query object + var query + var result + if (typeof config.submit === 'function') { result = query = config - if (typeof values == 'function') { + if (typeof values === 'function') { query.callback = query.callback || values } } else { query = new Query(config, values, callback) if (!query.callback) { - let resolve, reject; - result = new Promise((res, rej) => { - resolve = res - reject = rej + let resolveOut, rejectOut + result = new Promise((resolve, reject) => { + resolveOut = resolve + rejectOut = reject }) - query.callback = (err, res) => err ? reject(err) : resolve(res) + query.callback = (err, res) => err ? rejectOut(err) : resolveOut(res) } } if (this.binary && !query.binary) { - query.binary = true; + query.binary = true } if (query._result) { - query._result._getTypeParser = this._types.getTypeParser.bind(this._types); + query._result._getTypeParser = this._types.getTypeParser.bind(this._types) } - this.queryQueue.push(query); - this._pulseQueryQueue(); + this.queryQueue.push(query) + this._pulseQueryQueue() return result -}; +} Client.prototype.end = function (cb) { - this._ending = true; + this._ending = true if (this.activeQuery) { // if we have an active query we need to force a disconnect // on the socket - otherwise a hung query could block end forever this.connection.stream.destroy(new Error('Connection terminated by user')) - return; + return } if (cb) { - this.connection.end(); - this.connection.once('end', cb); + this.connection.end() + this.connection.once('end', cb) } else { return new global.Promise((resolve, reject) => { this.connection.end() this.connection.once('end', resolve) }) } -}; +} // expose a Query constructor -Client.Query = Query; +Client.Query = Query -module.exports = Client; +module.exports = Client diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index a675e5856..f999d1801 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,111 +7,110 @@ * README.md file in the root directory of this source tree. */ -var url = require('url'); -var dns = require('dns'); +var dns = require('dns') -var defaults = require('./defaults'); +var defaults = require('./defaults') -var val = function(key, config, envVar) { +var val = function (key, config, envVar) { if (envVar === undefined) { - envVar = process.env[ 'PG' + key.toUpperCase() ]; + envVar = process.env[ 'PG' + key.toUpperCase() ] } else if (envVar === false) { // do nothing ... use false } else { - envVar = process.env[ envVar ]; + envVar = process.env[ envVar ] } return config[key] || envVar || - defaults[key]; -}; + defaults[key] +} -//parses a connection string -var parse = require('pg-connection-string').parse; +// parses a connection string +var parse = require('pg-connection-string').parse -var useSsl = function() { - switch(process.env.PGSSLMODE) { - case "disable": - return false; - case "prefer": - case "require": - case "verify-ca": - case "verify-full": - return true; +var useSsl = function () { + switch (process.env.PGSSLMODE) { + case 'disable': + return false + case 'prefer': + case 'require': + case 'verify-ca': + case 'verify-full': + return true } - return defaults.ssl; -}; + return defaults.ssl +} -var ConnectionParameters = function(config) { - //if a string is passed, it is a raw connection string so we parse it into a config - config = typeof config == 'string' ? parse(config) : (config || {}); - //if the config has a connectionString defined, parse IT into the config we use - //this will override other default values with what is stored in connectionString - if(config.connectionString) { - config = parse(config.connectionString); +var ConnectionParameters = function (config) { + // if a string is passed, it is a raw connection string so we parse it into a config + config = typeof config === 'string' ? parse(config) : (config || {}) + // if the config has a connectionString defined, parse IT into the config we use + // this will override other default values with what is stored in connectionString + if (config.connectionString) { + config = parse(config.connectionString) } - this.user = val('user', config); - this.database = val('database', config); - this.port = parseInt(val('port', config), 10); - this.host = val('host', config); - this.password = val('password', config); - this.binary = val('binary', config); - this.ssl = typeof config.ssl === 'undefined' ? useSsl() : config.ssl; - this.client_encoding = val("client_encoding", config); - this.replication = val("replication", config); - //a domain socket begins with '/' - this.isDomainSocket = (!(this.host||'').indexOf('/')); + this.user = val('user', config) + this.database = val('database', config) + this.port = parseInt(val('port', config), 10) + this.host = val('host', config) + this.password = val('password', config) + this.binary = val('binary', config) + this.ssl = typeof config.ssl === 'undefined' ? useSsl() : config.ssl + this.client_encoding = val('client_encoding', config) + this.replication = val('replication', config) + // a domain socket begins with '/' + this.isDomainSocket = (!(this.host || '').indexOf('/')) - this.application_name = val('application_name', config, 'PGAPPNAME'); - this.fallback_application_name = val('fallback_application_name', config, false); -}; + this.application_name = val('application_name', config, 'PGAPPNAME') + this.fallback_application_name = val('fallback_application_name', config, false) +} // Convert arg to a string, surround in single quotes, and escape single quotes and backslashes -var quoteParamValue = function(value) { - return "'" + ('' + value).replace(/\\/g, "\\\\").replace(/'/g, "\\'") + "'"; -}; +var quoteParamValue = function (value) { + return "'" + ('' + value).replace(/\\/g, '\\\\').replace(/'/g, "\\'") + "'" +} -var add = function(params, config, paramName) { - var value = config[paramName]; - if(value) { - params.push(paramName + "=" + quoteParamValue(value)); +var add = function (params, config, paramName) { + var value = config[paramName] + if (value) { + params.push(paramName + '=' + quoteParamValue(value)) } -}; +} -ConnectionParameters.prototype.getLibpqConnectionString = function(cb) { - var params = []; - add(params, this, 'user'); - add(params, this, 'password'); - add(params, this, 'port'); - add(params, this, 'application_name'); - add(params, this, 'fallback_application_name'); +ConnectionParameters.prototype.getLibpqConnectionString = function (cb) { + var params = [] + add(params, this, 'user') + add(params, this, 'password') + add(params, this, 'port') + add(params, this, 'application_name') + add(params, this, 'fallback_application_name') - var ssl = typeof this.ssl === 'object' ? this.ssl : {sslmode: this.ssl}; - add(params, ssl, 'sslmode'); - add(params, ssl, 'sslca'); - add(params, ssl, 'sslkey'); - add(params, ssl, 'sslcert'); - - if(this.database) { - params.push("dbname=" + quoteParamValue(this.database)); + var ssl = typeof this.ssl === 'object' ? this.ssl : {sslmode: this.ssl} + add(params, ssl, 'sslmode') + add(params, ssl, 'sslca') + add(params, ssl, 'sslkey') + add(params, ssl, 'sslcert') + + if (this.database) { + params.push('dbname=' + quoteParamValue(this.database)) } - if(this.replication) { - params.push("replication=" + quoteParamValue(this.replication)); + if (this.replication) { + params.push('replication=' + quoteParamValue(this.replication)) } - if(this.host) { - params.push("host=" + quoteParamValue(this.host)); + if (this.host) { + params.push('host=' + quoteParamValue(this.host)) } - if(this.isDomainSocket) { - return cb(null, params.join(' ')); + if (this.isDomainSocket) { + return cb(null, params.join(' ')) } - if(this.client_encoding) { - params.push("client_encoding=" + quoteParamValue(this.client_encoding)); + if (this.client_encoding) { + params.push('client_encoding=' + quoteParamValue(this.client_encoding)) } - dns.lookup(this.host, function(err, address) { - if(err) return cb(err, null); - params.push("hostaddr=" + quoteParamValue(address)); - return cb(null, params.join(' ')); - }); -}; + dns.lookup(this.host, function (err, address) { + if (err) return cb(err, null) + params.push('hostaddr=' + quoteParamValue(address)) + return cb(null, params.join(' ')) + }) +} -module.exports = ConnectionParameters; +module.exports = ConnectionParameters diff --git a/lib/connection.js b/lib/connection.js index 18aaf6f85..2f13803e4 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,85 +7,84 @@ * README.md file in the root directory of this source tree. */ -var net = require('net'); -var EventEmitter = require('events').EventEmitter; -var util = require('util'); - -var Writer = require('buffer-writer'); -var Reader = require('packet-reader'); - -var TEXT_MODE = 0; -var BINARY_MODE = 1; -var Connection = function(config) { - EventEmitter.call(this); - config = config || {}; - this.stream = config.stream || new net.Stream(); - this._keepAlive = config.keepAlive; - this.lastBuffer = false; - this.lastOffset = 0; - this.buffer = null; - this.offset = null; - this.encoding = 'utf8'; - this.parsedStatements = {}; - this.writer = new Writer(); - this.ssl = config.ssl || false; - this._ending = false; - this._mode = TEXT_MODE; - this._emitMessage = false; +var net = require('net') +var EventEmitter = require('events').EventEmitter +var util = require('util') + +var Writer = require('buffer-writer') +var Reader = require('packet-reader') + +var TEXT_MODE = 0 +var BINARY_MODE = 1 +var Connection = function (config) { + EventEmitter.call(this) + config = config || {} + this.stream = config.stream || new net.Stream() + this._keepAlive = config.keepAlive + this.lastBuffer = false + this.lastOffset = 0 + this.buffer = null + this.offset = null + this.encoding = 'utf8' + this.parsedStatements = {} + this.writer = new Writer() + this.ssl = config.ssl || false + this._ending = false + this._mode = TEXT_MODE + this._emitMessage = false this._reader = new Reader({ headerSize: 1, lengthPadding: -4 - }); - var self = this; - this.on('newListener', function(eventName) { - if(eventName == 'message') { - self._emitMessage = true; + }) + var self = this + this.on('newListener', function (eventName) { + if (eventName === 'message') { + self._emitMessage = true } - }); -}; + }) +} -util.inherits(Connection, EventEmitter); +util.inherits(Connection, EventEmitter) -Connection.prototype.connect = function(port, host) { - - if(this.stream.readyState === 'closed') { - this.stream.connect(port, host); - } else if(this.stream.readyState == 'open') { - this.emit('connect'); +Connection.prototype.connect = function (port, host) { + if (this.stream.readyState === 'closed') { + this.stream.connect(port, host) + } else if (this.stream.readyState === 'open') { + this.emit('connect') } - var self = this; + var self = this - this.stream.on('connect', function() { + this.stream.on('connect', function () { if (self._keepAlive) { - self.stream.setKeepAlive(true); + self.stream.setKeepAlive(true) } - self.emit('connect'); - }); - - this.stream.on('error', function(error) { - //don't raise ECONNRESET errors - they can & should be ignored - //during disconnect - if(self._ending && error.code == 'ECONNRESET') { - return; + self.emit('connect') + }) + + this.stream.on('error', function (error) { + // don't raise ECONNRESET errors - they can & should be ignored + // during disconnect + if (self._ending && error.code === 'ECONNRESET') { + return } - self.emit('error', error); - }); + self.emit('error', error) + }) - this.stream.on('close', function() { - self.emit('end'); - }); + this.stream.on('close', function () { + self.emit('end') + }) - if(!this.ssl) { - return this.attachListeners(this.stream); + if (!this.ssl) { + return this.attachListeners(this.stream) } - this.stream.once('data', function(buffer) { - var responseCode = buffer.toString('utf8'); - if(responseCode != 'S') { - return self.emit('error', new Error('The server does not support SSL connections')); + this.stream.once('data', function (buffer) { + var responseCode = buffer.toString('utf8') + if (responseCode !== 'S') { + return self.emit('error', new Error('The server does not support SSL connections')) } - var tls = require('tls'); + var tls = require('tls') self.stream = tls.connect({ socket: self.stream, servername: host, @@ -96,562 +95,553 @@ Connection.prototype.connect = function(port, host) { passphrase: self.ssl.passphrase, cert: self.ssl.cert, NPNProtocols: self.ssl.NPNProtocols - }); - self.attachListeners(self.stream); - self.emit('sslconnect'); - - self.stream.on('error', function(error){ - self.emit('error', error); - }); - }); -}; - -Connection.prototype.attachListeners = function(stream) { - var self = this; - stream.on('data', function(buff) { - self._reader.addChunk(buff); - var packet = self._reader.read(); - while(packet) { - var msg = self.parseMessage(packet); - if(self._emitMessage) { - self.emit('message', msg); + }) + self.attachListeners(self.stream) + self.emit('sslconnect') + + self.stream.on('error', function (error) { + self.emit('error', error) + }) + }) +} + +Connection.prototype.attachListeners = function (stream) { + var self = this + stream.on('data', function (buff) { + self._reader.addChunk(buff) + var packet = self._reader.read() + while (packet) { + var msg = self.parseMessage(packet) + if (self._emitMessage) { + self.emit('message', msg) } - self.emit(msg.name, msg); - packet = self._reader.read(); + self.emit(msg.name, msg) + packet = self._reader.read() } - }); - stream.on('end', function() { - self.emit('end'); - }); -}; + }) + stream.on('end', function () { + self.emit('end') + }) +} -Connection.prototype.requestSsl = function() { +Connection.prototype.requestSsl = function () { var bodyBuffer = this.writer .addInt16(0x04D2) - .addInt16(0x162F).flush(); + .addInt16(0x162F).flush() - var length = bodyBuffer.length + 4; + var length = bodyBuffer.length + 4 var buffer = new Writer() .addInt32(length) .add(bodyBuffer) - .join(); - this.stream.write(buffer); -}; + .join() + this.stream.write(buffer) +} -Connection.prototype.startup = function(config) { +Connection.prototype.startup = function (config) { var writer = this.writer .addInt16(3) .addInt16(0) - ; - Object.keys(config).forEach(function(key){ - var val = config[key]; - writer.addCString(key).addCString(val); - }); + Object.keys(config).forEach(function (key) { + var val = config[key] + writer.addCString(key).addCString(val) + }) - writer.addCString('client_encoding').addCString("'utf-8'"); + writer.addCString('client_encoding').addCString("'utf-8'") - var bodyBuffer = writer.addCString('').flush(); - //this message is sent without a code + var bodyBuffer = writer.addCString('').flush() + // this message is sent without a code - var length = bodyBuffer.length + 4; + var length = bodyBuffer.length + 4 var buffer = new Writer() .addInt32(length) .add(bodyBuffer) - .join(); - this.stream.write(buffer); -}; + .join() + this.stream.write(buffer) +} -Connection.prototype.cancel = function(processID, secretKey) { +Connection.prototype.cancel = function (processID, secretKey) { var bodyBuffer = this.writer .addInt16(1234) .addInt16(5678) .addInt32(processID) .addInt32(secretKey) - .flush(); + .flush() - var length = bodyBuffer.length + 4; + var length = bodyBuffer.length + 4 var buffer = new Writer() .addInt32(length) .add(bodyBuffer) - .join(); - this.stream.write(buffer); -}; - -Connection.prototype.password = function(password) { - //0x70 = 'p' - this._send(0x70, this.writer.addCString(password)); -}; - -Connection.prototype._send = function(code, more) { - if(!this.stream.writable) { - return false; + .join() + this.stream.write(buffer) +} + +Connection.prototype.password = function (password) { + // 0x70 = 'p' + this._send(0x70, this.writer.addCString(password)) +} + +Connection.prototype._send = function (code, more) { + if (!this.stream.writable) { + return false } - if(more === true) { - this.writer.addHeader(code); + if (more === true) { + this.writer.addHeader(code) } else { - return this.stream.write(this.writer.flush(code)); + return this.stream.write(this.writer.flush(code)) } -}; +} -Connection.prototype.query = function(text) { - //0x51 = Q - this.stream.write(this.writer.addCString(text).flush(0x51)); -}; +Connection.prototype.query = function (text) { + // 0x51 = Q + this.stream.write(this.writer.addCString(text).flush(0x51)) +} -//send parse message -//"more" === true to buffer the message until flush() is called -Connection.prototype.parse = function(query, more) { - //expect something like this: +// send parse message +// "more" === true to buffer the message until flush() is called +Connection.prototype.parse = function (query, more) { + // expect something like this: // { name: 'queryName', // text: 'select * from blah', // types: ['int8', 'bool'] } - //normalize missing query names to allow for null - query.name = query.name || ''; + // normalize missing query names to allow for null + query.name = query.name || '' if (query.name.length > 63) { - console.error('Warning! Postgres only supports 63 characters for query names.'); - console.error('You supplied', query.name, '(', query.name.length, ')'); - console.error('This can cause conflicts and silent errors executing queries'); + console.error('Warning! Postgres only supports 63 characters for query names.') + console.error('You supplied', query.name, '(', query.name.length, ')') + console.error('This can cause conflicts and silent errors executing queries') } - //normalize null type array - query.types = query.types || []; - var len = query.types.length; + // normalize null type array + query.types = query.types || [] + var len = query.types.length var buffer = this.writer - .addCString(query.name) //name of query - .addCString(query.text) //actual query text - .addInt16(len); - for(var i = 0; i < len; i++) { - buffer.addInt32(query.types[i]); + .addCString(query.name) // name of query + .addCString(query.text) // actual query text + .addInt16(len) + for (var i = 0; i < len; i++) { + buffer.addInt32(query.types[i]) } - var code = 0x50; - this._send(code, more); -}; - -//send bind message -//"more" === true to buffer the message until flush() is called -Connection.prototype.bind = function(config, more) { - //normalize config - config = config || {}; - config.portal = config.portal || ''; - config.statement = config.statement || ''; - config.binary = config.binary || false; - var values = config.values || []; - var len = values.length; - var useBinary = false; - for (var j = 0; j < len; j++) - useBinary |= values[j] instanceof Buffer; + var code = 0x50 + this._send(code, more) +} + +// send bind message +// "more" === true to buffer the message until flush() is called +Connection.prototype.bind = function (config, more) { + // normalize config + config = config || {} + config.portal = config.portal || '' + config.statement = config.statement || '' + config.binary = config.binary || false + var values = config.values || [] + var len = values.length + var useBinary = false + for (var j = 0; j < len; j++) { useBinary |= values[j] instanceof Buffer } var buffer = this.writer .addCString(config.portal) - .addCString(config.statement); - if (!useBinary) - buffer.addInt16(0); - else { - buffer.addInt16(len); - for (j = 0; j < len; j++) - buffer.addInt16(values[j] instanceof Buffer); + .addCString(config.statement) + if (!useBinary) { buffer.addInt16(0) } else { + buffer.addInt16(len) + for (j = 0; j < len; j++) { buffer.addInt16(values[j] instanceof Buffer) } } - buffer.addInt16(len); - for(var i = 0; i < len; i++) { - var val = values[i]; - if(val === null || typeof val === "undefined") { - buffer.addInt32(-1); + buffer.addInt16(len) + for (var i = 0; i < len; i++) { + var val = values[i] + if (val === null || typeof val === 'undefined') { + buffer.addInt32(-1) } else if (val instanceof Buffer) { - buffer.addInt32(val.length); - buffer.add(val); + buffer.addInt32(val.length) + buffer.add(val) } else { - buffer.addInt32(Buffer.byteLength(val)); - buffer.addString(val); + buffer.addInt32(Buffer.byteLength(val)) + buffer.addString(val) } } - if(config.binary) { - buffer.addInt16(1); // format codes to use binary - buffer.addInt16(1); - } - else { - buffer.addInt16(0); // format codes to use text + if (config.binary) { + buffer.addInt16(1) // format codes to use binary + buffer.addInt16(1) + } else { + buffer.addInt16(0) // format codes to use text } - //0x42 = 'B' - this._send(0x42, more); -}; - -//send execute message -//"more" === true to buffer the message until flush() is called -Connection.prototype.execute = function(config, more) { - config = config || {}; - config.portal = config.portal || ''; - config.rows = config.rows || ''; + // 0x42 = 'B' + this._send(0x42, more) +} + +// send execute message +// "more" === true to buffer the message until flush() is called +Connection.prototype.execute = function (config, more) { + config = config || {} + config.portal = config.portal || '' + config.rows = config.rows || '' this.writer .addCString(config.portal) - .addInt32(config.rows); - - //0x45 = 'E' - this._send(0x45, more); -}; - -var emptyBuffer = Buffer.alloc(0); - -Connection.prototype.flush = function() { - //0x48 = 'H' - this.writer.add(emptyBuffer); - this._send(0x48); -}; - -Connection.prototype.sync = function() { - //clear out any pending data in the writer - this.writer.flush(0); - - this.writer.add(emptyBuffer); - this._ending = true; - this._send(0x53); -}; - -const END_BUFFER = new Buffer([0x58, 0x00, 0x00, 0x00, 0x04]); -Connection.prototype.end = function() { - //0x58 = 'X' - this.writer.add(emptyBuffer); - this._ending = true; - return this.stream.write(END_BUFFER); -}; - -Connection.prototype.close = function(msg, more) { - this.writer.addCString(msg.type + (msg.name || '')); - this._send(0x43, more); -}; - -Connection.prototype.describe = function(msg, more) { - this.writer.addCString(msg.type + (msg.name || '')); - this._send(0x44, more); -}; + .addInt32(config.rows) + + // 0x45 = 'E' + this._send(0x45, more) +} + +var emptyBuffer = Buffer.alloc(0) + +Connection.prototype.flush = function () { + // 0x48 = 'H' + this.writer.add(emptyBuffer) + this._send(0x48) +} + +Connection.prototype.sync = function () { + // clear out any pending data in the writer + this.writer.flush(0) + + this.writer.add(emptyBuffer) + this._ending = true + this._send(0x53) +} + +const END_BUFFER = Buffer.from([0x58, 0x00, 0x00, 0x00, 0x04]) + +Connection.prototype.end = function () { + // 0x58 = 'X' + this.writer.add(emptyBuffer) + this._ending = true + return this.stream.write(END_BUFFER) +} + +Connection.prototype.close = function (msg, more) { + this.writer.addCString(msg.type + (msg.name || '')) + this._send(0x43, more) +} + +Connection.prototype.describe = function (msg, more) { + this.writer.addCString(msg.type + (msg.name || '')) + this._send(0x44, more) +} Connection.prototype.sendCopyFromChunk = function (chunk) { - this.stream.write(this.writer.add(chunk).flush(0x64)); -}; + this.stream.write(this.writer.add(chunk).flush(0x64)) +} Connection.prototype.endCopyFrom = function () { - this.stream.write(this.writer.add(emptyBuffer).flush(0x63)); -}; + this.stream.write(this.writer.add(emptyBuffer).flush(0x63)) +} Connection.prototype.sendCopyFail = function (msg) { - //this.stream.write(this.writer.add(emptyBuffer).flush(0x66)); - this.writer.addCString(msg); - this._send(0x66); -}; - -var Message = function(name, length) { - this.name = name; - this.length = length; -}; - -Connection.prototype.parseMessage = function(buffer) { + // this.stream.write(this.writer.add(emptyBuffer).flush(0x66)); + this.writer.addCString(msg) + this._send(0x66) +} - this.offset = 0; - var length = buffer.length + 4; - switch(this._reader.header) - { +var Message = function (name, length) { + this.name = name + this.length = length +} - case 0x52: //R - return this.parseR(buffer, length); +Connection.prototype.parseMessage = function (buffer) { + this.offset = 0 + var length = buffer.length + 4 + switch (this._reader.header) { + case 0x52: // R + return this.parseR(buffer, length) - case 0x53: //S - return this.parseS(buffer, length); + case 0x53: // S + return this.parseS(buffer, length) - case 0x4b: //K - return this.parseK(buffer, length); + case 0x4b: // K + return this.parseK(buffer, length) - case 0x43: //C - return this.parseC(buffer, length); + case 0x43: // C + return this.parseC(buffer, length) - case 0x5a: //Z - return this.parseZ(buffer, length); + case 0x5a: // Z + return this.parseZ(buffer, length) - case 0x54: //T - return this.parseT(buffer, length); + case 0x54: // T + return this.parseT(buffer, length) - case 0x44: //D - return this.parseD(buffer, length); + case 0x44: // D + return this.parseD(buffer, length) - case 0x45: //E - return this.parseE(buffer, length); + case 0x45: // E + return this.parseE(buffer, length) - case 0x4e: //N - return this.parseN(buffer, length); + case 0x4e: // N + return this.parseN(buffer, length) - case 0x31: //1 - return new Message('parseComplete', length); + case 0x31: // 1 + return new Message('parseComplete', length) - case 0x32: //2 - return new Message('bindComplete', length); + case 0x32: // 2 + return new Message('bindComplete', length) - case 0x33: //3 - return new Message('closeComplete', length); + case 0x33: // 3 + return new Message('closeComplete', length) - case 0x41: //A - return this.parseA(buffer, length); + case 0x41: // A + return this.parseA(buffer, length) - case 0x6e: //n - return new Message('noData', length); + case 0x6e: // n + return new Message('noData', length) - case 0x49: //I - return new Message('emptyQuery', length); + case 0x49: // I + return new Message('emptyQuery', length) - case 0x73: //s - return new Message('portalSuspended', length); + case 0x73: // s + return new Message('portalSuspended', length) - case 0x47: //G - return this.parseG(buffer, length); + case 0x47: // G + return this.parseG(buffer, length) - case 0x48: //H - return this.parseH(buffer, length); + case 0x48: // H + return this.parseH(buffer, length) - case 0x57: //W - return new Message('replicationStart', length); + case 0x57: // W + return new Message('replicationStart', length) - case 0x63: //c - return new Message('copyDone', length); + case 0x63: // c + return new Message('copyDone', length) - case 0x64: //d - return this.parsed(buffer, length); + case 0x64: // d + return this.parsed(buffer, length) } -}; - -Connection.prototype.parseR = function(buffer, length) { - var code = 0; - var msg = new Message('authenticationOk', length); - if(msg.length === 8) { - code = this.parseInt32(buffer); - if(code === 3) { - msg.name = 'authenticationCleartextPassword'; +} + +Connection.prototype.parseR = function (buffer, length) { + var code = 0 + var msg = new Message('authenticationOk', length) + if (msg.length === 8) { + code = this.parseInt32(buffer) + if (code === 3) { + msg.name = 'authenticationCleartextPassword' } - return msg; + return msg } - if(msg.length === 12) { - code = this.parseInt32(buffer); - if(code === 5) { //md5 required - msg.name = 'authenticationMD5Password'; - msg.salt = Buffer.alloc(4); - buffer.copy(msg.salt, 0, this.offset, this.offset + 4); - this.offset += 4; - return msg; + if (msg.length === 12) { + code = this.parseInt32(buffer) + if (code === 5) { // md5 required + msg.name = 'authenticationMD5Password' + msg.salt = Buffer.alloc(4) + buffer.copy(msg.salt, 0, this.offset, this.offset + 4) + this.offset += 4 + return msg } } - throw new Error("Unknown authenticationOk message type" + util.inspect(msg)); -}; - -Connection.prototype.parseS = function(buffer, length) { - var msg = new Message('parameterStatus', length); - msg.parameterName = this.parseCString(buffer); - msg.parameterValue = this.parseCString(buffer); - return msg; -}; - -Connection.prototype.parseK = function(buffer, length) { - var msg = new Message('backendKeyData', length); - msg.processID = this.parseInt32(buffer); - msg.secretKey = this.parseInt32(buffer); - return msg; -}; - -Connection.prototype.parseC = function(buffer, length) { - var msg = new Message('commandComplete', length); - msg.text = this.parseCString(buffer); - return msg; -}; - -Connection.prototype.parseZ = function(buffer, length) { - var msg = new Message('readyForQuery', length); - msg.name = 'readyForQuery'; - msg.status = this.readString(buffer, 1); - return msg; -}; - -var ROW_DESCRIPTION = 'rowDescription'; -Connection.prototype.parseT = function(buffer, length) { - var msg = new Message(ROW_DESCRIPTION, length); - msg.fieldCount = this.parseInt16(buffer); - var fields = []; - for(var i = 0; i < msg.fieldCount; i++){ - fields.push(this.parseField(buffer)); + throw new Error('Unknown authenticationOk message type' + util.inspect(msg)) +} + +Connection.prototype.parseS = function (buffer, length) { + var msg = new Message('parameterStatus', length) + msg.parameterName = this.parseCString(buffer) + msg.parameterValue = this.parseCString(buffer) + return msg +} + +Connection.prototype.parseK = function (buffer, length) { + var msg = new Message('backendKeyData', length) + msg.processID = this.parseInt32(buffer) + msg.secretKey = this.parseInt32(buffer) + return msg +} + +Connection.prototype.parseC = function (buffer, length) { + var msg = new Message('commandComplete', length) + msg.text = this.parseCString(buffer) + return msg +} + +Connection.prototype.parseZ = function (buffer, length) { + var msg = new Message('readyForQuery', length) + msg.name = 'readyForQuery' + msg.status = this.readString(buffer, 1) + return msg +} + +var ROW_DESCRIPTION = 'rowDescription' +Connection.prototype.parseT = function (buffer, length) { + var msg = new Message(ROW_DESCRIPTION, length) + msg.fieldCount = this.parseInt16(buffer) + var fields = [] + for (var i = 0; i < msg.fieldCount; i++) { + fields.push(this.parseField(buffer)) } - msg.fields = fields; - return msg; -}; - -var Field = function() { - this.name = null; - this.tableID = null; - this.columnID = null; - this.dataTypeID = null; - this.dataTypeSize = null; - this.dataTypeModifier = null; - this.format = null; -}; - -var FORMAT_TEXT = 'text'; -var FORMAT_BINARY = 'binary'; -Connection.prototype.parseField = function(buffer) { - var field = new Field(); - field.name = this.parseCString(buffer); - field.tableID = this.parseInt32(buffer); - field.columnID = this.parseInt16(buffer); - field.dataTypeID = this.parseInt32(buffer); - field.dataTypeSize = this.parseInt16(buffer); - field.dataTypeModifier = this.parseInt32(buffer); - if(this.parseInt16(buffer) === TEXT_MODE) { - this._mode = TEXT_MODE; - field.format = FORMAT_TEXT; + msg.fields = fields + return msg +} + +var Field = function () { + this.name = null + this.tableID = null + this.columnID = null + this.dataTypeID = null + this.dataTypeSize = null + this.dataTypeModifier = null + this.format = null +} + +var FORMAT_TEXT = 'text' +var FORMAT_BINARY = 'binary' +Connection.prototype.parseField = function (buffer) { + var field = new Field() + field.name = this.parseCString(buffer) + field.tableID = this.parseInt32(buffer) + field.columnID = this.parseInt16(buffer) + field.dataTypeID = this.parseInt32(buffer) + field.dataTypeSize = this.parseInt16(buffer) + field.dataTypeModifier = this.parseInt32(buffer) + if (this.parseInt16(buffer) === TEXT_MODE) { + this._mode = TEXT_MODE + field.format = FORMAT_TEXT } else { - this._mode = BINARY_MODE; - field.format = FORMAT_BINARY; + this._mode = BINARY_MODE + field.format = FORMAT_BINARY } - return field; -}; - -var DATA_ROW = 'dataRow'; -var DataRowMessage = function(length, fieldCount) { - this.name = DATA_ROW; - this.length = length; - this.fieldCount = fieldCount; - this.fields = []; -}; - - -//extremely hot-path code -Connection.prototype.parseD = function(buffer, length) { - var fieldCount = this.parseInt16(buffer); - var msg = new DataRowMessage(length, fieldCount); - for(var i = 0; i < fieldCount; i++) { - msg.fields.push(this._readValue(buffer)); + return field +} + +var DATA_ROW = 'dataRow' +var DataRowMessage = function (length, fieldCount) { + this.name = DATA_ROW + this.length = length + this.fieldCount = fieldCount + this.fields = [] +} + +// extremely hot-path code +Connection.prototype.parseD = function (buffer, length) { + var fieldCount = this.parseInt16(buffer) + var msg = new DataRowMessage(length, fieldCount) + for (var i = 0; i < fieldCount; i++) { + msg.fields.push(this._readValue(buffer)) } - return msg; -}; - -//extremely hot-path code -Connection.prototype._readValue = function(buffer) { - var length = this.parseInt32(buffer); - if(length === -1) return null; - if(this._mode === TEXT_MODE) { - return this.readString(buffer, length); + return msg +} + +// extremely hot-path code +Connection.prototype._readValue = function (buffer) { + var length = this.parseInt32(buffer) + if (length === -1) return null + if (this._mode === TEXT_MODE) { + return this.readString(buffer, length) } - return this.readBytes(buffer, length); -}; - -//parses error -Connection.prototype.parseE = function(buffer, length) { - var fields = {}; - var msg, item; - var input = new Message('error', length); - var fieldType = this.readString(buffer, 1); - while(fieldType != '\0') { - fields[fieldType] = this.parseCString(buffer); - fieldType = this.readString(buffer, 1); + return this.readBytes(buffer, length) +} + +// parses error +Connection.prototype.parseE = function (buffer, length) { + var fields = {} + var msg, item + var input = new Message('error', length) + var fieldType = this.readString(buffer, 1) + while (fieldType !== '\0') { + fields[fieldType] = this.parseCString(buffer) + fieldType = this.readString(buffer, 1) } - if(input.name === 'error') { + if (input.name === 'error') { // the msg is an Error instance - msg = new Error(fields.M); + msg = new Error(fields.M) for (item in input) { // copy input properties to the error - if(input.hasOwnProperty(item)) { - msg[item] = input[item]; + if (input.hasOwnProperty(item)) { + msg[item] = input[item] } } } else { // the msg is an object literal - msg = input; - msg.message = fields.M; + msg = input + msg.message = fields.M } - msg.severity = fields.S; - msg.code = fields.C; - msg.detail = fields.D; - msg.hint = fields.H; - msg.position = fields.P; - msg.internalPosition = fields.p; - msg.internalQuery = fields.q; - msg.where = fields.W; - msg.schema = fields.s; - msg.table = fields.t; - msg.column = fields.c; - msg.dataType = fields.d; - msg.constraint = fields.n; - msg.file = fields.F; - msg.line = fields.L; - msg.routine = fields.R; - return msg; -}; - -//same thing, different name -Connection.prototype.parseN = function(buffer, length) { - var msg = this.parseE(buffer, length); - msg.name = 'notice'; - return msg; -}; - -Connection.prototype.parseA = function(buffer, length) { - var msg = new Message('notification', length); - msg.processId = this.parseInt32(buffer); - msg.channel = this.parseCString(buffer); - msg.payload = this.parseCString(buffer); - return msg; -}; + msg.severity = fields.S + msg.code = fields.C + msg.detail = fields.D + msg.hint = fields.H + msg.position = fields.P + msg.internalPosition = fields.p + msg.internalQuery = fields.q + msg.where = fields.W + msg.schema = fields.s + msg.table = fields.t + msg.column = fields.c + msg.dataType = fields.d + msg.constraint = fields.n + msg.file = fields.F + msg.line = fields.L + msg.routine = fields.R + return msg +} + +// same thing, different name +Connection.prototype.parseN = function (buffer, length) { + var msg = this.parseE(buffer, length) + msg.name = 'notice' + return msg +} + +Connection.prototype.parseA = function (buffer, length) { + var msg = new Message('notification', length) + msg.processId = this.parseInt32(buffer) + msg.channel = this.parseCString(buffer) + msg.payload = this.parseCString(buffer) + return msg +} Connection.prototype.parseG = function (buffer, length) { - var msg = new Message('copyInResponse', length); - return this.parseGH(buffer, msg); -}; + var msg = new Message('copyInResponse', length) + return this.parseGH(buffer, msg) +} -Connection.prototype.parseH = function(buffer, length) { - var msg = new Message('copyOutResponse', length); - return this.parseGH(buffer, msg); -}; +Connection.prototype.parseH = function (buffer, length) { + var msg = new Message('copyOutResponse', length) + return this.parseGH(buffer, msg) +} Connection.prototype.parseGH = function (buffer, msg) { - var isBinary = buffer[this.offset] !== 0; - this.offset++; - msg.binary = isBinary; - var columnCount = this.parseInt16(buffer); - msg.columnTypes = []; - for(var i = 0; i { - var BoundPool = function(options) { - var config = { Client: Client }; + var BoundPool = function (options) { + var config = { Client: Client } for (var key in options) { - config[key] = options[key]; + config[key] = options[key] } return new Pool(config) - }; + } - util.inherits(BoundPool, Pool); - - return BoundPool; -}; + util.inherits(BoundPool, Pool) + return BoundPool +} -var PG = function(clientConstructor) { - this.defaults = defaults; - this.Client = clientConstructor; - this.Query = this.Client.Query; - this.Pool = poolFactory(this.Client); - this._pools = []; - this.Connection = Connection; - this.types = require('pg-types'); -}; +var PG = function (clientConstructor) { + this.defaults = defaults + this.Client = clientConstructor + this.Query = this.Client.Query + this.Pool = poolFactory(this.Client) + this._pools = [] + this.Connection = Connection + this.types = require('pg-types') +} -if(typeof process.env.NODE_PG_FORCE_NATIVE != 'undefined') { - module.exports = new PG(require('./native')); +if (typeof process.env.NODE_PG_FORCE_NATIVE !== 'undefined') { + module.exports = new PG(require('./native')) } else { - module.exports = new PG(Client); + module.exports = new PG(Client) - //lazy require native module...the native module may not have installed - module.exports.__defineGetter__("native", function() { - delete module.exports.native; - var native = null; + // lazy require native module...the native module may not have installed + module.exports.__defineGetter__('native', function () { + delete module.exports.native + var native = null try { - native = new PG(require('./native')); + native = new PG(require('./native')) } catch (err) { if (err.code !== 'MODULE_NOT_FOUND') { - throw err; + throw err } - console.error(err.message); + console.error(err.message) } - module.exports.native = native; - return native; - }); + module.exports.native = native + return native + }) } diff --git a/lib/native/client.js b/lib/native/client.js index d8f20fe7c..bed548ad8 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,71 +7,71 @@ * README.md file in the root directory of this source tree. */ -var Native = require('pg-native'); -var TypeOverrides = require('../type-overrides'); -var semver = require('semver'); -var pkg = require('../../package.json'); -var assert = require('assert'); -var EventEmitter = require('events').EventEmitter; -var util = require('util'); -var ConnectionParameters = require('../connection-parameters'); +var Native = require('pg-native') +var TypeOverrides = require('../type-overrides') +var semver = require('semver') +var pkg = require('../../package.json') +var assert = require('assert') +var EventEmitter = require('events').EventEmitter +var util = require('util') +var ConnectionParameters = require('../connection-parameters') -var msg = 'Version >= ' + pkg.minNativeVersion + ' of pg-native required.'; -assert(semver.gte(Native.version, pkg.minNativeVersion), msg); +var msg = 'Version >= ' + pkg.minNativeVersion + ' of pg-native required.' +assert(semver.gte(Native.version, pkg.minNativeVersion), msg) -var NativeQuery = require('./query'); +var NativeQuery = require('./query') -var Client = module.exports = function(config) { - EventEmitter.call(this); - config = config || {}; +var Client = module.exports = function (config) { + EventEmitter.call(this) + config = config || {} - this._types = new TypeOverrides(config.types); + this._types = new TypeOverrides(config.types) this.native = new Native({ types: this._types - }); - - this._queryQueue = []; - this._connected = false; - this._connecting = false; - - //keep these on the object for legacy reasons - //for the time being. TODO: deprecate all this jazz - var cp = this.connectionParameters = new ConnectionParameters(config); - this.user = cp.user; - this.password = cp.password; - this.database = cp.database; - this.host = cp.host; - this.port = cp.port; - - //a hash to hold named queries - this.namedQueries = {}; -}; - -Client.Query = NativeQuery; - -util.inherits(Client, EventEmitter); - -//connect to the backend -//pass an optional callback to be called once connected -//or with an error if there was a connection error -//if no callback is passed and there is a connection error -//the client will emit an error event. -Client.prototype.connect = function(cb) { - var self = this; - - var onError = function(err) { - if(cb) return cb(err); - return self.emit('error', err); - }; + }) + + this._queryQueue = [] + this._connected = false + this._connecting = false + + // keep these on the object for legacy reasons + // for the time being. TODO: deprecate all this jazz + var cp = this.connectionParameters = new ConnectionParameters(config) + this.user = cp.user + this.password = cp.password + this.database = cp.database + this.host = cp.host + this.port = cp.port + + // a hash to hold named queries + this.namedQueries = {} +} + +Client.Query = NativeQuery + +util.inherits(Client, EventEmitter) + +// connect to the backend +// pass an optional callback to be called once connected +// or with an error if there was a connection error +// if no callback is passed and there is a connection error +// the client will emit an error event. +Client.prototype.connect = function (cb) { + var self = this + + var onError = function (err) { + if (cb) return cb(err) + return self.emit('error', err) + } var result if (!cb) { - var resolve, reject - cb = (err) => err ? reject(err) : resolve() - result = new global.Promise(function(res, rej) { - resolve = res - reject = rej + var resolveOut, rejectOut + cb = (err) => err ? rejectOut(err) : resolveOut() + result = new global.Promise(function (resolve, reject) { + resolveOut = resolve + rejectOut = reject }) } @@ -82,145 +82,145 @@ Client.prototype.connect = function(cb) { this._connecting = true - this.connectionParameters.getLibpqConnectionString(function(err, conString) { - if(err) return onError(err); - self.native.connect(conString, function(err) { - if(err) return onError(err); + this.connectionParameters.getLibpqConnectionString(function (err, conString) { + if (err) return onError(err) + self.native.connect(conString, function (err) { + if (err) return onError(err) - //set internal states to connected - self._connected = true; + // set internal states to connected + self._connected = true - //handle connection errors from the native layer - self.native.on('error', function(err) { - //error will be handled by active query - if(self._activeQuery && self._activeQuery.state != 'end') { - return; + // handle connection errors from the native layer + self.native.on('error', function (err) { + // error will be handled by active query + if (self._activeQuery && self._activeQuery.state !== 'end') { + return } - self.emit('error', err); - }); + self.emit('error', err) + }) - self.native.on('notification', function(msg) { + self.native.on('notification', function (msg) { self.emit('notification', { channel: msg.relname, payload: msg.extra - }); - }); + }) + }) - //signal we are connected now - self.emit('connect'); - self._pulseQueryQueue(true); + // signal we are connected now + self.emit('connect') + self._pulseQueryQueue(true) - //possibly call the optional callback - if(cb) cb(); - }); - }); + // possibly call the optional callback + if (cb) cb() + }) + }) return result -}; +} -//send a query to the server -//this method is highly overloaded to take -//1) string query, optional array of parameters, optional function callback -//2) object query with { +// send a query to the server +// this method is highly overloaded to take +// 1) string query, optional array of parameters, optional function callback +// 2) object query with { // string query // optional array values, // optional function callback instead of as a separate parameter // optional string name to name & cache the query plan // optional string rowMode = 'array' for an array of results // } -Client.prototype.query = function(config, values, callback) { - if (typeof config.submit == 'function') { +Client.prototype.query = function (config, values, callback) { + if (typeof config.submit === 'function') { // accept query(new Query(...), (err, res) => { }) style - if (typeof values == 'function') { - config.callback = values; + if (typeof values === 'function') { + config.callback = values } - this._queryQueue.push(config); - this._pulseQueryQueue(); - return config; + this._queryQueue.push(config) + this._pulseQueryQueue() + return config } - var query = new NativeQuery(config, values, callback); + var query = new NativeQuery(config, values, callback) var result if (!query.callback) { - let resolve, reject; - result = new Promise((res, rej) => { - resolve = res - reject = rej + let resolveOut, rejectOut + result = new Promise((resolve, reject) => { + resolveOut = resolve + rejectOut = reject }) - query.callback = (err, res) => err ? reject(err) : resolve(res) + query.callback = (err, res) => err ? rejectOut(err) : resolveOut(res) } - this._queryQueue.push(query); - this._pulseQueryQueue(); - return result; -}; - -//disconnect from the backend server -Client.prototype.end = function(cb) { - var self = this; - if(!this._connected) { - this.once('connect', this.end.bind(this, cb)); + this._queryQueue.push(query) + this._pulseQueryQueue() + return result +} + +// disconnect from the backend server +Client.prototype.end = function (cb) { + var self = this + if (!this._connected) { + this.once('connect', this.end.bind(this, cb)) } - var result; + var result if (!cb) { var resolve, reject cb = (err) => err ? reject(err) : resolve() - result = new global.Promise(function(res, rej) { + result = new global.Promise(function (res, rej) { resolve = res reject = rej }) } - this.native.end(function() { - //send an error to the active query - if(self._hasActiveQuery()) { - var msg = 'Connection terminated'; - self._queryQueue.length = 0; - self._activeQuery.handleError(new Error(msg)); + this.native.end(function () { + // send an error to the active query + if (self._hasActiveQuery()) { + var msg = 'Connection terminated' + self._queryQueue.length = 0 + self._activeQuery.handleError(new Error(msg)) } - self.emit('end'); - if(cb) cb(); - }); + self.emit('end') + if (cb) cb() + }) return result -}; +} -Client.prototype._hasActiveQuery = function() { - return this._activeQuery && this._activeQuery.state != 'error' && this._activeQuery.state != 'end'; -}; +Client.prototype._hasActiveQuery = function () { + return this._activeQuery && this._activeQuery.state !== 'error' && this._activeQuery.state !== 'end' +} -Client.prototype._pulseQueryQueue = function(initialConnection) { - if(!this._connected) { - return; +Client.prototype._pulseQueryQueue = function (initialConnection) { + if (!this._connected) { + return } - if(this._hasActiveQuery()) { - return; + if (this._hasActiveQuery()) { + return } - var query = this._queryQueue.shift(); - if(!query) { - if(!initialConnection) { - this.emit('drain'); + var query = this._queryQueue.shift() + if (!query) { + if (!initialConnection) { + this.emit('drain') } - return; + return } - this._activeQuery = query; - query.submit(this); - var self = this; - query.once('_done', function() { - self._pulseQueryQueue(); - }); -}; - -//attempt to cancel an in-progress query -Client.prototype.cancel = function(query) { - if(this._activeQuery == query) { - this.native.cancel(function() {}); - } else if (this._queryQueue.indexOf(query) != -1) { - this._queryQueue.splice(this._queryQueue.indexOf(query), 1); + this._activeQuery = query + query.submit(this) + var self = this + query.once('_done', function () { + self._pulseQueryQueue() + }) +} + +// attempt to cancel an in-progress query +Client.prototype.cancel = function (query) { + if (this._activeQuery === query) { + this.native.cancel(function () {}) + } else if (this._queryQueue.indexOf(query) !== -1) { + this._queryQueue.splice(this._queryQueue.indexOf(query), 1) } -}; +} -Client.prototype.setTypeParser = function(oid, format, parseFn) { - return this._types.setTypeParser(oid, format, parseFn); -}; +Client.prototype.setTypeParser = function (oid, format, parseFn) { + return this._types.setTypeParser(oid, format, parseFn) +} -Client.prototype.getTypeParser = function(oid, format) { - return this._types.getTypeParser(oid, format); -}; +Client.prototype.getTypeParser = function (oid, format) { + return this._types.getTypeParser(oid, format) +} diff --git a/lib/native/index.js b/lib/native/index.js index 53f10c4aa..eead422a3 100644 --- a/lib/native/index.js +++ b/lib/native/index.js @@ -1,2 +1,2 @@ -"use strict"; +'use strict' module.exports = require('./client') diff --git a/lib/native/query.js b/lib/native/query.js index a35e53040..c1a769154 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,33 +7,33 @@ * README.md file in the root directory of this source tree. */ -var EventEmitter = require('events').EventEmitter; -var util = require('util'); -var utils = require('../utils'); -var NativeResult = require('./result'); - -var NativeQuery = module.exports = function(config, values, callback) { - EventEmitter.call(this); - config = utils.normalizeQueryConfig(config, values, callback); - this.text = config.text; - this.values = config.values; - this.name = config.name; - this.callback = config.callback; - this.state = 'new'; - this._arrayMode = config.rowMode == 'array'; - - //if the 'row' event is listened for - //then emit them as they come in - //without setting singleRowMode to true - //this has almost no meaning because libpq - //reads all rows into memory befor returning any - this._emitRowEvents = false; - this.on('newListener', function(event) { - if(event === 'row') this._emitRowEvents = true; - }.bind(this)); -}; - -util.inherits(NativeQuery, EventEmitter); +var EventEmitter = require('events').EventEmitter +var util = require('util') +var utils = require('../utils') +var NativeResult = require('./result') + +var NativeQuery = module.exports = function (config, values, callback) { + EventEmitter.call(this) + config = utils.normalizeQueryConfig(config, values, callback) + this.text = config.text + this.values = config.values + this.name = config.name + this.callback = config.callback + this.state = 'new' + this._arrayMode = config.rowMode === 'array' + + // if the 'row' event is listened for + // then emit them as they come in + // without setting singleRowMode to true + // this has almost no meaning because libpq + // reads all rows into memory befor returning any + this._emitRowEvents = false + this.on('newListener', function (event) { + if (event === 'row') this._emitRowEvents = true + }.bind(this)) +} + +util.inherits(NativeQuery, EventEmitter) var errorFieldMap = { 'sqlState': 'code', @@ -47,113 +47,112 @@ var errorFieldMap = { 'constraintName': 'constraint', 'sourceFile': 'file', 'sourceLine': 'line', - 'sourceFunction': 'routine', -}; - -NativeQuery.prototype.handleError = function(err) { - var self = this; - //copy pq error fields into the error object - var fields = self.native.pq.resultErrorFields(); - if(fields) { - for(var key in fields) { - var normalizedFieldName = errorFieldMap[key] || key; - err[normalizedFieldName] = fields[key]; + 'sourceFunction': 'routine' +} + +NativeQuery.prototype.handleError = function (err) { + var self = this + // copy pq error fields into the error object + var fields = self.native.pq.resultErrorFields() + if (fields) { + for (var key in fields) { + var normalizedFieldName = errorFieldMap[key] || key + err[normalizedFieldName] = fields[key] } } - if(self.callback) { - self.callback(err); + if (self.callback) { + self.callback(err) } else { - self.emit('error', err); + self.emit('error', err) } - self.state = 'error'; -}; - -NativeQuery.prototype.then = function(onSuccess, onFailure) { - return this._getPromise().then(onSuccess, onFailure); -}; - -NativeQuery.prototype.catch = function(callback) { - return this._getPromise().catch(callback); -}; - -NativeQuery.prototype._getPromise = function() { - if (this._promise) return this._promise; - this._promise = new Promise(function(resolve, reject) { - this._once('end', resolve); - this._once('error', reject); - }.bind(this)); - return this._promise; -}; - -NativeQuery.prototype.submit = function(client) { - this.state = 'running'; - var self = this; - this.native = client.native; - client.native.arrayMode = this._arrayMode; - - var after = function(err, rows) { - client.native.arrayMode = false; - setImmediate(function() { - self.emit('_done'); - }); - - //handle possible query error - if(err) { - return self.handleError(err); + self.state = 'error' +} + +NativeQuery.prototype.then = function (onSuccess, onFailure) { + return this._getPromise().then(onSuccess, onFailure) +} + +NativeQuery.prototype.catch = function (callback) { + return this._getPromise().catch(callback) +} + +NativeQuery.prototype._getPromise = function () { + if (this._promise) return this._promise + this._promise = new Promise(function (resolve, reject) { + this._once('end', resolve) + this._once('error', reject) + }.bind(this)) + return this._promise +} + +NativeQuery.prototype.submit = function (client) { + this.state = 'running' + var self = this + this.native = client.native + client.native.arrayMode = this._arrayMode + + var after = function (err, rows) { + client.native.arrayMode = false + setImmediate(function () { + self.emit('_done') + }) + + // handle possible query error + if (err) { + return self.handleError(err) } - var result = new NativeResult(); - result.addCommandComplete(self.native.pq); - result.rows = rows; + var result = new NativeResult() + result.addCommandComplete(self.native.pq) + result.rows = rows - //emit row events for each row in the result - if(self._emitRowEvents) { - rows.forEach(function(row) { - self.emit('row', row, result); - }); + // emit row events for each row in the result + if (self._emitRowEvents) { + rows.forEach(function (row) { + self.emit('row', row, result) + }) } - - //handle successful result - self.state = 'end'; - self.emit('end', result); - if(self.callback) { - self.callback(null, result); + // handle successful result + self.state = 'end' + self.emit('end', result) + if (self.callback) { + self.callback(null, result) } - }; + } - if(process.domain) { - after = process.domain.bind(after); + if (process.domain) { + after = process.domain.bind(after) } - //named query - if(this.name) { + // named query + if (this.name) { if (this.name.length > 63) { - console.error('Warning! Postgres only supports 63 characters for query names.'); - console.error('You supplied', this.name, '(', this.name.length, ')'); - console.error('This can cause conflicts and silent errors executing queries'); + console.error('Warning! Postgres only supports 63 characters for query names.') + console.error('You supplied', this.name, '(', this.name.length, ')') + console.error('This can cause conflicts and silent errors executing queries') } - var values = (this.values||[]).map(utils.prepareValue); + var values = (this.values || []).map(utils.prepareValue) - //check if the client has already executed this named query - //if so...just execute it again - skip the planning phase - if(client.namedQueries[this.name]) { - return client.native.execute(this.name, values, after); + // check if the client has already executed this named query + // if so...just execute it again - skip the planning phase + if (client.namedQueries[this.name]) { + return client.native.execute(this.name, values, after) } - //plan the named query the first time, then execute it - return client.native.prepare(this.name, this.text, values.length, function(err) { - if(err) return after(err); - client.namedQueries[self.name] = true; - return self.native.execute(self.name, values, after); - }); - } else if(this.values) { + // plan the named query the first time, then execute it + return client.native.prepare(this.name, this.text, values.length, function (err) { + if (err) return after(err) + client.namedQueries[self.name] = true + return self.native.execute(self.name, values, after) + }) + } else if (this.values) { if (!Array.isArray(this.values)) { const err = new Error('Query values must be an array') return after(err) } - var vals = this.values.map(utils.prepareValue); - client.native.query(this.text, vals, after); + var vals = this.values.map(utils.prepareValue) + client.native.query(this.text, vals, after) } else { - client.native.query(this.text, after); + client.native.query(this.text, after) } -}; +} diff --git a/lib/native/result.js b/lib/native/result.js index 62075b657..ae9a97a1e 100644 --- a/lib/native/result.js +++ b/lib/native/result.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,31 +7,31 @@ * README.md file in the root directory of this source tree. */ -var NativeResult = module.exports = function(pq) { - this.command = null; - this.rowCount = 0; - this.rows = null; - this.fields = null; -}; +var NativeResult = module.exports = function (pq) { + this.command = null + this.rowCount = 0 + this.rows = null + this.fields = null +} -NativeResult.prototype.addCommandComplete = function(pq) { - this.command = pq.cmdStatus().split(' ')[0]; - this.rowCount = parseInt(pq.cmdTuples(), 10); - var nfields = pq.nfields(); - if(nfields < 1) return; +NativeResult.prototype.addCommandComplete = function (pq) { + this.command = pq.cmdStatus().split(' ')[0] + this.rowCount = parseInt(pq.cmdTuples(), 10) + var nfields = pq.nfields() + if (nfields < 1) return - this.fields = []; - for(var i = 0; i < nfields; i++) { + this.fields = [] + for (var i = 0; i < nfields; i++) { this.fields.push({ name: pq.fname(i), dataTypeID: pq.ftype(i) - }); + }) } -}; +} -NativeResult.prototype.addRow = function(row) { +NativeResult.prototype.addRow = function (row) { // This is empty to ensure pg code doesn't break when switching to pg-native // pg-native loads all rows into the final result object by default. // This is because libpg loads all rows into memory before passing the result // to pg-native. -}; +} diff --git a/lib/query.js b/lib/query.js index 26b930fbc..89bde080b 100644 --- a/lib/query.js +++ b/lib/query.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,127 +7,127 @@ * README.md file in the root directory of this source tree. */ -var EventEmitter = require('events').EventEmitter; -var util = require('util'); +var EventEmitter = require('events').EventEmitter +var util = require('util') -var Result = require('./result'); -var utils = require('./utils'); +var Result = require('./result') +var utils = require('./utils') -var Query = function(config, values, callback) { +var Query = function (config, values, callback) { // use of "new" optional - if(!(this instanceof Query)) { return new Query(config, values, callback); } - - config = utils.normalizeQueryConfig(config, values, callback); - - this.text = config.text; - this.values = config.values; - this.rows = config.rows; - this.types = config.types; - this.name = config.name; - this.binary = config.binary; - this.stream = config.stream; - //use unique portal name each time - this.portal = config.portal || ""; - this.callback = config.callback; - if(process.domain && config.callback) { - this.callback = process.domain.bind(config.callback); - } - this._result = new Result(config.rowMode, config.types); - this.isPreparedStatement = false; - this._canceledDueToError = false; - this._promise = null; - EventEmitter.call(this); -}; - -util.inherits(Query, EventEmitter); - -Query.prototype.requiresPreparation = function() { - //named queries must always be prepared - if(this.name) { return true; } - //always prepare if there are max number of rows expected per - //portal execution - if(this.rows) { return true; } - //don't prepare empty text queries - if(!this.text) { return false; } - //prepare if there are values - if(!this.values) { return false; } - return this.values.length > 0; -}; - -//associates row metadata from the supplied -//message with this query object -//metadata used when parsing row results -Query.prototype.handleRowDescription = function(msg) { - this._result.addFields(msg.fields); - this._accumulateRows = this.callback || !this.listeners('row').length; -}; - -Query.prototype.handleDataRow = function(msg) { - var row; + if (!(this instanceof Query)) { return new Query(config, values, callback) } + + config = utils.normalizeQueryConfig(config, values, callback) + + this.text = config.text + this.values = config.values + this.rows = config.rows + this.types = config.types + this.name = config.name + this.binary = config.binary + this.stream = config.stream + // use unique portal name each time + this.portal = config.portal || '' + this.callback = config.callback + if (process.domain && config.callback) { + this.callback = process.domain.bind(config.callback) + } + this._result = new Result(config.rowMode, config.types) + this.isPreparedStatement = false + this._canceledDueToError = false + this._promise = null + EventEmitter.call(this) +} + +util.inherits(Query, EventEmitter) + +Query.prototype.requiresPreparation = function () { + // named queries must always be prepared + if (this.name) { return true } + // always prepare if there are max number of rows expected per + // portal execution + if (this.rows) { return true } + // don't prepare empty text queries + if (!this.text) { return false } + // prepare if there are values + if (!this.values) { return false } + return this.values.length > 0 +} + +// associates row metadata from the supplied +// message with this query object +// metadata used when parsing row results +Query.prototype.handleRowDescription = function (msg) { + this._result.addFields(msg.fields) + this._accumulateRows = this.callback || !this.listeners('row').length +} + +Query.prototype.handleDataRow = function (msg) { + var row if (this._canceledDueToError) { - return; + return } try { - row = this._result.parseRow(msg.fields); + row = this._result.parseRow(msg.fields) } catch (err) { - this._canceledDueToError = err; - return; + this._canceledDueToError = err + return } - this.emit('row', row, this._result); + this.emit('row', row, this._result) if (this._accumulateRows) { - this._result.addRow(row); + this._result.addRow(row) } -}; +} -Query.prototype.handleCommandComplete = function(msg, con) { - this._result.addCommandComplete(msg); - //need to sync after each command complete of a prepared statement - if(this.isPreparedStatement) { - con.sync(); +Query.prototype.handleCommandComplete = function (msg, con) { + this._result.addCommandComplete(msg) + // need to sync after each command complete of a prepared statement + if (this.isPreparedStatement) { + con.sync() } -}; +} -//if a named prepared statement is created with empty query text -//the backend will send an emptyQuery message but *not* a command complete message -//execution on the connection will hang until the backend receives a sync message -Query.prototype.handleEmptyQuery = function(con) { +// if a named prepared statement is created with empty query text +// the backend will send an emptyQuery message but *not* a command complete message +// execution on the connection will hang until the backend receives a sync message +Query.prototype.handleEmptyQuery = function (con) { if (this.isPreparedStatement) { - con.sync(); + con.sync() } -}; +} -Query.prototype.handleReadyForQuery = function(con) { - if(this._canceledDueToError) { - return this.handleError(this._canceledDueToError, con); +Query.prototype.handleReadyForQuery = function (con) { + if (this._canceledDueToError) { + return this.handleError(this._canceledDueToError, con) } - if(this.callback) { - this.callback(null, this._result); + if (this.callback) { + this.callback(null, this._result) } - this.emit('end', this._result); -}; + this.emit('end', this._result) +} -Query.prototype.handleError = function(err, connection) { - //need to sync after error during a prepared statement - if(this.isPreparedStatement) { - connection.sync(); +Query.prototype.handleError = function (err, connection) { + // need to sync after error during a prepared statement + if (this.isPreparedStatement) { + connection.sync() } - if(this._canceledDueToError) { - err = this._canceledDueToError; - this._canceledDueToError = false; + if (this._canceledDueToError) { + err = this._canceledDueToError + this._canceledDueToError = false } - //if callback supplied do not emit error event as uncaught error - //events will bubble up to node process - if(this.callback) { - return this.callback(err); + // if callback supplied do not emit error event as uncaught error + // events will bubble up to node process + if (this.callback) { + return this.callback(err) } - this.emit('error', err); -}; + this.emit('error', err) +} -Query.prototype.submit = function(connection) { - if (typeof this.text != 'string' && typeof this.name != 'string') { +Query.prototype.submit = function (connection) { + if (typeof this.text !== 'string' && typeof this.name !== 'string') { const err = new Error('A query must have either text or a name. Supplying neither is unsupported.') connection.emit('error', err) connection.emit('readyForQuery') @@ -139,75 +139,75 @@ Query.prototype.submit = function(connection) { connection.emit('readyForQuery') return } - if(this.requiresPreparation()) { - this.prepare(connection); + if (this.requiresPreparation()) { + this.prepare(connection) } else { - connection.query(this.text); + connection.query(this.text) } -}; +} -Query.prototype.hasBeenParsed = function(connection) { - return this.name && connection.parsedStatements[this.name]; -}; +Query.prototype.hasBeenParsed = function (connection) { + return this.name && connection.parsedStatements[this.name] +} -Query.prototype.handlePortalSuspended = function(connection) { - this._getRows(connection, this.rows); -}; +Query.prototype.handlePortalSuspended = function (connection) { + this._getRows(connection, this.rows) +} -Query.prototype._getRows = function(connection, rows) { +Query.prototype._getRows = function (connection, rows) { connection.execute({ portal: this.portalName, rows: rows - }, true); - connection.flush(); -}; - -Query.prototype.prepare = function(connection) { - var self = this; - //prepared statements need sync to be called after each command - //complete or when an error is encountered - this.isPreparedStatement = true; - //TODO refactor this poor encapsulation - if(!this.hasBeenParsed(connection)) { + }, true) + connection.flush() +} + +Query.prototype.prepare = function (connection) { + var self = this + // prepared statements need sync to be called after each command + // complete or when an error is encountered + this.isPreparedStatement = true + // TODO refactor this poor encapsulation + if (!this.hasBeenParsed(connection)) { connection.parse({ text: self.text, name: self.name, types: self.types - }, true); + }, true) } - if(self.values) { - self.values = self.values.map(utils.prepareValue); + if (self.values) { + self.values = self.values.map(utils.prepareValue) } - //http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY + // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY connection.bind({ portal: self.portalName, statement: self.name, values: self.values, binary: self.binary - }, true); + }, true) connection.describe({ type: 'P', - name: self.portalName || "" - }, true); + name: self.portalName || '' + }, true) - this._getRows(connection, this.rows); -}; + this._getRows(connection, this.rows) +} Query.prototype.handleCopyInResponse = function (connection) { - if(this.stream) this.stream.startStreamingToConnection(connection); - else connection.sendCopyFail('No source stream defined'); -}; + if (this.stream) this.stream.startStreamingToConnection(connection) + else connection.sendCopyFail('No source stream defined') +} Query.prototype.handleCopyData = function (msg, connection) { - var chunk = msg.chunk; - if(this.stream) { - this.stream.handleChunk(chunk); - } - //if there are no stream (for example when copy to query was sent by - //query method instead of copyTo) error will be handled - //on copyOutResponse event, so silently ignore this error here -}; -module.exports = Query; + var chunk = msg.chunk + if (this.stream) { + this.stream.handleChunk(chunk) + } + // if there are no stream (for example when copy to query was sent by + // query method instead of copyTo) error will be handled + // on copyOutResponse event, so silently ignore this error here +} +module.exports = Query diff --git a/lib/result.js b/lib/result.js index 21b649a93..da999158a 100644 --- a/lib/result.js +++ b/lib/result.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,110 +7,110 @@ * README.md file in the root directory of this source tree. */ -var types = require('pg-types'); +var types = require('pg-types') -//result object returned from query -//in the 'end' event and also -//passed as second argument to provided callback -var Result = function(rowMode) { - this.command = null; - this.rowCount = null; - this.oid = null; - this.rows = []; - this.fields = []; - this._parsers = []; - this.RowCtor = null; - this.rowAsArray = rowMode == "array"; - if(this.rowAsArray) { - this.parseRow = this._parseRowAsArray; +// result object returned from query +// in the 'end' event and also +// passed as second argument to provided callback +var Result = function (rowMode) { + this.command = null + this.rowCount = null + this.oid = null + this.rows = [] + this.fields = [] + this._parsers = [] + this.RowCtor = null + this.rowAsArray = rowMode === 'array' + if (this.rowAsArray) { + this.parseRow = this._parseRowAsArray } -}; +} -var matchRegexp = /([A-Za-z]+) ?(\d+ )?(\d+)?/; +var matchRegexp = /([A-Za-z]+) ?(\d+ )?(\d+)?/ -//adds a command complete message -Result.prototype.addCommandComplete = function(msg) { - var match; - if(msg.text) { - //pure javascript - match = matchRegexp.exec(msg.text); +// adds a command complete message +Result.prototype.addCommandComplete = function (msg) { + var match + if (msg.text) { + // pure javascript + match = matchRegexp.exec(msg.text) } else { - //native bindings - match = matchRegexp.exec(msg.command); + // native bindings + match = matchRegexp.exec(msg.command) } - if(match) { - this.command = match[1]; - //match 3 will only be existing on insert commands - if(match[3]) { - //msg.value is from native bindings - this.rowCount = parseInt(match[3] || msg.value, 10); - this.oid = parseInt(match[2], 10); + if (match) { + this.command = match[1] + // match 3 will only be existing on insert commands + if (match[3]) { + // msg.value is from native bindings + this.rowCount = parseInt(match[3] || msg.value, 10) + this.oid = parseInt(match[2], 10) } else { - this.rowCount = parseInt(match[2], 10); + this.rowCount = parseInt(match[2], 10) } } -}; +} -Result.prototype._parseRowAsArray = function(rowData) { - var row = []; - for(var i = 0, len = rowData.length; i < len; i++) { - var rawValue = rowData[i]; - if(rawValue !== null) { - row.push(this._parsers[i](rawValue)); +Result.prototype._parseRowAsArray = function (rowData) { + var row = [] + for (var i = 0, len = rowData.length; i < len; i++) { + var rawValue = rowData[i] + if (rawValue !== null) { + row.push(this._parsers[i](rawValue)) } else { - row.push(null); + row.push(null) } } - return row; -}; + return row +} -//rowData is an array of text or binary values -//this turns the row into a JavaScript object -Result.prototype.parseRow = function(rowData) { - return new this.RowCtor(this._parsers, rowData); -}; +// rowData is an array of text or binary values +// this turns the row into a JavaScript object +Result.prototype.parseRow = function (rowData) { + return new this.RowCtor(this._parsers, rowData) +} -Result.prototype.addRow = function(row) { - this.rows.push(row); -}; +Result.prototype.addRow = function (row) { + this.rows.push(row) +} -var inlineParser = function(fieldName, i) { +var inlineParser = function (fieldName, i) { return "\nthis['" + - //fields containing single quotes will break - //the evaluated javascript unless they are escaped - //see https://github.com/brianc/node-postgres/issues/507 - //Addendum: However, we need to make sure to replace all - //occurences of apostrophes, not just the first one. - //See https://github.com/brianc/node-postgres/issues/934 + // fields containing single quotes will break + // the evaluated javascript unless they are escaped + // see https://github.com/brianc/node-postgres/issues/507 + // Addendum: However, we need to make sure to replace all + // occurences of apostrophes, not just the first one. + // See https://github.com/brianc/node-postgres/issues/934 fieldName.replace(/'/g, "\\'") + "'] = " + - "rowData[" + i + "] == null ? null : parsers[" + i + "](rowData[" + i + "]);"; -}; + 'rowData[' + i + '] == null ? null : parsers[' + i + '](rowData[' + i + ']);' +} -Result.prototype.addFields = function(fieldDescriptions) { - //clears field definitions - //multiple query statements in 1 action can result in multiple sets - //of rowDescriptions...eg: 'select NOW(); select 1::int;' - //you need to reset the fields - if(this.fields.length) { - this.fields = []; - this._parsers = []; +Result.prototype.addFields = function (fieldDescriptions) { + // clears field definitions + // multiple query statements in 1 action can result in multiple sets + // of rowDescriptions...eg: 'select NOW(); select 1::int;' + // you need to reset the fields + if (this.fields.length) { + this.fields = [] + this._parsers = [] } - var ctorBody = ""; - for(var i = 0; i < fieldDescriptions.length; i++) { - var desc = fieldDescriptions[i]; - this.fields.push(desc); - var parser = this._getTypeParser(desc.dataTypeID, desc.format || 'text'); - this._parsers.push(parser); - //this is some craziness to compile the row result parsing - //results in ~60% speedup on large query result sets - ctorBody += inlineParser(desc.name, i); + var ctorBody = '' + for (var i = 0; i < fieldDescriptions.length; i++) { + var desc = fieldDescriptions[i] + this.fields.push(desc) + var parser = this._getTypeParser(desc.dataTypeID, desc.format || 'text') + this._parsers.push(parser) + // this is some craziness to compile the row result parsing + // results in ~60% speedup on large query result sets + ctorBody += inlineParser(desc.name, i) } - if(!this.rowAsArray) { - this.RowCtor = Function("parsers", "rowData", ctorBody); + if (!this.rowAsArray) { + this.RowCtor = Function('parsers', 'rowData', ctorBody) } -}; +} -Result.prototype._getTypeParser = types.getTypeParser; +Result.prototype._getTypeParser = types.getTypeParser -module.exports = Result; +module.exports = Result diff --git a/lib/type-overrides.js b/lib/type-overrides.js index 53be35ef9..543944062 100644 --- a/lib/type-overrides.js +++ b/lib/type-overrides.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,33 +7,33 @@ * README.md file in the root directory of this source tree. */ -var types = require('pg-types'); +var types = require('pg-types') -function TypeOverrides(userTypes) { - this._types = userTypes || types; - this.text = {}; - this.binary = {}; +function TypeOverrides (userTypes) { + this._types = userTypes || types + this.text = {} + this.binary = {} } -TypeOverrides.prototype.getOverrides = function(format) { - switch(format) { - case 'text': return this.text; - case 'binary': return this.binary; - default: return {}; +TypeOverrides.prototype.getOverrides = function (format) { + switch (format) { + case 'text': return this.text + case 'binary': return this.binary + default: return {} } -}; +} -TypeOverrides.prototype.setTypeParser = function(oid, format, parseFn) { - if(typeof format == 'function') { - parseFn = format; - format = 'text'; +TypeOverrides.prototype.setTypeParser = function (oid, format, parseFn) { + if (typeof format === 'function') { + parseFn = format + format = 'text' } - this.getOverrides(format)[oid] = parseFn; -}; + this.getOverrides(format)[oid] = parseFn +} -TypeOverrides.prototype.getTypeParser = function(oid, format) { - format = format || 'text'; - return this.getOverrides(format)[oid] || this._types.getTypeParser(oid, format); -}; +TypeOverrides.prototype.getTypeParser = function (oid, format) { + format = format || 'text' + return this.getOverrides(format)[oid] || this._types.getTypeParser(oid, format) +} -module.exports = TypeOverrides; +module.exports = TypeOverrides diff --git a/lib/utils.js b/lib/utils.js index 05c6f0b4c..a83cdee9d 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' /** * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) * All rights reserved. @@ -7,151 +7,141 @@ * README.md file in the root directory of this source tree. */ -const util = require('util') -const crypto = require('crypto'); +const crypto = require('crypto') -const defaults = require('./defaults'); +const defaults = require('./defaults') -function escapeElement(elementRepresentation) { +function escapeElement (elementRepresentation) { var escaped = elementRepresentation .replace(/\\/g, '\\\\') - .replace(/"/g, '\\"'); + .replace(/"/g, '\\"') - return '"' + escaped + '"'; + return '"' + escaped + '"' } // convert a JS array to a postgres array literal // uses comma separator so won't work for types like box that use // a different array separator. -function arrayString(val) { - var result = '{'; - for (var i = 0 ; i < val.length; i++) { - if(i > 0) { - result = result + ','; +function arrayString (val) { + var result = '{' + for (var i = 0; i < val.length; i++) { + if (i > 0) { + result = result + ',' } - if(val[i] === null || typeof val[i] === 'undefined') { - result = result + 'NULL'; - } - else if(Array.isArray(val[i])) { - result = result + arrayString(val[i]); - } - else - { - result += escapeElement(prepareValue(val[i])); + if (val[i] === null || typeof val[i] === 'undefined') { + result = result + 'NULL' + } else if (Array.isArray(val[i])) { + result = result + arrayString(val[i]) + } else { + result += escapeElement(prepareValue(val[i])) } } - result = result + '}'; - return result; + result = result + '}' + return result } -//converts values from javascript types -//to their 'raw' counterparts for use as a postgres parameter -//note: you can override this function to provide your own conversion mechanism -//for complex types, etc... -var prepareValue = function(val, seen) { +// converts values from javascript types +// to their 'raw' counterparts for use as a postgres parameter +// note: you can override this function to provide your own conversion mechanism +// for complex types, etc... +var prepareValue = function (val, seen) { if (val instanceof Buffer) { - return val; + return val } - if(val instanceof Date) { - if(defaults.parseInputDatesAsUTC) { - return dateToStringUTC(val); + if (val instanceof Date) { + if (defaults.parseInputDatesAsUTC) { + return dateToStringUTC(val) } else { - return dateToString(val); + return dateToString(val) } } - if(Array.isArray(val)) { - return arrayString(val); + if (Array.isArray(val)) { + return arrayString(val) } - if(val === null || typeof val === 'undefined') { - return null; + if (val === null || typeof val === 'undefined') { + return null } - if(typeof val === 'object') { - return prepareObject(val, seen); + if (typeof val === 'object') { + return prepareObject(val, seen) } - return val.toString(); -}; + return val.toString() +} -function prepareObject(val, seen) { - if(val.toPostgres && typeof val.toPostgres === 'function') { - seen = seen || []; +function prepareObject (val, seen) { + if (val.toPostgres && typeof val.toPostgres === 'function') { + seen = seen || [] if (seen.indexOf(val) !== -1) { - throw new Error('circular reference detected while preparing "' + val + '" for query'); + throw new Error('circular reference detected while preparing "' + val + '" for query') } - seen.push(val); + seen.push(val) - return prepareValue(val.toPostgres(prepareValue), seen); + return prepareValue(val.toPostgres(prepareValue), seen) } - return JSON.stringify(val); + return JSON.stringify(val) } -function pad(number, digits) { - number = "" +number; - while(number.length < digits) - number = "0" + number; - return number; +function pad (number, digits) { + number = '' + number + while (number.length < digits) { number = '0' + number } + return number } -function dateToString(date) { - - var offset = -date.getTimezoneOffset(); +function dateToString (date) { + var offset = -date.getTimezoneOffset() var ret = pad(date.getFullYear(), 4) + '-' + pad(date.getMonth() + 1, 2) + '-' + pad(date.getDate(), 2) + 'T' + pad(date.getHours(), 2) + ':' + pad(date.getMinutes(), 2) + ':' + pad(date.getSeconds(), 2) + '.' + - pad(date.getMilliseconds(), 3); + pad(date.getMilliseconds(), 3) - if(offset < 0) { - ret += "-"; - offset *= -1; - } - else - ret += "+"; + if (offset < 0) { + ret += '-' + offset *= -1 + } else { ret += '+' } - return ret + pad(Math.floor(offset/60), 2) + ":" + pad(offset%60, 2); + return ret + pad(Math.floor(offset / 60), 2) + ':' + pad(offset % 60, 2) } -function dateToStringUTC(date) { - +function dateToStringUTC (date) { var ret = pad(date.getUTCFullYear(), 4) + '-' + pad(date.getUTCMonth() + 1, 2) + '-' + pad(date.getUTCDate(), 2) + 'T' + pad(date.getUTCHours(), 2) + ':' + pad(date.getUTCMinutes(), 2) + ':' + pad(date.getUTCSeconds(), 2) + '.' + - pad(date.getUTCMilliseconds(), 3); + pad(date.getUTCMilliseconds(), 3) - return ret + "+00:00"; + return ret + '+00:00' } function normalizeQueryConfig (config, values, callback) { - //can take in strings or config objects - config = (typeof(config) == 'string') ? { text: config } : config; - if(values) { - if(typeof values === 'function') { - config.callback = values; + // can take in strings or config objects + config = (typeof (config) === 'string') ? { text: config } : config + if (values) { + if (typeof values === 'function') { + config.callback = values } else { - config.values = values; + config.values = values } } - if(callback) { - config.callback = callback; + if (callback) { + config.callback = callback } - return config; + return config } - const md5 = function (string) { - return crypto.createHash('md5').update(string, 'utf-8').digest('hex'); -}; + return crypto.createHash('md5').update(string, 'utf-8').digest('hex') +} module.exports = { prepareValue: function prepareValueWrapper (value) { - //this ensures that extra arguments do not get passed into prepareValue - //by accident, eg: from calling values.map(utils.prepareValue) - return prepareValue(value); + // this ensures that extra arguments do not get passed into prepareValue + // by accident, eg: from calling values.map(utils.prepareValue) + return prepareValue(value) }, normalizeQueryConfig: normalizeQueryConfig, - md5: md5, -}; + md5: md5 +} diff --git a/package.json b/package.json index 537570d04..070689726 100644 --- a/package.json +++ b/package.json @@ -29,13 +29,17 @@ "devDependencies": { "async": "0.9.0", "co": "4.6.0", - "jshint": "2.5.2", + "eslint": "4.2.0", + "eslint-config-standard": "10.2.1", + "eslint-plugin-import": "2.7.0", + "eslint-plugin-node": "5.1.0", + "eslint-plugin-promise": "3.5.0", + "eslint-plugin-standard": "3.0.1", "pg-copy-streams": "0.3.0" }, "minNativeVersion": "1.7.0", "scripts": { - "changelog": "npm i github-changes && ./node_modules/.bin/github-changes -o brianc -r node-postgres -d pulls -a -v", - "test": "make test-all connectionString=postgres://postgres@localhost:5432/postgres" + "test": "make test-all" }, "license": "MIT", "engines": { diff --git a/script/create-test-tables.js b/script/create-test-tables.js index 4881daf87..c887629ec 100644 --- a/script/create-test-tables.js +++ b/script/create-test-tables.js @@ -1,33 +1,33 @@ -"use strict"; -var args = require(__dirname + '/../test/cli'); -var pg = require(__dirname + '/../lib'); +'use strict' +var args = require(__dirname + '/../test/cli') +var pg = require(__dirname + '/../lib') var people = [ - {name: 'Aaron', age: 10}, - {name: 'Brian', age: 20}, - {name: 'Chris', age: 30}, - {name: 'David', age: 40}, - {name: 'Elvis', age: 50}, - {name: 'Frank', age: 60}, - {name: 'Grace', age: 70}, - {name: 'Haley', age: 80}, - {name: 'Irma', age: 90}, - {name: 'Jenny', age: 100}, - {name: 'Kevin', age: 110}, - {name: 'Larry', age: 120}, + {name: 'Aaron', age: 10}, + {name: 'Brian', age: 20}, + {name: 'Chris', age: 30}, + {name: 'David', age: 40}, + {name: 'Elvis', age: 50}, + {name: 'Frank', age: 60}, + {name: 'Grace', age: 70}, + {name: 'Haley', age: 80}, + {name: 'Irma', age: 90}, + {name: 'Jenny', age: 100}, + {name: 'Kevin', age: 110}, + {name: 'Larry', age: 120}, {name: 'Michelle', age: 130}, - {name: 'Nancy', age: 140}, - {name: 'Olivia', age: 150}, - {name: 'Peter', age: 160}, - {name: 'Quinn', age: 170}, - {name: 'Ronda', age: 180}, - {name: 'Shelley', age: 190}, - {name: 'Tobias', age: 200}, - {name: 'Uma', age: 210}, - {name: 'Veena', age: 220}, - {name: 'Wanda', age: 230}, - {name: 'Xavier', age: 240}, - {name: 'Yoyo', age: 250}, + {name: 'Nancy', age: 140}, + {name: 'Olivia', age: 150}, + {name: 'Peter', age: 160}, + {name: 'Quinn', age: 170}, + {name: 'Ronda', age: 180}, + {name: 'Shelley', age: 190}, + {name: 'Tobias', age: 200}, + {name: 'Uma', age: 210}, + {name: 'Veena', age: 220}, + {name: 'Wanda', age: 230}, + {name: 'Xavier', age: 240}, + {name: 'Yoyo', age: 250}, {name: 'Zanzabar', age: 260} ] @@ -37,16 +37,16 @@ var con = new pg.Client({ user: args.user, password: args.password, database: args.database -}); -con.connect(); -var query = con.query("drop table if exists person"); -con.query("create table person(id serial, name varchar(10), age integer)", (err, res) => { - console.log("Created table person"); - console.log("Filling it with people"); }) -people.map(function(person) { - return con.query(new pg.Query("insert into person(name, age) values('"+person.name + "', '" + person.age + "')")); -}).pop().on('end', function(){ - console.log("Inserted 26 people"); - con.end(); -}); +con.connect() +var query = con.query('drop table if exists person') +con.query('create table person(id serial, name varchar(10), age integer)', (err, res) => { + console.log('Created table person') + console.log('Filling it with people') +}) +people.map(function (person) { + return con.query(new pg.Query("insert into person(name, age) values('" + person.name + "', '" + person.age + "')")) +}).pop().on('end', function () { + console.log('Inserted 26 people') + con.end() +}) diff --git a/script/dump-db-types.js b/script/dump-db-types.js index cd2041535..2e55969d2 100644 --- a/script/dump-db-types.js +++ b/script/dump-db-types.js @@ -1,24 +1,23 @@ -"use strict"; -var pg = require(__dirname + '/../lib'); -var args = require(__dirname + '/../test/cli'); +'use strict' +var pg = require(__dirname + '/../lib') +var args = require(__dirname + '/../test/cli') var queries = [ - "select CURRENT_TIMESTAMP", + 'select CURRENT_TIMESTAMP', "select interval '1 day' + interval '1 hour'", - "select TIMESTAMP 'today'"]; - -queries.forEach(function(query) { + "select TIMESTAMP 'today'"] +queries.forEach(function (query) { var client = new pg.Client({ user: args.user, database: args.database, password: args.password - }); - client.connect(); + }) + client.connect() client .query(query) - .on('row', function(row) { - console.log(row); - client.end(); - }); -}); + .on('row', function (row) { + console.log(row) + client.end() + }) +}) diff --git a/script/list-db-types.js b/script/list-db-types.js index b2db8403e..d281bb90e 100644 --- a/script/list-db-types.js +++ b/script/list-db-types.js @@ -1,7 +1,7 @@ -"use strict"; -var helper = require(__dirname + "/../test/integration/test-helper"); -var pg = helper.pg; -pg.connect(helper.config, assert.success(function(client) { - var query = client.query('select oid, typname from pg_type where typtype = \'b\' order by oid'); - query.on('row', console.log); +'use strict' +var helper = require(__dirname + '/../test/integration/test-helper') +var pg = helper.pg +pg.connect(helper.config, assert.success(function (client) { + var query = client.query('select oid, typname from pg_type where typtype = \'b\' order by oid') + query.on('row', console.log) })) diff --git a/test/buffer-list.js b/test/buffer-list.js index 3ebffe9da..527743fb2 100644 --- a/test/buffer-list.js +++ b/test/buffer-list.js @@ -1,70 +1,70 @@ -"use strict"; -global.BufferList = function() { - this.buffers = []; -}; -var p = BufferList.prototype; +'use strict' +global.BufferList = function () { + this.buffers = [] +} +var p = BufferList.prototype -p.add = function(buffer, front) { - this.buffers[front ? "unshift" : "push"](buffer); - return this; -}; +p.add = function (buffer, front) { + this.buffers[front ? 'unshift' : 'push'](buffer) + return this +} -p.addInt16 = function(val, front) { - return this.add(Buffer.from([(val >>> 8),(val >>> 0)]),front); -}; +p.addInt16 = function (val, front) { + return this.add(Buffer.from([(val >>> 8), (val >>> 0)]), front) +} -p.getByteLength = function(initial) { - return this.buffers.reduce(function(previous, current){ - return previous + current.length; - },initial || 0); -}; +p.getByteLength = function (initial) { + return this.buffers.reduce(function (previous, current) { + return previous + current.length + }, initial || 0) +} -p.addInt32 = function(val, first) { +p.addInt32 = function (val, first) { return this.add(Buffer.from([ (val >>> 24 & 0xFF), (val >>> 16 & 0xFF), (val >>> 8 & 0xFF), (val >>> 0 & 0xFF) - ]),first); -}; + ]), first) +} -p.addCString = function(val, front) { - var len = Buffer.byteLength(val); - var buffer = Buffer.alloc(len+1); - buffer.write(val); - buffer[len] = 0; - return this.add(buffer, front); -}; +p.addCString = function (val, front) { + var len = Buffer.byteLength(val) + var buffer = Buffer.alloc(len + 1) + buffer.write(val) + buffer[len] = 0 + return this.add(buffer, front) +} -p.addChar = function(char, first) { - return this.add(Buffer.from(char,'utf8'), first); -}; +p.addChar = function (char, first) { + return this.add(Buffer.from(char, 'utf8'), first) +} -p.join = function(appendLength, char) { - var length = this.getByteLength(); - if(appendLength) { - this.addInt32(length+4, true); - return this.join(false, char); +p.join = function (appendLength, char) { + var length = this.getByteLength() + if (appendLength) { + this.addInt32(length + 4, true) + return this.join(false, char) } - if(char) { - this.addChar(char, true); - length++; + if (char) { + this.addChar(char, true) + length++ } - var result = Buffer.alloc(length); - var index = 0; - this.buffers.forEach(function(buffer) { - buffer.copy(result, index, 0); - index += buffer.length; - }); - return result; -}; + var result = Buffer.alloc(length) + var index = 0 + this.buffers.forEach(function (buffer) { + buffer.copy(result, index, 0) + index += buffer.length + }) + return result +} -BufferList.concat = function() { - var total = new BufferList(); - for(var i = 0; i < arguments.length; i++) { - total.add(arguments[i]); +BufferList.concat = function () { + var total = new BufferList() + for (var i = 0; i < arguments.length; i++) { + total.add(arguments[i]) } - return total.join(); -}; + return total.join() +} -module.exports = BufferList; +module.exports = BufferList diff --git a/test/cli.js b/test/cli.js index 388b8acf7..2b40976c6 100644 --- a/test/cli.js +++ b/test/cli.js @@ -1,25 +1,25 @@ -"use strict"; -var ConnectionParameters = require(__dirname + '/../lib/connection-parameters'); -var config = new ConnectionParameters(process.argv[2]); +'use strict' +var ConnectionParameters = require(__dirname + '/../lib/connection-parameters') +var config = new ConnectionParameters(process.argv[2]) -for(var i = 0; i < process.argv.length; i++) { - switch(process.argv[i].toLowerCase()) { - case 'native': - config.native = true; - break; - case 'binary': - config.binary = true; - break; - case 'down': - config.down = true; - break; - default: - break; +for (var i = 0; i < process.argv.length; i++) { + switch (process.argv[i].toLowerCase()) { + case 'native': + config.native = true + break + case 'binary': + config.binary = true + break + case 'down': + config.down = true + break + default: + break } } -if(process.env['PG_TEST_NATIVE']) { - config.native = true; +if (process.env['PG_TEST_NATIVE']) { + config.native = true } -module.exports = config; +module.exports = config diff --git a/test/integration/client/api-tests.js b/test/integration/client/api-tests.js index 668c6a743..22fe96b2f 100644 --- a/test/integration/client/api-tests.js +++ b/test/integration/client/api-tests.js @@ -1,208 +1,208 @@ -"use strict"; -var helper = require(__dirname + "/../test-helper"); -var pg = helper.pg; +'use strict' +var helper = require(__dirname + '/../test-helper') +var pg = helper.pg -var suite = new helper.Suite(); +var suite = new helper.Suite() -suite.test("pool callback behavior", done => { - //test weird callback behavior with node-pool - const pool = new pg.Pool(); - pool.connect(function(err) { - assert(!err); - arguments[1].emit("drain"); - arguments[2](); - pool.end(done); - }); -}); +suite.test('pool callback behavior', done => { + // test weird callback behavior with node-pool + const pool = new pg.Pool() + pool.connect(function (err) { + assert(!err) + arguments[1].emit('drain') + arguments[2]() + pool.end(done) + }) +}) -suite.test("callback API", done => { - const client = new helper.Client(); - client.query("CREATE TEMP TABLE peep(name text)"); - client.query("INSERT INTO peep(name) VALUES ($1)", ["brianc"]); +suite.test('callback API', done => { + const client = new helper.Client() + client.query('CREATE TEMP TABLE peep(name text)') + client.query('INSERT INTO peep(name) VALUES ($1)', ['brianc']) const config = { - text: "INSERT INTO peep(name) VALUES ($1)", - values: ["brian"] - }; - client.query(config); - client.query("INSERT INTO peep(name) VALUES ($1)", ["aaron"]); + text: 'INSERT INTO peep(name) VALUES ($1)', + values: ['brian'] + } + client.query(config) + client.query('INSERT INTO peep(name) VALUES ($1)', ['aaron']) - client.query("SELECT * FROM peep ORDER BY name", (err, res) => { - assert(!err); - assert.equal(res.rowCount, 3); + client.query('SELECT * FROM peep ORDER BY name', (err, res) => { + assert(!err) + assert.equal(res.rowCount, 3) assert.deepEqual(res.rows, [ { - name: "aaron" + name: 'aaron' }, { - name: "brian" + name: 'brian' }, { - name: "brianc" + name: 'brianc' } - ]); - done(); - }); + ]) + done() + }) client.connect(err => { - assert(!err); - client.once("drain", () => client.end()); - }); -}); + assert(!err) + client.once('drain', () => client.end()) + }) +}) -suite.test("executing nested queries", function(done) { - const pool = new pg.Pool(); +suite.test('executing nested queries', function (done) { + const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { - assert(!err); + assert.calls(function (err, client, release) { + assert(!err) client.query( - "select now as now from NOW()", - assert.calls(function(err, result) { - assert.equal(new Date().getYear(), result.rows[0].now.getYear()); + 'select now as now from NOW()', + assert.calls(function (err, result) { + assert.equal(new Date().getYear(), result.rows[0].now.getYear()) client.query( - "select now as now_again FROM NOW()", - assert.calls(function() { + 'select now as now_again FROM NOW()', + assert.calls(function () { client.query( - "select * FROM NOW()", - assert.calls(function() { - assert.ok("all queries hit"); - release(); - pool.end(done); + 'select * FROM NOW()', + assert.calls(function () { + assert.ok('all queries hit') + release() + pool.end(done) }) - ); + ) }) - ); + ) }) - ); + ) }) - ); -}); + ) +}) -suite.test("raises error if cannot connect", function() { - var connectionString = "pg://sfalsdkf:asdf@localhost/ieieie"; - const pool = new pg.Pool({ connectionString: connectionString }); +suite.test('raises error if cannot connect', function () { + var connectionString = 'pg://sfalsdkf:asdf@localhost/ieieie' + const pool = new pg.Pool({ connectionString: connectionString }) pool.connect( - assert.calls(function(err, client, done) { - assert.ok(err, "should have raised an error"); - done(); + assert.calls(function (err, client, done) { + assert.ok(err, 'should have raised an error') + done() }) - ); -}); + ) +}) -suite.test("query errors are handled and do not bubble if callback is provded", function(done) { - const pool = new pg.Pool(); - pool.connect( - assert.calls(function(err, client, release) { - assert(!err); +suite.test('query errors are handled and do not bubble if callback is provded', function (done) { + const pool = new pg.Pool() + pool.connect( + assert.calls(function (err, client, release) { + assert(!err) client.query( - "SELECT OISDJF FROM LEIWLISEJLSE", - assert.calls(function(err, result) { - assert.ok(err); + 'SELECT OISDJF FROM LEIWLISEJLSE', + assert.calls(function (err, result) { + assert.ok(err) release() pool.end(done) }) - ); + ) }) - ); - } -); + ) +} +) -suite.test("callback is fired once and only once", function(done) { +suite.test('callback is fired once and only once', function (done) { const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { - assert(!err); - client.query("CREATE TEMP TABLE boom(name varchar(10))"); - var callCount = 0; + assert.calls(function (err, client, release) { + assert(!err) + client.query('CREATE TEMP TABLE boom(name varchar(10))') + var callCount = 0 client.query( [ "INSERT INTO boom(name) VALUES('hai')", "INSERT INTO boom(name) VALUES('boom')", "INSERT INTO boom(name) VALUES('zoom')" - ].join(";"), - function(err, callback) { + ].join(';'), + function (err, callback) { assert.equal( callCount++, 0, - "Call count should be 0. More means this callback fired more than once." - ); + 'Call count should be 0. More means this callback fired more than once.' + ) release() pool.end(done) } - ); + ) }) - ); -}); + ) +}) -suite.test("can provide callback and config object", function(done) { +suite.test('can provide callback and config object', function (done) { const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { - assert(!err); + assert.calls(function (err, client, release) { + assert(!err) client.query( { - name: "boom", - text: "select NOW()" + name: 'boom', + text: 'select NOW()' }, - assert.calls(function(err, result) { - assert(!err); - assert.equal(result.rows[0].now.getYear(), new Date().getYear()); - release(); + assert.calls(function (err, result) { + assert(!err) + assert.equal(result.rows[0].now.getYear(), new Date().getYear()) + release() pool.end(done) }) - ); + ) }) - ); -}); + ) +}) -suite.test("can provide callback and config and parameters", function(done) { +suite.test('can provide callback and config and parameters', function (done) { const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { - assert(!err); + assert.calls(function (err, client, release) { + assert(!err) var config = { - text: "select $1::text as val" - }; + text: 'select $1::text as val' + } client.query( config, - ["hi"], - assert.calls(function(err, result) { - assert(!err); - assert.equal(result.rows.length, 1); - assert.equal(result.rows[0].val, "hi"); + ['hi'], + assert.calls(function (err, result) { + assert(!err) + assert.equal(result.rows.length, 1) + assert.equal(result.rows[0].val, 'hi') release() pool.end(done) }) - ); + ) }) - ); -}); + ) +}) -suite.test("null and undefined are both inserted as NULL", function(done) { +suite.test('null and undefined are both inserted as NULL', function (done) { const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { - assert(!err); + assert.calls(function (err, client, release) { + assert(!err) client.query( - "CREATE TEMP TABLE my_nulls(a varchar(1), b varchar(1), c integer, d integer, e date, f date)" - ); + 'CREATE TEMP TABLE my_nulls(a varchar(1), b varchar(1), c integer, d integer, e date, f date)' + ) client.query( - "INSERT INTO my_nulls(a,b,c,d,e,f) VALUES ($1,$2,$3,$4,$5,$6)", + 'INSERT INTO my_nulls(a,b,c,d,e,f) VALUES ($1,$2,$3,$4,$5,$6)', [null, undefined, null, undefined, null, undefined] - ); + ) client.query( - "SELECT * FROM my_nulls", - assert.calls(function(err, result) { - assert(!err); - assert.equal(result.rows.length, 1); - assert.isNull(result.rows[0].a); - assert.isNull(result.rows[0].b); - assert.isNull(result.rows[0].c); - assert.isNull(result.rows[0].d); - assert.isNull(result.rows[0].e); - assert.isNull(result.rows[0].f); + 'SELECT * FROM my_nulls', + assert.calls(function (err, result) { + assert(!err) + assert.equal(result.rows.length, 1) + assert.isNull(result.rows[0].a) + assert.isNull(result.rows[0].b) + assert.isNull(result.rows[0].c) + assert.isNull(result.rows[0].d) + assert.isNull(result.rows[0].e) + assert.isNull(result.rows[0].f) pool.end(done) - release(); + release() }) - ); + ) }) - ); -}); + ) +}) diff --git a/test/integration/client/appname-tests.js b/test/integration/client/appname-tests.js index 98c41776b..4db5297c9 100644 --- a/test/integration/client/appname-tests.js +++ b/test/integration/client/appname-tests.js @@ -1,101 +1,99 @@ -"use strict"; -var helper = require('./test-helper'); -var Client = helper.Client; +'use strict' +var helper = require('./test-helper') +var Client = helper.Client -var suite = new helper.Suite(); +var suite = new helper.Suite() -var conInfo = helper.config; +var conInfo = helper.config -function getConInfo(override) { - var newConInfo = {}; - Object.keys(conInfo).forEach(function(k){ - newConInfo[k] = conInfo[k]; - }); - Object.keys(override || {}).forEach(function(k){ - newConInfo[k] = override[k]; - }); - return newConInfo; +function getConInfo (override) { + var newConInfo = {} + Object.keys(conInfo).forEach(function (k) { + newConInfo[k] = conInfo[k] + }) + Object.keys(override || {}).forEach(function (k) { + newConInfo[k] = override[k] + }) + return newConInfo } -function getAppName(conf, cb) { - var client = new Client(conf); - client.connect(assert.success(function(){ - client.query('SHOW application_name', assert.success(function(res){ - var appName = res.rows[0].application_name; - cb(appName); - client.end(); - })); - })); +function getAppName (conf, cb) { + var client = new Client(conf) + client.connect(assert.success(function () { + client.query('SHOW application_name', assert.success(function (res) { + var appName = res.rows[0].application_name + cb(appName) + client.end() + })) + })) } -suite.test('No default appliation_name ', function(done) { - var conf = getConInfo(); - getAppName({ }, function(res){ - assert.strictEqual(res, ''); +suite.test('No default appliation_name ', function (done) { + var conf = getConInfo() + getAppName({ }, function (res) { + assert.strictEqual(res, '') done() - }); -}); + }) +}) -suite.test('fallback_application_name is used', function(done) { - var fbAppName = 'this is my app'; +suite.test('fallback_application_name is used', function (done) { + var fbAppName = 'this is my app' var conf = getConInfo({ - 'fallback_application_name' : fbAppName - }); - getAppName(conf, function(res){ - assert.strictEqual(res, fbAppName); + 'fallback_application_name': fbAppName + }) + getAppName(conf, function (res) { + assert.strictEqual(res, fbAppName) done() - }); -}); + }) +}) -suite.test('application_name is used', function(done) { - var appName = 'some wired !@#$% application_name'; +suite.test('application_name is used', function (done) { + var appName = 'some wired !@#$% application_name' var conf = getConInfo({ - 'application_name' : appName - }); - getAppName(conf, function(res){ - assert.strictEqual(res, appName); + 'application_name': appName + }) + getAppName(conf, function (res) { + assert.strictEqual(res, appName) done() - }); -}); + }) +}) -suite.test('application_name has precedence over fallback_application_name', function(done) { - var appName = 'some wired !@#$% application_name'; - var fbAppName = 'some other strange $$test$$ appname'; +suite.test('application_name has precedence over fallback_application_name', function (done) { + var appName = 'some wired !@#$% application_name' + var fbAppName = 'some other strange $$test$$ appname' var conf = getConInfo({ - 'application_name' : appName , - 'fallback_application_name' : fbAppName - }); - getAppName(conf, function(res){ - assert.strictEqual(res, appName); + 'application_name': appName, + 'fallback_application_name': fbAppName + }) + getAppName(conf, function (res) { + assert.strictEqual(res, appName) done() - }); -}); + }) +}) -suite.test('application_name from connection string', function(done) { - var appName = 'my app'; - var conParams = require(__dirname + '/../../../lib/connection-parameters'); - var conf; +suite.test('application_name from connection string', function (done) { + var appName = 'my app' + var conParams = require(__dirname + '/../../../lib/connection-parameters') + var conf if (process.argv[2]) { - conf = new conParams(process.argv[2]+'?application_name='+appName); + conf = new conParams(process.argv[2] + '?application_name=' + appName) } else { - conf = 'postgres://?application_name='+appName; + conf = 'postgres://?application_name=' + appName } - getAppName(conf, function(res){ - assert.strictEqual(res, appName); + getAppName(conf, function (res) { + assert.strictEqual(res, appName) done() - }); -}); - - + }) +}) // TODO: make the test work for native client too if (!helper.args.native) { - suite.test('application_name is read from the env', function(done) { - var appName = process.env.PGAPPNAME = 'testest'; - getAppName({ }, function(res){ - delete process.env.PGAPPNAME; - assert.strictEqual(res, appName); + suite.test('application_name is read from the env', function (done) { + var appName = process.env.PGAPPNAME = 'testest' + getAppName({ }, function (res) { + delete process.env.PGAPPNAME + assert.strictEqual(res, appName) done() - }); - }); + }) + }) } diff --git a/test/integration/client/array-tests.js b/test/integration/client/array-tests.js index 3185ad2c3..84e97f190 100644 --- a/test/integration/client/array-tests.js +++ b/test/integration/client/array-tests.js @@ -1,177 +1,177 @@ -"use strict"; -var helper = require(__dirname + "/test-helper"); -var pg = helper.pg; +'use strict' +var helper = require(__dirname + '/test-helper') +var pg = helper.pg var suite = new helper.Suite() const pool = new pg.Pool() -pool.connect(assert.calls(function(err, client, release) { - assert(!err); +pool.connect(assert.calls(function (err, client, release) { + assert(!err) - suite.test('nulls', function(done) { - client.query('SELECT $1::text[] as array', [[null]], assert.success(function(result) { - var array = result.rows[0].array; - assert.lengthIs(array, 1); - assert.isNull(array[0]); + suite.test('nulls', function (done) { + client.query('SELECT $1::text[] as array', [[null]], assert.success(function (result) { + var array = result.rows[0].array + assert.lengthIs(array, 1) + assert.isNull(array[0]) done() - })); - }); + })) + }) - suite.test('elements containing JSON-escaped characters', function(done) { - var param = '\\"\\"'; + suite.test('elements containing JSON-escaped characters', function (done) { + var param = '\\"\\"' for (var i = 1; i <= 0x1f; i++) { - param += String.fromCharCode(i); + param += String.fromCharCode(i) } - client.query('SELECT $1::text[] as array', [[param]], assert.success(function(result) { - var array = result.rows[0].array; - assert.lengthIs(array, 1); - assert.equal(array[0], param); + client.query('SELECT $1::text[] as array', [[param]], assert.success(function (result) { + var array = result.rows[0].array + assert.lengthIs(array, 1) + assert.equal(array[0], param) done() - })); - }); + })) + }) suite.test('cleanup', () => release()) pool.connect(assert.calls(function (err, client, release) { - assert(!err); - client.query("CREATE TEMP TABLE why(names text[], numbors integer[])"); - client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log); + assert(!err) + client.query('CREATE TEMP TABLE why(names text[], numbors integer[])') + client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log) suite.test('numbers', function (done) { // client.connection.on('message', console.log) client.query('SELECT numbors FROM why', assert.success(function (result) { - assert.lengthIs(result.rows[0].numbors, 3); - assert.equal(result.rows[0].numbors[0], 1); - assert.equal(result.rows[0].numbors[1], 2); - assert.equal(result.rows[0].numbors[2], 3); + assert.lengthIs(result.rows[0].numbors, 3) + assert.equal(result.rows[0].numbors[0], 1) + assert.equal(result.rows[0].numbors[1], 2) + assert.equal(result.rows[0].numbors[2], 3) done() })) }) suite.test('parses string arrays', function (done) { client.query('SELECT names FROM why', assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 'aaron'); - assert.equal(names[1], 'brian'); - assert.equal(names[2], "a b c"); + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0], 'aaron') + assert.equal(names[1], 'brian') + assert.equal(names[2], 'a b c') done() })) }) suite.test('empty array', function (done) { client.query("SELECT '{}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 0); + var names = result.rows[0].names + assert.lengthIs(names, 0) done() })) }) suite.test('element containing comma', function (done) { client.query("SELECT '{\"joe,bob\",jim}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - assert.equal(names[0], 'joe,bob'); - assert.equal(names[1], 'jim'); + var names = result.rows[0].names + assert.lengthIs(names, 2) + assert.equal(names[0], 'joe,bob') + assert.equal(names[1], 'jim') done() })) }) suite.test('bracket in quotes', function (done) { client.query("SELECT '{\"{\",\"}\"}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); - assert.equal(names[0], '{'); - assert.equal(names[1], '}'); + var names = result.rows[0].names + assert.lengthIs(names, 2) + assert.equal(names[0], '{') + assert.equal(names[1], '}') done() })) }) suite.test('null value', function (done) { client.query("SELECT '{joe,null,bob,\"NULL\"}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 4); - assert.equal(names[0], 'joe'); - assert.equal(names[1], null); - assert.equal(names[2], 'bob'); - assert.equal(names[3], 'NULL'); + var names = result.rows[0].names + assert.lengthIs(names, 4) + assert.equal(names[0], 'joe') + assert.equal(names[1], null) + assert.equal(names[2], 'bob') + assert.equal(names[3], 'NULL') done() })) }) suite.test('element containing quote char', function (done) { client.query("SELECT ARRAY['joe''', 'jim', 'bob\"'] AS names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 'joe\''); - assert.equal(names[1], 'jim'); - assert.equal(names[2], 'bob"'); + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0], 'joe\'') + assert.equal(names[1], 'jim') + assert.equal(names[2], 'bob"') done() })) }) suite.test('nested array', function (done) { client.query("SELECT '{{1,joe},{2,bob}}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 2); + var names = result.rows[0].names + assert.lengthIs(names, 2) - assert.lengthIs(names[0], 2); - assert.equal(names[0][0], '1'); - assert.equal(names[0][1], 'joe'); + assert.lengthIs(names[0], 2) + assert.equal(names[0][0], '1') + assert.equal(names[0][1], 'joe') - assert.lengthIs(names[1], 2); - assert.equal(names[1][0], '2'); - assert.equal(names[1][1], 'bob'); + assert.lengthIs(names[1], 2) + assert.equal(names[1][0], '2') + assert.equal(names[1][1], 'bob') done() })) }) suite.test('integer array', function (done) { client.query("SELECT '{1,2,3}'::integer[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0], 1); - assert.equal(names[1], 2); - assert.equal(names[2], 3); + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0], 1) + assert.equal(names[1], 2) + assert.equal(names[2], 3) done() })) }) suite.test('integer nested array', function (done) { client.query("SELECT '{{1,100},{2,100},{3,100}}'::integer[] as names", assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0][0], 1); - assert.equal(names[0][1], 100); + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0][0], 1) + assert.equal(names[0][1], 100) - assert.equal(names[1][0], 2); - assert.equal(names[1][1], 100); + assert.equal(names[1][0], 2) + assert.equal(names[1][1], 100) - assert.equal(names[2][0], 3); - assert.equal(names[2][1], 100); + assert.equal(names[2][0], 3) + assert.equal(names[2][1], 100) done() })) }) suite.test('JS array parameter', function (done) { - client.query("SELECT $1::integer[] as names", [[[1, 100], [2, 100], [3, 100]]], assert.success(function (result) { - var names = result.rows[0].names; - assert.lengthIs(names, 3); - assert.equal(names[0][0], 1); - assert.equal(names[0][1], 100); - - assert.equal(names[1][0], 2); - assert.equal(names[1][1], 100); - - assert.equal(names[2][0], 3); - assert.equal(names[2][1], 100); - release(); + client.query('SELECT $1::integer[] as names', [[[1, 100], [2, 100], [3, 100]]], assert.success(function (result) { + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0][0], 1) + assert.equal(names[0][1], 100) + + assert.equal(names[1][0], 2) + assert.equal(names[1][1], 100) + + assert.equal(names[2][0], 3) + assert.equal(names[2][1], 100) + release() pool.end(() => { done() }) })) }) })) -})); +})) diff --git a/test/integration/client/big-simple-query-tests.js b/test/integration/client/big-simple-query-tests.js index 7db183f41..5a15dca36 100644 --- a/test/integration/client/big-simple-query-tests.js +++ b/test/integration/client/big-simple-query-tests.js @@ -1,8 +1,8 @@ -"use strict"; -var helper = require("./test-helper"); +'use strict' +var helper = require('./test-helper') var Query = helper.pg.Query -const suite = new helper.Suite(); +const suite = new helper.Suite() /* Test to trigger a bug. @@ -12,75 +12,74 @@ const suite = new helper.Suite(); */ // Big query with a where clouse from supplied value -var big_query_rows_1 = []; -var big_query_rows_2 = []; -var big_query_rows_3 = []; +var big_query_rows_1 = [] +var big_query_rows_2 = [] +var big_query_rows_3 = [] // Works -suite.test('big simple query 1', function(done) { - var client = helper.client(); +suite.test('big simple query 1', function (done) { + var client = helper.client() client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = '' or 1 = 1")) - .on('row', function(row) { big_query_rows_1.push(row); }) - .on('error', function(error) { console.log("big simple query 1 error"); console.log(error); }); + .on('row', function (row) { big_query_rows_1.push(row) }) + .on('error', function (error) { console.log('big simple query 1 error'); console.log(error) }) client.on('drain', () => { client.end() done() - }); -}); + }) +}) // Works -suite.test('big simple query 2', function(done) { - var client = helper.client(); - client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",[''])) - .on('row', function(row) { big_query_rows_2.push(row); }) - .on('error', function(error) { console.log("big simple query 2 error"); console.log(error); }); +suite.test('big simple query 2', function (done) { + var client = helper.client() + client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", [''])) + .on('row', function (row) { big_query_rows_2.push(row) }) + .on('error', function (error) { console.log('big simple query 2 error'); console.log(error) }) client.on('drain', () => { client.end() done() - }); -}); + }) +}) // Fails most of the time with 'invalid byte sequence for encoding "UTF8": 0xb9' or 'insufficient data left in message' // If test 1 and 2 are commented out it works -suite.test('big simple query 3',function(done) { - var client = helper.client(); - client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",[''])) - .on('row', function(row) { big_query_rows_3.push(row); }) - .on('error', function(error) { console.log("big simple query 3 error"); console.log(error); }); +suite.test('big simple query 3', function (done) { + var client = helper.client() + client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", [''])) + .on('row', function (row) { big_query_rows_3.push(row) }) + .on('error', function (error) { console.log('big simple query 3 error'); console.log(error) }) client.on('drain', () => { client.end() done() - }); -}); - -process.on('exit', function() { - assert.equal(big_query_rows_1.length, 26,'big simple query 1 should return 26 rows'); - assert.equal(big_query_rows_2.length, 26,'big simple query 2 should return 26 rows'); - assert.equal(big_query_rows_3.length, 26,'big simple query 3 should return 26 rows'); -}); + }) +}) +process.on('exit', function () { + assert.equal(big_query_rows_1.length, 26, 'big simple query 1 should return 26 rows') + assert.equal(big_query_rows_2.length, 26, 'big simple query 2 should return 26 rows') + assert.equal(big_query_rows_3.length, 26, 'big simple query 3 should return 26 rows') +}) -var runBigQuery = function(client) { - var rows = []; - var q = client.query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1",[''], function(err, result) { - if(err != null) { - console.log(err); - throw Err; +var runBigQuery = function (client) { + var rows = [] + var q = client.query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", [''], function (err, result) { + if (err != null) { + console.log(err) + throw Err } - assert.lengthIs(result.rows, 26); - }); + assert.lengthIs(result.rows, 26) + }) } -suite.test('many times', function(done) { - var client = helper.client(); - for(var i = 0; i < 20; i++) { - runBigQuery(client); +suite.test('many times', function (done) { + var client = helper.client() + for (var i = 0; i < 20; i++) { + runBigQuery(client) } - client.on('drain', function() { - client.end(); - setTimeout(function() { + client.on('drain', function () { + client.end() + setTimeout(function () { done() - //let client disconnect fully + // let client disconnect fully }, 100) - }); + }) }) diff --git a/test/integration/client/configuration-tests.js b/test/integration/client/configuration-tests.js index 8bd065e91..9d3b7f5ab 100644 --- a/test/integration/client/configuration-tests.js +++ b/test/integration/client/configuration-tests.js @@ -1,17 +1,17 @@ -"use strict"; -var helper = require('./test-helper'); -var pg = helper.pg; +'use strict' +var helper = require('./test-helper') +var pg = helper.pg -var suite = new helper.Suite(); +var suite = new helper.Suite() -//clear process.env -var realEnv = {}; -for(var key in process.env) { - realEnv[key] = process.env[key]; - if(!key.indexOf('PG')) delete process.env[key]; +// clear process.env +var realEnv = {} +for (var key in process.env) { + realEnv[key] = process.env[key] + if (!key.indexOf('PG')) delete process.env[key] } -suite.test('default values are used in new clients', function() { +suite.test('default values are used in new clients', function () { assert.same(pg.defaults, { user: process.env.USER, database: process.env.USER, @@ -21,7 +21,7 @@ suite.test('default values are used in new clients', function() { poolSize: 10 }) - var client = new pg.Client(); + var client = new pg.Client() assert.same(client, { user: process.env.USER, database: process.env.USER, @@ -30,16 +30,15 @@ suite.test('default values are used in new clients', function() { }) }) - -suite.test('modified values are passed to created clients', function() { +suite.test('modified values are passed to created clients', function () { pg.defaults.user = 'boom' pg.defaults.password = 'zap' pg.defaults.database = 'pow' pg.defaults.port = 1234 pg.defaults.host = 'blam' - var client = new Client(); - assert.same(client,{ + var client = new Client() + assert.same(client, { user: 'boom', password: 'zap', database: 'pow', @@ -49,8 +48,8 @@ suite.test('modified values are passed to created clients', function() { }) suite.test('cleanup', () => { - //restore process.env + // restore process.env for (var key in realEnv) { - process.env[key] = realEnv[key]; + process.env[key] = realEnv[key] } }) diff --git a/test/integration/client/custom-types-tests.js b/test/integration/client/custom-types-tests.js index db1433569..99e04d01d 100644 --- a/test/integration/client/custom-types-tests.js +++ b/test/integration/client/custom-types-tests.js @@ -1,6 +1,6 @@ -"use strict"; -const helper = require('./test-helper'); -const Client = helper.pg.Client; +'use strict' +const helper = require('./test-helper') +const Client = helper.pg.Client const suite = new helper.Suite() const client = new Client({ @@ -13,8 +13,8 @@ suite.test('custom type parser in client config', (done) => { client.connect() .then(() => { client.query('SELECT NOW() as val', assert.success(function (res) { - assert.equal(res.rows[0].val, 'okay!'); - client.end().then(done); - })); + assert.equal(res.rows[0].val, 'okay!') + client.end().then(done) + })) }) }) diff --git a/test/integration/client/empty-query-tests.js b/test/integration/client/empty-query-tests.js index d02c142df..975dc0f66 100644 --- a/test/integration/client/empty-query-tests.js +++ b/test/integration/client/empty-query-tests.js @@ -1,21 +1,20 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') const suite = new helper.Suite() -suite.test("empty query message handling", function(done) { - const client = helper.client(); - assert.emits(client, 'drain', function() { - client.end(done); - }); - client.query({text: ""}); -}); - -suite.test('callback supported', function(done) { - const client = helper.client(); - client.query("", function(err, result) { - assert(!err); - assert.empty(result.rows); +suite.test('empty query message handling', function (done) { + const client = helper.client() + assert.emits(client, 'drain', function () { client.end(done) }) + client.query({text: ''}) }) +suite.test('callback supported', function (done) { + const client = helper.client() + client.query('', function (err, result) { + assert(!err) + assert.empty(result.rows) + client.end(done) + }) +}) diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index e4d779031..55372d141 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -1,19 +1,19 @@ -"use strict"; +'use strict' -var helper = require('./test-helper'); -var util = require('util'); +var helper = require('./test-helper') +var util = require('util') var pg = helper.pg const Client = pg.Client -var createErorrClient = function() { - var client = helper.client(); - client.once('error', function(err) { - assert.fail('Client shoud not throw error during query execution'); - }); - client.on('drain', client.end.bind(client)); - return client; -}; +var createErorrClient = function () { + var client = helper.client() + client.once('error', function (err) { + assert.fail('Client shoud not throw error during query execution') + }) + client.on('drain', client.end.bind(client)) + return client +} const suite = new helper.Suite('error handling') @@ -50,131 +50,129 @@ suite.test('re-using connections results in promise rejection', (done) => { }) }) -suite.test('query receives error on client shutdown', function(done) { - var client = new Client(); - client.connect(assert.success(function() { +suite.test('query receives error on client shutdown', function (done) { + var client = new Client() + client.connect(assert.success(function () { const config = { text: 'select pg_sleep(5)', name: 'foobar' } - let queryError; - client.query(new pg.Query(config), assert.calls(function(err, res) { + let queryError + client.query(new pg.Query(config), assert.calls(function (err, res) { assert(err instanceof Error) queryError = err - })); + })) setTimeout(() => client.end(), 50) client.once('end', () => { assert(queryError instanceof Error) done() }) - })); -}); - - var ensureFuture = function (testClient, done) { - var goodQuery = testClient.query(new pg.Query("select age from boom")); - assert.emits(goodQuery, 'row', function (row) { - assert.equal(row.age, 28); - done(); - }); - }; - - suite.test("when query is parsing", (done) => { - var client = createErorrClient(); + })) +}) - var q = client.query({ text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);" }); +var ensureFuture = function (testClient, done) { + var goodQuery = testClient.query(new pg.Query('select age from boom')) + assert.emits(goodQuery, 'row', function (row) { + assert.equal(row.age, 28) + done() + }) +} +suite.test('when query is parsing', (done) => { + var client = createErorrClient() - //this query wont parse since there isn't a table named bang - var query = client.query(new pg.Query({ - text: "select * from bang where name = $1", - values: ['0'] - })); + var q = client.query({ text: 'CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);' }) - assert.emits(query, 'error', function (err) { - ensureFuture(client, done); - }); - }); + // this query wont parse since there isn't a table named bang + var query = client.query(new pg.Query({ + text: 'select * from bang where name = $1', + values: ['0'] + })) - suite.test("when a query is binding", function (done) { - var client = createErorrClient(); + assert.emits(query, 'error', function (err) { + ensureFuture(client, done) + }) +}) - var q = client.query({ text: "CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);" }); +suite.test('when a query is binding', function (done) { + var client = createErorrClient() + var q = client.query({ text: 'CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);' }) - var query = client.query(new pg.Query({ - text: 'select * from boom where age = $1', - values: ['asldkfjasdf'] - })); + var query = client.query(new pg.Query({ + text: 'select * from boom where age = $1', + values: ['asldkfjasdf'] + })) - assert.emits(query, 'error', function (err) { - assert.equal(err.severity, "ERROR"); - ensureFuture(client, done); - }); - }); + assert.emits(query, 'error', function (err) { + assert.equal(err.severity, 'ERROR') + ensureFuture(client, done) + }) +}) -suite.test('non-query error with callback', function(done) { +suite.test('non-query error with callback', function (done) { var client = new Client({ - user:'asldkfjsadlfkj' - }); - client.connect(assert.calls(function(error, client) { + user: 'asldkfjsadlfkj' + }) + client.connect(assert.calls(function (error, client) { assert(error instanceof Error) done() - })); -}); + })) +}) -suite.test('non-error calls supplied callback', function(done) { +suite.test('non-error calls supplied callback', function (done) { var client = new Client({ user: helper.args.user, password: helper.args.password, host: helper.args.host, port: helper.args.port, database: helper.args.database - }); + }) - client.connect(assert.calls(function(err) { - assert.ifError(err); - client.end(done); + client.connect(assert.calls(function (err) { + assert.ifError(err) + client.end(done) })) -}); +}) suite.test('when connecting to an invalid host with callback', function (done) { var client = new Client({ - user: 'very invalid username', - }); - client.connect(function(error, client) { - assert(error instanceof Error); - done(); - }); -}); - -suite.test('when connecting to invalid host with promise', function(done) { + user: 'very invalid username' + }) + client.connect(function (error, client) { + assert(error instanceof Error) + done() + }) +}) + +suite.test('when connecting to invalid host with promise', function (done) { var client = new Client({ user: 'very invalid username' - }); - client.connect().catch((e) => done()); -}); + }) + client.connect().catch((e) => done()) +}) -suite.test('non-query error', function(done) { +suite.test('non-query error', function (done) { var client = new Client({ - user:'asldkfjsadlfkj' - }); + user: 'asldkfjsadlfkj' + }) client.connect() .catch(e => { assert(e instanceof Error) done() }) -}); +}) suite.test('within a simple query', (done) => { - var client = createErorrClient(); + var client = createErorrClient() - var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")); + var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")) - assert.emits(query, 'error', function(error) { - assert.equal(error.severity, "ERROR"); - done(); - }); -}); + assert.emits(query, 'error', function (error) { + assert.equal(error.severity, 'ERROR') + done() + }) +}) suite.test('connected, idle client error', (done) => { const client = new Client() diff --git a/test/integration/client/huge-numeric-tests.js b/test/integration/client/huge-numeric-tests.js index a5bdbc8a0..111adf200 100644 --- a/test/integration/client/huge-numeric-tests.js +++ b/test/integration/client/huge-numeric-tests.js @@ -1,22 +1,22 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') const pool = new helper.pg.Pool() -pool.connect(assert.success(function(client, done) { - var types = require('pg-types'); - //1231 = numericOID - types.setTypeParser(1700, function(){ - return 'yes'; +pool.connect(assert.success(function (client, done) { + var types = require('pg-types') + // 1231 = numericOID + types.setTypeParser(1700, function () { + return 'yes' }) - types.setTypeParser(1700, 'binary', function(){ - return 'yes'; + types.setTypeParser(1700, 'binary', function () { + return 'yes' }) - var bignum = '294733346389144765940638005275322203805'; - client.query('CREATE TEMP TABLE bignumz(id numeric)'); - client.query('INSERT INTO bignumz(id) VALUES ($1)', [bignum]); - client.query('SELECT * FROM bignumz', assert.success(function(result) { + var bignum = '294733346389144765940638005275322203805' + client.query('CREATE TEMP TABLE bignumz(id numeric)') + client.query('INSERT INTO bignumz(id) VALUES ($1)', [bignum]) + client.query('SELECT * FROM bignumz', assert.success(function (result) { assert.equal(result.rows[0].id, 'yes') - done(); + done() pool.end() })) -})); +})) diff --git a/test/integration/client/json-type-parsing-tests.js b/test/integration/client/json-type-parsing-tests.js index 77c5469a7..63684d96d 100644 --- a/test/integration/client/json-type-parsing-tests.js +++ b/test/integration/client/json-type-parsing-tests.js @@ -1,28 +1,28 @@ -"use strict"; -var helper = require('./test-helper'); -var assert = require('assert'); +'use strict' +var helper = require('./test-helper') +var assert = require('assert') const pool = new helper.pg.Pool() pool.connect(assert.success(function (client, done) { helper.versionGTE(client, '9.2.0', assert.success(function (jsonSupported) { if (!jsonSupported) { - console.log('skip json test on older versions of postgres'); - done(); - return pool.end(); + console.log('skip json test on older versions of postgres') + done() + return pool.end() } - client.query('CREATE TEMP TABLE stuff(id SERIAL PRIMARY KEY, data JSON)'); - var value = { name: 'Brian', age: 250, alive: true, now: new Date() }; - client.query('INSERT INTO stuff (data) VALUES ($1)', [value]); + client.query('CREATE TEMP TABLE stuff(id SERIAL PRIMARY KEY, data JSON)') + var value = { name: 'Brian', age: 250, alive: true, now: new Date() } + client.query('INSERT INTO stuff (data) VALUES ($1)', [value]) client.query('SELECT * FROM stuff', assert.success(function (result) { - assert.equal(result.rows.length, 1); - assert.equal(typeof result.rows[0].data, 'object'); - var row = result.rows[0].data; - assert.strictEqual(row.name, value.name); - assert.strictEqual(row.age, value.age); - assert.strictEqual(row.alive, value.alive); - assert.equal(JSON.stringify(row.now), JSON.stringify(value.now)); - done(); + assert.equal(result.rows.length, 1) + assert.equal(typeof result.rows[0].data, 'object') + var row = result.rows[0].data + assert.strictEqual(row.name, value.name) + assert.strictEqual(row.age, value.age) + assert.strictEqual(row.alive, value.alive) + assert.equal(JSON.stringify(row.now), JSON.stringify(value.now)) + done() pool.end() - })); - })); -})); + })) + })) +})) diff --git a/test/integration/client/network-partition-tests.js b/test/integration/client/network-partition-tests.js index 704f7fdfe..95eca8e73 100644 --- a/test/integration/client/network-partition-tests.js +++ b/test/integration/client/network-partition-tests.js @@ -1,11 +1,11 @@ -"use strict"; +'use strict' var buffers = require('../../test-buffers') var helper = require('./test-helper') var suite = new helper.Suite() var net = require('net') -var Server = function(response) { +var Server = function (response) { this.server = undefined this.socket = undefined this.response = response @@ -38,7 +38,7 @@ Server.prototype.start = function (cb) { var options = { host: 'localhost', - port: port, + port: port } this.server.listen(options.port, options.host, function () { cb(options) @@ -55,7 +55,7 @@ Server.prototype.close = function (cb) { var testServer = function (server, cb) { // wait for our server to start - server.start(function(options) { + server.start(function (options) { // connect a client to it var client = new helper.Client(options) client.connect() @@ -66,7 +66,7 @@ var testServer = function (server, cb) { }) // after 50 milliseconds, drop the client - setTimeout(function() { + setTimeout(function () { server.drop() }, 50) diff --git a/test/integration/client/no-data-tests.js b/test/integration/client/no-data-tests.js index a4ab36fb5..46ea45662 100644 --- a/test/integration/client/no-data-tests.js +++ b/test/integration/client/no-data-tests.js @@ -1,32 +1,30 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') const suite = new helper.Suite() - -suite.test("noData message handling", function() { - - var client = helper.client(); +suite.test('noData message handling', function () { + var client = helper.client() var q = client.query({ name: 'boom', text: 'create temp table boom(id serial, size integer)' - }); + }) client.query({ name: 'insert', text: 'insert into boom(size) values($1)', values: [100] - }, function(err, result) { - if(err) { - console.log(err); - throw err; + }, function (err, result) { + if (err) { + console.log(err) + throw err } - }); + }) client.query({ name: 'insert', values: [101] - }); + }) var query = client.query({ name: 'fetch', @@ -35,7 +33,7 @@ suite.test("noData message handling", function() { }, (err, res) => { var row = res.rows[0] assert.strictEqual(row.size, 100) - }); + }) - client.on('drain', client.end.bind(client)); -}); + client.on('drain', client.end.bind(client)) +}) diff --git a/test/integration/client/no-row-result-tests.js b/test/integration/client/no-row-result-tests.js index 4ff289951..e52d113d8 100644 --- a/test/integration/client/no-row-result-tests.js +++ b/test/integration/client/no-row-result-tests.js @@ -1,28 +1,28 @@ -"use strict"; -var helper = require("./test-helper"); -var pg = helper.pg; -const suite = new helper.Suite(); -const pool = new pg.Pool(); +'use strict' +var helper = require('./test-helper') +var pg = helper.pg +const suite = new helper.Suite() +const pool = new pg.Pool() -suite.test("can access results when no rows are returned", function (done) { +suite.test('can access results when no rows are returned', function (done) { var checkResult = function (result) { - assert(result.fields, "should have fields definition"); - assert.equal(result.fields.length, 1); - assert.equal(result.fields[0].name, "val"); - assert.equal(result.fields[0].dataTypeID, 25); - }; + assert(result.fields, 'should have fields definition') + assert.equal(result.fields.length, 1) + assert.equal(result.fields[0].name, 'val') + assert.equal(result.fields[0].dataTypeID, 25) + } pool.connect( assert.success(function (client, release) { - const q = new pg.Query("select $1::text as val limit 0", ["hi"]); + const q = new pg.Query('select $1::text as val limit 0', ['hi']) var query = client.query(q, assert.success(function (result) { - checkResult(result); - release(); - pool.end(done); + checkResult(result) + release() + pool.end(done) }) - ); + ) - assert.emits(query, "end", checkResult); + assert.emits(query, 'end', checkResult) }) - ); -}); + ) +}) diff --git a/test/integration/client/notice-tests.js b/test/integration/client/notice-tests.js index 9c682050a..f3dc5090e 100644 --- a/test/integration/client/notice-tests.js +++ b/test/integration/client/notice-tests.js @@ -1,34 +1,34 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') const suite = new helper.Suite() suite.test('emits notify message', function (done) { - var client = helper.client(); + var client = helper.client() client.query('LISTEN boom', assert.calls(function () { - var otherClient = helper.client(); + var otherClient = helper.client() var bothEmitted = -1 otherClient.query('LISTEN boom', assert.calls(function () { assert.emits(client, 'notification', function (msg) { - //make sure PQfreemem doesn't invalidate string pointers + // make sure PQfreemem doesn't invalidate string pointers setTimeout(function () { - assert.equal(msg.channel, 'boom'); - assert.ok(msg.payload == 'omg!' /*9.x*/ || msg.payload == '' /*8.x*/, "expected blank payload or correct payload but got " + msg.message) + assert.equal(msg.channel, 'boom') + assert.ok(msg.payload == 'omg!' /* 9.x */ || msg.payload == '' /* 8.x */, 'expected blank payload or correct payload but got ' + msg.message) client.end(++bothEmitted ? done : undefined) }, 100) - }); + }) assert.emits(otherClient, 'notification', function (msg) { - assert.equal(msg.channel, 'boom'); - otherClient.end(++bothEmitted ? done : undefined); - }); + assert.equal(msg.channel, 'boom') + otherClient.end(++bothEmitted ? done : undefined) + }) client.query("NOTIFY boom, 'omg!'", function (err, q) { if (err) { - //notify not supported with payload on 8.x - client.query("NOTIFY boom") + // notify not supported with payload on 8.x + client.query('NOTIFY boom') } - }); - })); - })); + }) + })) + })) }) // this test fails on travis due to their config @@ -37,8 +37,8 @@ suite.test('emits notice message', false, function (done) { console.error('need to get notice message working on native') return done() } - //TODO this doesn't work on all versions of postgres - var client = helper.client(); + // TODO this doesn't work on all versions of postgres + var client = helper.client() const text = ` DO language plpgsql $$ BEGIN @@ -47,10 +47,10 @@ END $$; ` client.query(text, () => { - client.end(); - }); + client.end() + }) assert.emits(client, 'notice', function (notice) { - assert.ok(notice != null); - done(); - }); + assert.ok(notice != null) + done() + }) }) diff --git a/test/integration/client/parse-int-8-tests.js b/test/integration/client/parse-int-8-tests.js index 920f5558f..193689045 100644 --- a/test/integration/client/parse-int-8-tests.js +++ b/test/integration/client/parse-int-8-tests.js @@ -1,29 +1,29 @@ -"use strict"; +'use strict' -var helper = require('../test-helper'); -var pg = helper.pg; +var helper = require('../test-helper') +var pg = helper.pg const suite = new helper.Suite() const pool = new pg.Pool(helper.config) -suite.test('ability to turn on and off parser', function() { - if(helper.args.binary) return false; - pool.connect(assert.success(function(client, done) { - pg.defaults.parseInt8 = true; - client.query('CREATE TEMP TABLE asdf(id SERIAL PRIMARY KEY)'); - client.query('SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', assert.success(function(res) { - assert.strictEqual(0, res.rows[0].count); - assert.strictEqual(1, res.rows[0].array[0]); - assert.strictEqual(2, res.rows[0].array[1]); - assert.strictEqual(3, res.rows[0].array[2]); - pg.defaults.parseInt8 = false; - client.query('SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', assert.success(function(res) { - done(); - assert.strictEqual('0', res.rows[0].count); - assert.strictEqual('1', res.rows[0].array[0]); - assert.strictEqual('2', res.rows[0].array[1]); - assert.strictEqual('3', res.rows[0].array[2]); - pool.end(); - })); - })); - })); -}); +suite.test('ability to turn on and off parser', function () { + if (helper.args.binary) return false + pool.connect(assert.success(function (client, done) { + pg.defaults.parseInt8 = true + client.query('CREATE TEMP TABLE asdf(id SERIAL PRIMARY KEY)') + client.query('SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', assert.success(function (res) { + assert.strictEqual(0, res.rows[0].count) + assert.strictEqual(1, res.rows[0].array[0]) + assert.strictEqual(2, res.rows[0].array[1]) + assert.strictEqual(3, res.rows[0].array[2]) + pg.defaults.parseInt8 = false + client.query('SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', assert.success(function (res) { + done() + assert.strictEqual('0', res.rows[0].count) + assert.strictEqual('1', res.rows[0].array[0]) + assert.strictEqual('2', res.rows[0].array[1]) + assert.strictEqual('3', res.rows[0].array[2]) + pool.end() + })) + })) + })) +}) diff --git a/test/integration/client/prepared-statement-tests.js b/test/integration/client/prepared-statement-tests.js index 9b00f9d8c..6fdf72f6d 100644 --- a/test/integration/client/prepared-statement-tests.js +++ b/test/integration/client/prepared-statement-tests.js @@ -1,136 +1,132 @@ -"use strict"; -var helper = require('./test-helper'); -var Query = helper.pg.Query; +'use strict' +var helper = require('./test-helper') +var Query = helper.pg.Query var suite = new helper.Suite() -;(function() { +;(function () { + var client = helper.client() + client.on('drain', client.end.bind(client)) - var client = helper.client(); - client.on('drain', client.end.bind(client)); + var queryName = 'user by age and like name' + var parseCount = 0 - var queryName = "user by age and like name"; - var parseCount = 0; - - suite.test("first named prepared statement", function(done) { + suite.test('first named prepared statement', function (done) { var query = client.query(new Query({ text: 'select name from person where age <= $1 and name LIKE $2', values: [20, 'Bri%'], name: queryName - })); + })) - assert.emits(query, 'row', function(row) { - assert.equal(row.name, 'Brian'); - }); + assert.emits(query, 'row', function (row) { + assert.equal(row.name, 'Brian') + }) query.on('end', () => done()) - }); + }) - suite.test("second named prepared statement with same name & text", function(done) { + suite.test('second named prepared statement with same name & text', function (done) { var cachedQuery = client.query(new Query({ text: 'select name from person where age <= $1 and name LIKE $2', name: queryName, values: [10, 'A%'] - })); + })) - assert.emits(cachedQuery, 'row', function(row) { - assert.equal(row.name, 'Aaron'); - }); + assert.emits(cachedQuery, 'row', function (row) { + assert.equal(row.name, 'Aaron') + }) cachedQuery.on('end', () => done()) - }); + }) - suite.test("with same name, but without query text", function(done) { + suite.test('with same name, but without query text', function (done) { var q = client.query(new Query({ name: queryName, values: [30, '%n%'] - })); + })) - assert.emits(q, 'row', function(row) { - assert.equal(row.name, "Aaron"); + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Aaron') // test second row is emitted as well - assert.emits(q, 'row', function(row) { - assert.equal(row.name, "Brian"); - }); - }); + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Brian') + }) + }) q.on('end', () => done()) - }); -})(); - -;(function() { - var statementName = "differ"; - var statement1 = "select count(*)::int4 as count from person"; - var statement2 = "select count(*)::int4 as count from person where age < $1"; + }) +})() - var client1 = helper.client(); - var client2 = helper.client(); +;(function () { + var statementName = 'differ' + var statement1 = 'select count(*)::int4 as count from person' + var statement2 = 'select count(*)::int4 as count from person where age < $1' - suite.test("client 1 execution", function(done) { + var client1 = helper.client() + var client2 = helper.client() + suite.test('client 1 execution', function (done) { var query = client1.query({ name: statementName, text: statement1 }, (err, res) => { - assert(!err); - assert.equal(res.rows[0].count, 26); + assert(!err) + assert.equal(res.rows[0].count, 26) done() - }); - }); + }) + }) - suite.test('client 2 execution', function(done) { + suite.test('client 2 execution', function (done) { var query = client2.query(new Query({ name: statementName, text: statement2, values: [11] - })); + })) - assert.emits(query, 'row', function(row) { - assert.equal(row.count, 1); - }); + assert.emits(query, 'row', function (row) { + assert.equal(row.count, 1) + }) - assert.emits(query, 'end', function() { - done(); - }); - }); + assert.emits(query, 'end', function () { + done() + }) + }) suite.test('clean up clients', () => { return client1.end().then(() => client2.end()) - }); - -})(); + }) +})() -;(function() { - var client = helper.client(); - client.query('CREATE TEMP TABLE zoom(name varchar(100));'); - client.query("INSERT INTO zoom (name) VALUES ('zed')"); - client.query("INSERT INTO zoom (name) VALUES ('postgres')"); - client.query("INSERT INTO zoom (name) VALUES ('node postgres')"); +;(function () { + var client = helper.client() + client.query('CREATE TEMP TABLE zoom(name varchar(100));') + client.query("INSERT INTO zoom (name) VALUES ('zed')") + client.query("INSERT INTO zoom (name) VALUES ('postgres')") + client.query("INSERT INTO zoom (name) VALUES ('node postgres')") var checkForResults = function (q) { assert.emits(q, 'row', function (row) { - assert.equal(row.name, 'node postgres'); + assert.equal(row.name, 'node postgres') assert.emits(q, 'row', function (row) { - assert.equal(row.name, 'postgres'); + assert.equal(row.name, 'postgres') assert.emits(q, 'row', function (row) { - assert.equal(row.name, 'zed'); + assert.equal(row.name, 'zed') }) - }); + }) }) - }; + } suite.test('with small row count', function (done) { var query = client.query(new Query({ name: 'get names', - text: "SELECT name FROM zoom ORDER BY name", + text: 'SELECT name FROM zoom ORDER BY name', rows: 1 - }, done)); - - checkForResults(query); + }, done)) + checkForResults(query) }) suite.test('with large row count', function (done) { @@ -139,7 +135,7 @@ var suite = new helper.Suite() text: 'SELECT name FROM zoom ORDER BY name', rows: 1000 }, done)) - checkForResults(query); + checkForResults(query) }) suite.test('cleanup', () => client.end()) diff --git a/test/integration/client/promise-api-tests.js b/test/integration/client/promise-api-tests.js index 45083a1bb..d06132601 100644 --- a/test/integration/client/promise-api-tests.js +++ b/test/integration/client/promise-api-tests.js @@ -1,8 +1,8 @@ -"use strict"; -'use strict'; +'use strict' +'use strict' const helper = require('./test-helper') -const pg = helper.pg; +const pg = helper.pg const suite = new helper.Suite() @@ -24,7 +24,6 @@ suite.test('valid connection completes promise', () => { }) }) - suite.test('invalid connection rejects promise', (done) => { const client = new pg.Client({ host: 'alksdjflaskdfj' }) return client.connect() diff --git a/test/integration/client/query-as-promise-tests.js b/test/integration/client/query-as-promise-tests.js index 52487a7d4..625a33392 100644 --- a/test/integration/client/query-as-promise-tests.js +++ b/test/integration/client/query-as-promise-tests.js @@ -1,8 +1,8 @@ -"use strict"; -var helper = require(__dirname + '/../test-helper'); -var pg = helper.pg; +'use strict' +var helper = require(__dirname + '/../test-helper') +var pg = helper.pg -process.on('unhandledRejection', function(e) { +process.on('unhandledRejection', function (e) { console.error(e, e.stack) process.exit(1) }) diff --git a/test/integration/client/query-column-names-tests.js b/test/integration/client/query-column-names-tests.js index a670bae3b..cc5a42b56 100644 --- a/test/integration/client/query-column-names-tests.js +++ b/test/integration/client/query-column-names-tests.js @@ -1,15 +1,15 @@ -"use strict"; -var helper = require(__dirname + '/../test-helper'); -var pg = helper.pg; +'use strict' +var helper = require(__dirname + '/../test-helper') +var pg = helper.pg new helper.Suite().test('support for complex column names', function () { const pool = new pg.Pool() pool.connect(assert.success(function (client, done) { - client.query("CREATE TEMP TABLE t ( \"complex''column\" TEXT )"); + client.query("CREATE TEMP TABLE t ( \"complex''column\" TEXT )") client.query('SELECT * FROM t', assert.success(function (res) { - done(); - assert.strictEqual(res.fields[0].name, "complex''column"); - pool.end(); - })); - })); -}); + done() + assert.strictEqual(res.fields[0].name, "complex''column") + pool.end() + })) + })) +}) diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index f16f96f66..a29c41a0b 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -1,99 +1,98 @@ -"use strict"; -var helper = require('./test-helper'); -var Query = helper.pg.Query; -var util = require('util'); +'use strict' +var helper = require('./test-helper') +var Query = helper.pg.Query +var util = require('util') -var suite = new helper.Suite(); +var suite = new helper.Suite() -suite.test('client end during query execution of prepared statement', function(done) { - var client = new Client(); - client.connect(assert.success(function() { - - var sleepQuery = 'select pg_sleep($1)'; +suite.test('client end during query execution of prepared statement', function (done) { + var client = new Client() + client.connect(assert.success(function () { + var sleepQuery = 'select pg_sleep($1)' var queryConfig = { name: 'sleep query', text: sleepQuery, - values: [5], + values: [5] } var queryInstance = new Query(queryConfig, assert.calls(function (err, result) { - assert.equal(err.message, 'Connection terminated'); - done(); + assert.equal(err.message, 'Connection terminated') + done() })) - var query1 = client.query(queryInstance); + var query1 = client.query(queryInstance) query1.on('error', function (err) { - assert.fail('Prepared statement should not emit error'); - }); + assert.fail('Prepared statement should not emit error') + }) query1.on('row', function (row) { - assert.fail('Prepared statement should not emit row'); - }); + assert.fail('Prepared statement should not emit row') + }) query1.on('end', function (err) { - assert.fail('Prepared statement when executed should not return before being killed'); - }); + assert.fail('Prepared statement when executed should not return before being killed') + }) - client.end(); - })); -}); + client.end() + })) +}) -function killIdleQuery(targetQuery, cb) { - var client2 = new Client(helper.args); +function killIdleQuery (targetQuery, cb) { + var client2 = new Client(helper.args) var pidColName = 'procpid' - var queryColName = 'current_query'; - client2.connect(assert.success(function() { - helper.versionGTE(client2, '9.2.0', assert.success(function(isGreater) { - if(isGreater) { - pidColName = 'pid'; - queryColName = 'query'; + var queryColName = 'current_query' + client2.connect(assert.success(function () { + helper.versionGTE(client2, '9.2.0', assert.success(function (isGreater) { + if (isGreater) { + pidColName = 'pid' + queryColName = 'query' } - var killIdleQuery = "SELECT " + pidColName + ", (SELECT pg_terminate_backend(" + pidColName + ")) AS killed FROM pg_stat_activity WHERE " + queryColName + " = $1"; - client2.query(killIdleQuery, [targetQuery], assert.calls(function(err, res) { - assert.ifError(err); - assert.equal(res.rows.length, 1); - client2.end(cb); - assert.emits(client2, 'end'); - })); - })); - })); + var killIdleQuery = 'SELECT ' + pidColName + ', (SELECT pg_terminate_backend(' + pidColName + ')) AS killed FROM pg_stat_activity WHERE ' + queryColName + ' = $1' + client2.query(killIdleQuery, [targetQuery], assert.calls(function (err, res) { + assert.ifError(err) + assert.equal(res.rows.length, 1) + client2.end(cb) + assert.emits(client2, 'end') + })) + })) + })) } -suite.test('query killed during query execution of prepared statement', function(done) { - if(helper.args.native) { - return done(); +suite.test('query killed during query execution of prepared statement', function (done) { + if (helper.args.native) { + return done() } - var client = new Client(helper.args); - client.connect(assert.success(function() { - var sleepQuery = 'select pg_sleep($1)'; + var client = new Client(helper.args) + client.connect(assert.success(function () { + var sleepQuery = 'select pg_sleep($1)' const queryConfig = { name: 'sleep query', text: sleepQuery, - values: [5], - }; + values: [5] + } // client should emit an error because it is unexpectedly disconnected assert.emits(client, 'error') - var query1 = client.query(new Query(queryConfig), assert.calls(function(err, result) { - assert.equal(err.message, 'terminating connection due to administrator command'); - })); + var query1 = client.query(new Query(queryConfig), assert.calls(function (err, result) { + assert.equal(err.message, 'terminating connection due to administrator command') + })) - query1.on('error', function(err) { - assert.fail('Prepared statement should not emit error'); - }); + query1.on('error', function (err) { + assert.fail('Prepared statement should not emit error') + }) - query1.on('row', function(row) { - assert.fail('Prepared statement should not emit row'); - }); + query1.on('row', function (row) { + assert.fail('Prepared statement should not emit row') + }) - query1.on('end', function(err) { - assert.fail('Prepared statement when executed should not return before being killed'); - }); + query1.on('end', function (err) { + assert.fail('Prepared statement when executed should not return before being killed') + }) - killIdleQuery(sleepQuery, done); - })); -}); + killIdleQuery(sleepQuery, done) + })) +}) diff --git a/test/integration/client/quick-disconnect-tests.js b/test/integration/client/quick-disconnect-tests.js index 76a825ac1..066411fc8 100644 --- a/test/integration/client/quick-disconnect-tests.js +++ b/test/integration/client/quick-disconnect-tests.js @@ -1,8 +1,8 @@ -"use strict"; -//test for issue #320 +'use strict' +// test for issue #320 // -var helper = require('./test-helper'); +var helper = require('./test-helper') -var client = new helper.pg.Client(helper.config); -client.connect(); -client.end(); +var client = new helper.pg.Client(helper.config) +client.connect() +client.end() diff --git a/test/integration/client/result-metadata-tests.js b/test/integration/client/result-metadata-tests.js index 5b683a3ad..0f2e7e763 100644 --- a/test/integration/client/result-metadata-tests.js +++ b/test/integration/client/result-metadata-tests.js @@ -1,32 +1,32 @@ -"use strict"; -var helper = require("./test-helper"); -var pg = helper.pg; +'use strict' +var helper = require('./test-helper') +var pg = helper.pg const pool = new pg.Pool() -new helper.Suite().test('should return insert metadata', function() { - pool.connect(assert.calls(function(err, client, done) { - assert(!err); +new helper.Suite().test('should return insert metadata', function () { + pool.connect(assert.calls(function (err, client, done) { + assert(!err) - helper.versionGTE(client, '9.0.0', assert.success(function(hasRowCount) { - client.query("CREATE TEMP TABLE zugzug(name varchar(10))", assert.calls(function(err, result) { - assert(!err); - assert.equal(result.oid, null); - assert.equal(result.command, 'CREATE'); + helper.versionGTE(client, '9.0.0', assert.success(function (hasRowCount) { + client.query('CREATE TEMP TABLE zugzug(name varchar(10))', assert.calls(function (err, result) { + assert(!err) + assert.equal(result.oid, null) + assert.equal(result.command, 'CREATE') - var q = client.query("INSERT INTO zugzug(name) VALUES('more work?')", assert.calls(function(err, result) { - assert(!err); - assert.equal(result.command, "INSERT"); - assert.equal(result.rowCount, 1); + var q = client.query("INSERT INTO zugzug(name) VALUES('more work?')", assert.calls(function (err, result) { + assert(!err) + assert.equal(result.command, 'INSERT') + assert.equal(result.rowCount, 1) - client.query('SELECT * FROM zugzug', assert.calls(function(err, result) { - assert(!err); - if(hasRowCount) assert.equal(result.rowCount, 1); - assert.equal(result.command, 'SELECT'); - done(); - process.nextTick(pool.end.bind(pool)); - })); - })); - })); - })); - })); -}); + client.query('SELECT * FROM zugzug', assert.calls(function (err, result) { + assert(!err) + if (hasRowCount) assert.equal(result.rowCount, 1) + assert.equal(result.command, 'SELECT') + done() + process.nextTick(pool.end.bind(pool)) + })) + })) + })) + })) + })) +}) diff --git a/test/integration/client/results-as-array-tests.js b/test/integration/client/results-as-array-tests.js index 45398c05c..b6b00ef71 100644 --- a/test/integration/client/results-as-array-tests.js +++ b/test/integration/client/results-as-array-tests.js @@ -1,31 +1,31 @@ -"use strict"; -var util = require('util'); -var helper = require('./test-helper'); +'use strict' +var util = require('util') +var helper = require('./test-helper') -var Client = helper.Client; +var Client = helper.Client -var conInfo = helper.config; +var conInfo = helper.config -test('returns results as array', function() { - var client = new Client(conInfo); - var checkRow = function(row) { - assert(util.isArray(row), 'row should be an array'); - assert.equal(row.length, 4); - assert.equal(row[0].getFullYear(), new Date().getFullYear()); - assert.strictEqual(row[1], 1); - assert.strictEqual(row[2], 'hai'); - assert.strictEqual(row[3], null); +test('returns results as array', function () { + var client = new Client(conInfo) + var checkRow = function (row) { + assert(util.isArray(row), 'row should be an array') + assert.equal(row.length, 4) + assert.equal(row[0].getFullYear(), new Date().getFullYear()) + assert.strictEqual(row[1], 1) + assert.strictEqual(row[2], 'hai') + assert.strictEqual(row[3], null) } - client.connect(assert.success(function() { + client.connect(assert.success(function () { var config = { text: 'SELECT NOW(), 1::int, $1::text, null', values: ['hai'], rowMode: 'array' - }; - var query = client.query(config, assert.success(function(result) { - assert.equal(result.rows.length, 1); - checkRow(result.rows[0]); - client.end(); - })); - })); -}); + } + var query = client.query(config, assert.success(function (result) { + assert.equal(result.rows.length, 1) + checkRow(result.rows[0]) + client.end() + })) + })) +}) diff --git a/test/integration/client/row-description-on-results-tests.js b/test/integration/client/row-description-on-results-tests.js index 3d146bd6a..108e51977 100644 --- a/test/integration/client/row-description-on-results-tests.js +++ b/test/integration/client/row-description-on-results-tests.js @@ -1,38 +1,38 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') -var Client = helper.Client; +var Client = helper.Client -var conInfo = helper.config; +var conInfo = helper.config -var checkResult = function(result) { - assert(result.fields); - assert.equal(result.fields.length, 3); - var fields = result.fields; - assert.equal(fields[0].name, 'now'); - assert.equal(fields[1].name, 'num'); - assert.equal(fields[2].name, 'texty'); - assert.equal(fields[0].dataTypeID, 1184); - assert.equal(fields[1].dataTypeID, 23); - assert.equal(fields[2].dataTypeID, 25); -}; +var checkResult = function (result) { + assert(result.fields) + assert.equal(result.fields.length, 3) + var fields = result.fields + assert.equal(fields[0].name, 'now') + assert.equal(fields[1].name, 'num') + assert.equal(fields[2].name, 'texty') + assert.equal(fields[0].dataTypeID, 1184) + assert.equal(fields[1].dataTypeID, 23) + assert.equal(fields[2].dataTypeID, 25) +} -test('row descriptions on result object', function() { - var client = new Client(conInfo); - client.connect(assert.success(function() { - client.query('SELECT NOW() as now, 1::int as num, $1::text as texty', ["hello"], assert.success(function(result) { - checkResult(result); - client.end(); - })); - })); -}); +test('row descriptions on result object', function () { + var client = new Client(conInfo) + client.connect(assert.success(function () { + client.query('SELECT NOW() as now, 1::int as num, $1::text as texty', ['hello'], assert.success(function (result) { + checkResult(result) + client.end() + })) + })) +}) -test('row description on no rows', function() { - var client = new Client(conInfo); - client.connect(assert.success(function() { - client.query('SELECT NOW() as now, 1::int as num, $1::text as texty LIMIT 0', ["hello"], assert.success(function(result) { - checkResult(result); - client.end(); - })); - })); -}); +test('row description on no rows', function () { + var client = new Client(conInfo) + client.connect(assert.success(function () { + client.query('SELECT NOW() as now, 1::int as num, $1::text as texty LIMIT 0', ['hello'], assert.success(function (result) { + checkResult(result) + client.end() + })) + })) +}) diff --git a/test/integration/client/simple-query-tests.js b/test/integration/client/simple-query-tests.js index 6ae957dc3..e46958f2d 100644 --- a/test/integration/client/simple-query-tests.js +++ b/test/integration/client/simple-query-tests.js @@ -1,93 +1,91 @@ -"use strict"; -var helper = require("./test-helper"); -var Query = helper.pg.Query; +'use strict' +var helper = require('./test-helper') +var Query = helper.pg.Query -//before running this test make sure you run the script create-test-tables -test("simple query interface", function() { +// before running this test make sure you run the script create-test-tables +test('simple query interface', function () { + var client = helper.client() - var client = helper.client(); + var query = client.query(new Query('select name from person order by name')) - var query = client.query(new Query("select name from person order by name")); + client.on('drain', client.end.bind(client)) - client.on('drain', client.end.bind(client)); - - var rows = []; - query.on('row', function(row, result) { - assert.ok(result); - rows.push(row['name']); - }); - query.once('row', function(row) { + var rows = [] + query.on('row', function (row, result) { + assert.ok(result) + rows.push(row['name']) + }) + query.once('row', function (row) { test('Can iterate through columns', function () { - var columnCount = 0; + var columnCount = 0 for (var column in row) { - columnCount++; + columnCount++ } if ('length' in row) { - assert.lengthIs(row, columnCount, 'Iterating through the columns gives a different length from calling .length.'); + assert.lengthIs(row, columnCount, 'Iterating through the columns gives a different length from calling .length.') } - }); - }); - - assert.emits(query, 'end', function() { - test("returned right number of rows", function() { - assert.lengthIs(rows, 26); - }); - test("row ordering", function(){ - assert.equal(rows[0], "Aaron"); - assert.equal(rows[25], "Zanzabar"); - }); - }); -}); - -test("prepared statements do not mutate params", function() { - - var client = helper.client(); + }) + }) + + assert.emits(query, 'end', function () { + test('returned right number of rows', function () { + assert.lengthIs(rows, 26) + }) + test('row ordering', function () { + assert.equal(rows[0], 'Aaron') + assert.equal(rows[25], 'Zanzabar') + }) + }) +}) + +test('prepared statements do not mutate params', function () { + var client = helper.client() var params = [1] - var query = client.query(new Query("select name from person where $1 = 1 order by name", params)); + var query = client.query(new Query('select name from person where $1 = 1 order by name', params)) assert.deepEqual(params, [1]) - client.on('drain', client.end.bind(client)); + client.on('drain', client.end.bind(client)) - query.on('row', function(row, result) { - assert.ok(result); - result.addRow(row); - }); + query.on('row', function (row, result) { + assert.ok(result) + result.addRow(row) + }) - query.on('end', function(result) { - assert.lengthIs(result.rows, 26, "result returned wrong number of rows"); - assert.lengthIs(result.rows, result.rowCount); - assert.equal(result.rows[0].name, "Aaron"); - assert.equal(result.rows[25].name, "Zanzabar"); - }); -}); + query.on('end', function (result) { + assert.lengthIs(result.rows, 26, 'result returned wrong number of rows') + assert.lengthIs(result.rows, result.rowCount) + assert.equal(result.rows[0].name, 'Aaron') + assert.equal(result.rows[25].name, 'Zanzabar') + }) +}) -test("multiple simple queries", function() { - var client = helper.client(); +test('multiple simple queries', function () { + var client = helper.client() client.query({ text: "create temp table bang(id serial, name varchar(5));insert into bang(name) VALUES('boom');"}) - client.query("insert into bang(name) VALUES ('yes');"); - var query = client.query(new Query("select name from bang")); - assert.emits(query, 'row', function(row) { - assert.equal(row['name'], 'boom'); - assert.emits(query, 'row', function(row) { - assert.equal(row['name'],'yes'); - }); - }); - client.on('drain', client.end.bind(client)); -}); - -test("multiple select statements", function() { - var client = helper.client(); - client.query("create temp table boom(age integer); insert into boom(age) values(1); insert into boom(age) values(2); insert into boom(age) values(3)"); - client.query({text: "create temp table bang(name varchar(5)); insert into bang(name) values('zoom');"}); - var result = client.query(new Query({text: "select age from boom where age < 2; select name from bang"})); - assert.emits(result, 'row', function(row) { - assert.strictEqual(row['age'], 1); - assert.emits(result, 'row', function(row) { - assert.strictEqual(row['name'], 'zoom'); - }); - }); - client.on('drain', client.end.bind(client)); -}); + client.query("insert into bang(name) VALUES ('yes');") + var query = client.query(new Query('select name from bang')) + assert.emits(query, 'row', function (row) { + assert.equal(row['name'], 'boom') + assert.emits(query, 'row', function (row) { + assert.equal(row['name'], 'yes') + }) + }) + client.on('drain', client.end.bind(client)) +}) + +test('multiple select statements', function () { + var client = helper.client() + client.query('create temp table boom(age integer); insert into boom(age) values(1); insert into boom(age) values(2); insert into boom(age) values(3)') + client.query({text: "create temp table bang(name varchar(5)); insert into bang(name) values('zoom');"}) + var result = client.query(new Query({text: 'select age from boom where age < 2; select name from bang'})) + assert.emits(result, 'row', function (row) { + assert.strictEqual(row['age'], 1) + assert.emits(result, 'row', function (row) { + assert.strictEqual(row['name'], 'zoom') + }) + }) + client.on('drain', client.end.bind(client)) +}) diff --git a/test/integration/client/ssl-tests.js b/test/integration/client/ssl-tests.js index 7523dfd36..bd864d1e1 100644 --- a/test/integration/client/ssl-tests.js +++ b/test/integration/client/ssl-tests.js @@ -1,15 +1,15 @@ -"use strict"; -var pg = require(__dirname + '/../../../lib'); -var config = require(__dirname + '/test-helper').config; -test('can connect with ssl', function() { - return false; +'use strict' +var pg = require(__dirname + '/../../../lib') +var config = require(__dirname + '/test-helper').config +test('can connect with ssl', function () { + return false config.ssl = { rejectUnauthorized: false - }; - pg.connect(config, assert.success(function(client) { - return false; - client.query('SELECT NOW()', assert.success(function() { - pg.end(); - })); - })); -}); + } + pg.connect(config, assert.success(function (client) { + return false + client.query('SELECT NOW()', assert.success(function () { + pg.end() + })) + })) +}) diff --git a/test/integration/client/test-helper.js b/test/integration/client/test-helper.js index 027477a1f..14f8134eb 100644 --- a/test/integration/client/test-helper.js +++ b/test/integration/client/test-helper.js @@ -1,4 +1,4 @@ -"use strict"; -var helper = require('./../test-helper'); +'use strict' +var helper = require('./../test-helper') -module.exports = helper; +module.exports = helper diff --git a/test/integration/client/timezone-tests.js b/test/integration/client/timezone-tests.js index 1f0e06989..c9f6a8c83 100644 --- a/test/integration/client/timezone-tests.js +++ b/test/integration/client/timezone-tests.js @@ -1,34 +1,34 @@ -"use strict"; -var helper = require('./../test-helper'); -var exec = require('child_process').exec; +'use strict' +var helper = require('./../test-helper') +var exec = require('child_process').exec -var oldTz = process.env.TZ; -process.env.TZ = 'Europe/Berlin'; +var oldTz = process.env.TZ +process.env.TZ = 'Europe/Berlin' -var date = new Date(); +var date = new Date() const pool = new helper.pg.Pool() const suite = new helper.Suite() pool.connect(function (err, client, done) { - assert(!err); + assert(!err) suite.test('timestamp without time zone', function (cb) { - client.query("SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS \"val\"", [date], function (err, result) { - assert(!err); - assert.equal(result.rows[0].val.getTime(), date.getTime()); + client.query('SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS "val"', [date], function (err, result) { + assert(!err) + assert.equal(result.rows[0].val.getTime(), date.getTime()) cb() }) }) suite.test('timestamp with time zone', function (cb) { - client.query("SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS \"val\"", [date], function (err, result) { - assert(!err); - assert.equal(result.rows[0].val.getTime(), date.getTime()); + client.query('SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS "val"', [date], function (err, result) { + assert(!err) + assert.equal(result.rows[0].val.getTime(), date.getTime()) - done(); + done() pool.end(cb) - process.env.TZ = oldTz; - }); - }); -}); + process.env.TZ = oldTz + }) + }) +}) diff --git a/test/integration/client/transaction-tests.js b/test/integration/client/transaction-tests.js index 4668a427f..560067ba4 100644 --- a/test/integration/client/transaction-tests.js +++ b/test/integration/client/transaction-tests.js @@ -1,49 +1,48 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') const suite = new helper.Suite() const pg = helper.pg const client = new pg.Client() client.connect(assert.success(function () { - - client.query('begin'); + client.query('begin') var getZed = { text: 'SELECT * FROM person WHERE name = $1', values: ['Zed'] - }; + } suite.test('name should not exist in the database', function (done) { client.query(getZed, assert.calls(function (err, result) { - assert(!err); - assert.empty(result.rows); + assert(!err) + assert.empty(result.rows) done() })) }) suite.test('can insert name', (done) => { - client.query("INSERT INTO person(name, age) VALUES($1, $2)", ['Zed', 270], assert.calls(function (err, result) { + client.query('INSERT INTO person(name, age) VALUES($1, $2)', ['Zed', 270], assert.calls(function (err, result) { assert(!err) done() - })); + })) }) suite.test('name should exist in the database', function (done) { client.query(getZed, assert.calls(function (err, result) { - assert(!err); - assert.equal(result.rows[0].name, 'Zed'); + assert(!err) + assert.equal(result.rows[0].name, 'Zed') done() })) }) suite.test('rollback', (done) => { - client.query('rollback', done); + client.query('rollback', done) }) suite.test('name should not exist in the database', function (done) { client.query(getZed, assert.calls(function (err, result) { - assert(!err); - assert.empty(result.rows); + assert(!err) + assert.empty(result.rows) client.end(done) })) }) @@ -52,26 +51,26 @@ client.connect(assert.success(function () { suite.test('gh#36', function (cb) { const pool = new pg.Pool() pool.connect(assert.success(function (client, done) { - client.query("BEGIN"); + client.query('BEGIN') client.query({ name: 'X', - text: "SELECT $1::INTEGER", + text: 'SELECT $1::INTEGER', values: [0] }, assert.calls(function (err, result) { - if (err) throw err; - assert.equal(result.rows.length, 1); + if (err) throw err + assert.equal(result.rows.length, 1) })) client.query({ name: 'X', - text: "SELECT $1::INTEGER", + text: 'SELECT $1::INTEGER', values: [0] }, assert.calls(function (err, result) { - if (err) throw err; - assert.equal(result.rows.length, 1); + if (err) throw err + assert.equal(result.rows.length, 1) })) - client.query("COMMIT", function () { - done(); + client.query('COMMIT', function () { + done() pool.end(cb) }) - })); + })) }) diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index 2aaffbc44..44ac89639 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -1,51 +1,49 @@ -"use strict"; -var helper = require(__dirname + '/test-helper'); -var pg = helper.pg; -var sink; +'use strict' +var helper = require(__dirname + '/test-helper') +var pg = helper.pg +var sink const suite = new helper.Suite() var testForTypeCoercion = function (type) { const pool = new pg.Pool() suite.test(`test type coercion ${type.name}`, (cb) => { pool.connect(function (err, client, done) { - assert(!err); - client.query("create temp table test_type(col " + type.name + ")", assert.calls(function (err, result) { - assert(!err); + assert(!err) + client.query('create temp table test_type(col ' + type.name + ')', assert.calls(function (err, result) { + assert(!err) type.values.forEach(function (val) { - var insertQuery = client.query('insert into test_type(col) VALUES($1)', [val], assert.calls(function (err, result) { - assert(!err); - })); + assert(!err) + })) var query = client.query(new pg.Query({ name: 'get type ' + type.name, text: 'select col from test_type' - })); + })) query.on('error', function (err) { - console.log(err); - throw err; - }); + console.log(err) + throw err + }) assert.emits(query, 'row', function (row) { - var expected = val + " (" + typeof val + ")"; - var returned = row.col + " (" + typeof row.col + ")"; - assert.strictEqual(row.col, val, "expected " + type.name + " of " + expected + " but got " + returned); - }, "row should have been called for " + type.name + " of " + val); + var expected = val + ' (' + typeof val + ')' + var returned = row.col + ' (' + typeof row.col + ')' + assert.strictEqual(row.col, val, 'expected ' + type.name + ' of ' + expected + ' but got ' + returned) + }, 'row should have been called for ' + type.name + ' of ' + val) - client.query('delete from test_type'); - }); + client.query('delete from test_type') + }) client.query('drop table test_type', function () { - done(); + done() pool.end(cb) - }); - })); + }) + })) }) - }) -}; +} var types = [{ name: 'integer', @@ -101,96 +99,95 @@ var types = [{ }, { name: 'time', values: ['13:12:12.321', null] -}]; +}] // ignore some tests in binary mode if (helper.config.binary) { types = types.filter(function (type) { - return !(type.name in { 'real': 1, 'timetz': 1, 'time': 1, 'numeric': 1, 'bigint': 1 }); - }); + return !(type.name in { 'real': 1, 'timetz': 1, 'time': 1, 'numeric': 1, 'bigint': 1 }) + }) } -var valueCount = 0; +var valueCount = 0 types.forEach(function (type) { testForTypeCoercion(type) -}); +}) -suite.test("timestampz round trip", function (cb) { - var now = new Date(); - var client = helper.client(); - client.query("create temp table date_tests(name varchar(10), tstz timestamptz(3))"); +suite.test('timestampz round trip', function (cb) { + var now = new Date() + var client = helper.client() + client.query('create temp table date_tests(name varchar(10), tstz timestamptz(3))') client.query({ - text: "insert into date_tests(name, tstz)VALUES($1, $2)", + text: 'insert into date_tests(name, tstz)VALUES($1, $2)', name: 'add date', values: ['now', now] - }); + }) var result = client.query(new pg.Query({ name: 'get date', text: 'select * from date_tests where name = $1', values: ['now'] - })); + })) assert.emits(result, 'row', function (row) { - var date = row.tstz; - assert.equal(date.getYear(), now.getYear()); - assert.equal(date.getMonth(), now.getMonth()); - assert.equal(date.getDate(), now.getDate()); - assert.equal(date.getHours(), now.getHours()); - assert.equal(date.getMinutes(), now.getMinutes()); - assert.equal(date.getSeconds(), now.getSeconds()); - assert.equal(date.getMilliseconds(), now.getMilliseconds()); - }); + var date = row.tstz + assert.equal(date.getYear(), now.getYear()) + assert.equal(date.getMonth(), now.getMonth()) + assert.equal(date.getDate(), now.getDate()) + assert.equal(date.getHours(), now.getHours()) + assert.equal(date.getMinutes(), now.getMinutes()) + assert.equal(date.getSeconds(), now.getSeconds()) + assert.equal(date.getMilliseconds(), now.getMilliseconds()) + }) client.on('drain', () => { client.end(cb) - }); -}); + }) +}) suite.test('selecting nulls', cb => { const pool = new pg.Pool() pool.connect(assert.calls(function (err, client, done) { - assert.ifError(err); + assert.ifError(err) client.query('select null as res;', assert.calls(function (err, res) { - assert(!err); + assert(!err) assert.strictEqual(res.rows[0].res, null) })) client.query('select 7 <> $1 as res;', [null], function (err, res) { - assert(!err); - assert.strictEqual(res.rows[0].res, null); - done(); + assert(!err) + assert.strictEqual(res.rows[0].res, null) + done() pool.end(cb) }) })) }) suite.test('date range extremes', function (done) { - var client = helper.client(); + var client = helper.client() // Set the server timeszone to the same as used for the test, // otherwise (if server's timezone is ahead of GMT) in // textParsers.js::parseDate() the timezone offest is added to the date; // in the case of "275760-09-13 00:00:00 GMT" the timevalue overflows. client.query('SET TIMEZONE TO GMT', assert.success(function (res) { - // PostgreSQL supports date range of 4713 BCE to 294276 CE // http://www.postgresql.org/docs/9.2/static/datatype-datetime.html // ECMAScript supports date range of Apr 20 271821 BCE to Sep 13 275760 CE // http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1 - client.query('SELECT $1::TIMESTAMPTZ as when', ["275760-09-13 00:00:00 GMT"], assert.success(function (res) { - assert.equal(res.rows[0].when.getFullYear(), 275760); - })); + client.query('SELECT $1::TIMESTAMPTZ as when', ['275760-09-13 00:00:00 GMT'], assert.success(function (res) { + assert.equal(res.rows[0].when.getFullYear(), 275760) + })) - client.query('SELECT $1::TIMESTAMPTZ as when', ["4713-12-31 12:31:59 BC GMT"], assert.success(function (res) { - assert.equal(res.rows[0].when.getFullYear(), -4713); - })); + client.query('SELECT $1::TIMESTAMPTZ as when', ['4713-12-31 12:31:59 BC GMT'], assert.success(function (res) { + assert.equal(res.rows[0].when.getFullYear(), -4713) + })) - client.query('SELECT $1::TIMESTAMPTZ as when', ["275760-09-13 00:00:00 -15:00"], assert.success(function (res) { - assert(isNaN(res.rows[0].when.getTime())); - })); + client.query('SELECT $1::TIMESTAMPTZ as when', ['275760-09-13 00:00:00 -15:00'], assert.success(function (res) { + assert(isNaN(res.rows[0].when.getTime())) + })) client.on('drain', () => { client.end(done) - }); - })); -}); + }) + })) +}) diff --git a/test/integration/client/type-parser-override-tests.js b/test/integration/client/type-parser-override-tests.js index f12e40054..e806a3907 100644 --- a/test/integration/client/type-parser-override-tests.js +++ b/test/integration/client/type-parser-override-tests.js @@ -1,37 +1,37 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') -function testTypeParser(client, expectedResult, done) { - var boolValue = true; - client.query('CREATE TEMP TABLE parserOverrideTest(id bool)'); - client.query('INSERT INTO parserOverrideTest(id) VALUES ($1)', [boolValue]); - client.query('SELECT * FROM parserOverrideTest', assert.success(function(result) { - assert.equal(result.rows[0].id, expectedResult); - done(); - })); +function testTypeParser (client, expectedResult, done) { + var boolValue = true + client.query('CREATE TEMP TABLE parserOverrideTest(id bool)') + client.query('INSERT INTO parserOverrideTest(id) VALUES ($1)', [boolValue]) + client.query('SELECT * FROM parserOverrideTest', assert.success(function (result) { + assert.equal(result.rows[0].id, expectedResult) + done() + })) } const pool = new helper.pg.Pool(helper.config) -pool.connect(assert.success(function(client1, done1) { - pool.connect(assert.success(function(client2, done2) { - var boolTypeOID = 16; - client1.setTypeParser(boolTypeOID, function(){ - return 'first client'; - }); - client2.setTypeParser(boolTypeOID, function(){ - return 'second client'; - }); +pool.connect(assert.success(function (client1, done1) { + pool.connect(assert.success(function (client2, done2) { + var boolTypeOID = 16 + client1.setTypeParser(boolTypeOID, function () { + return 'first client' + }) + client2.setTypeParser(boolTypeOID, function () { + return 'second client' + }) - client1.setTypeParser(boolTypeOID, 'binary', function(){ - return 'first client binary'; - }); - client2.setTypeParser(boolTypeOID, 'binary', function(){ - return 'second client binary'; - }); + client1.setTypeParser(boolTypeOID, 'binary', function () { + return 'first client binary' + }) + client2.setTypeParser(boolTypeOID, 'binary', function () { + return 'second client binary' + }) testTypeParser(client1, 'first client', () => { done1() - testTypeParser(client2, 'second client', () => done2(), pool.end()); - }); - })); -})); + testTypeParser(client2, 'second client', () => done2(), pool.end()) + }) + })) +})) diff --git a/test/integration/connection-pool/connection-pool-size-tests.js b/test/integration/connection-pool/connection-pool-size-tests.js index 51051c242..da281a191 100644 --- a/test/integration/connection-pool/connection-pool-size-tests.js +++ b/test/integration/connection-pool/connection-pool-size-tests.js @@ -1,10 +1,10 @@ -"use strict"; -var helper = require("./test-helper") +'use strict' +var helper = require('./test-helper') -helper.testPoolSize(1); +helper.testPoolSize(1) -helper.testPoolSize(2); +helper.testPoolSize(2) -helper.testPoolSize(40); +helper.testPoolSize(40) -helper.testPoolSize(200); +helper.testPoolSize(200) diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index 4098ba9d8..b90ab5dfb 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -1,9 +1,9 @@ -"use strict"; -var helper = require("./test-helper"); +'use strict' +var helper = require('./test-helper') const pg = helper.pg -//first make pool hold 2 clients -pg.defaults.poolSize = 2; +// first make pool hold 2 clients +pg.defaults.poolSize = 2 const pool = new pg.Pool() @@ -14,39 +14,37 @@ suite.test('connecting to invalid port', (cb) => { }) suite.test('errors emitted on pool', (cb) => { - //get first client + // get first client pool.connect(assert.success(function (client, done) { - client.id = 1; + client.id = 1 client.query('SELECT NOW()', function () { pool.connect(assert.success(function (client2, done2) { - client2.id = 2; - var pidColName = 'procpid'; + client2.id = 2 + var pidColName = 'procpid' helper.versionGTE(client2, '9.2.0', assert.success(function (isGreater) { - var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1'; - var params = ['idle']; + var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1' + var params = ['idle'] if (!isGreater) { - killIdleQuery = 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE $1'; + killIdleQuery = 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE $1' params = ['%IDLE%'] } pool.once('error', (err, brokenClient) => { - assert.ok(err); - assert.ok(brokenClient); - assert.equal(client.id, brokenClient.id); + assert.ok(err) + assert.ok(brokenClient) + assert.equal(client.id, brokenClient.id) cb() }) - //kill the connection from client + // kill the connection from client client2.query(killIdleQuery, params, assert.success(function (res) { - //check to make sure client connection actually was killed - //return client2 to the pool - done2(); - pool.end(); - })); - })); - })); - + // check to make sure client connection actually was killed + // return client2 to the pool + done2() + pool.end() + })) + })) + })) }) - })); - + })) }) diff --git a/test/integration/connection-pool/idle-timeout-tests.js b/test/integration/connection-pool/idle-timeout-tests.js index 63956b641..c48f712ea 100644 --- a/test/integration/connection-pool/idle-timeout-tests.js +++ b/test/integration/connection-pool/idle-timeout-tests.js @@ -1,13 +1,12 @@ -"use strict"; -var helper = require('./test-helper'); - +'use strict' +var helper = require('./test-helper') new helper.Suite().test('idle timeout', function () { const config = Object.assign({}, helper.config, { idleTimeoutMillis: 50 }) const pool = new helper.pg.Pool(config) pool.connect(assert.calls(function (err, client, done) { - assert(!err); - client.query('SELECT NOW()'); - done(); - })); -}); + assert(!err) + client.query('SELECT NOW()') + done() + })) +}) diff --git a/test/integration/connection-pool/native-instance-tests.js b/test/integration/connection-pool/native-instance-tests.js index caaa2b67a..5347677a9 100644 --- a/test/integration/connection-pool/native-instance-tests.js +++ b/test/integration/connection-pool/native-instance-tests.js @@ -1,11 +1,11 @@ -"use strict"; -var helper = require("./../test-helper") +'use strict' +var helper = require('./../test-helper') var pg = helper.pg var native = helper.args.native var pool = new pg.Pool() -pool.connect(assert.calls(function(err, client, done) { +pool.connect(assert.calls(function (err, client, done) { if (native) { assert(client.native) } else { diff --git a/test/integration/connection-pool/test-helper.js b/test/integration/connection-pool/test-helper.js index 2fde015ee..97a177a62 100644 --- a/test/integration/connection-pool/test-helper.js +++ b/test/integration/connection-pool/test-helper.js @@ -1,5 +1,5 @@ -"use strict"; -var helper = require("./../test-helper"); +'use strict' +var helper = require('./../test-helper') const suite = new helper.Suite() @@ -9,19 +9,19 @@ helper.testPoolSize = function (max) { var sink = new helper.Sink(max, function () { pool.end(cb) - }); + }) for (var i = 0; i < max; i++) { pool.connect(function (err, client, done) { - assert(!err); - client.query("SELECT * FROM NOW()") - client.query("select generate_series(0, 25)", function (err, result) { + assert(!err) + client.query('SELECT * FROM NOW()') + client.query('select generate_series(0, 25)', function (err, result) { assert.equal(result.rows.length, 26) }) - var query = client.query("SELECT * FROM NOW()", (err) => { + var query = client.query('SELECT * FROM NOW()', (err) => { assert(!err) - sink.add(); - done(); + sink.add() + done() }) }) } @@ -29,4 +29,3 @@ helper.testPoolSize = function (max) { } module.exports = Object.assign({}, helper, { suite: suite }) - diff --git a/test/integration/connection-pool/yield-support-tests.js b/test/integration/connection-pool/yield-support-tests.js index 149266996..08d89b308 100644 --- a/test/integration/connection-pool/yield-support-tests.js +++ b/test/integration/connection-pool/yield-support-tests.js @@ -1,9 +1,9 @@ -"use strict"; +'use strict' var helper = require('./test-helper') var co = require('co') const pool = new helper.pg.Pool() -new helper.Suite().test('using coroutines works with promises', co.wrap(function* () { +new helper.Suite().test('using coroutines works with promises', co.wrap(function * () { var client = yield pool.connect() var res = yield client.query('SELECT $1::text as name', ['foo']) assert.equal(res.rows[0].name, 'foo') diff --git a/test/integration/connection/bound-command-tests.js b/test/integration/connection/bound-command-tests.js index 40da4b5a2..c6cf84e11 100644 --- a/test/integration/connection/bound-command-tests.js +++ b/test/integration/connection/bound-command-tests.js @@ -1,61 +1,58 @@ -"use strict"; -var helper = require(__dirname + '/test-helper'); -//http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY +'use strict' +var helper = require(__dirname + '/test-helper') +// http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY -test('flushing once', function() { - helper.connect(function(con) { +test('flushing once', function () { + helper.connect(function (con) { con.parse({ text: 'select * from ids' - }); - - con.bind(); - con.execute(); - con.flush(); - - assert.emits(con, 'parseComplete'); - assert.emits(con, 'bindComplete'); - assert.emits(con, 'dataRow'); - assert.emits(con, 'commandComplete', function(){ - con.sync(); - }); - assert.emits(con, 'readyForQuery', function(){ - con.end(); - }); - - }); -}); - -test("sending many flushes", function() { - helper.connect(function(con) { - - assert.emits(con, 'parseComplete', function(){ - con.bind(); - con.flush(); - }); - - assert.emits(con, 'bindComplete', function(){ - con.execute(); - con.flush(); - }); - - assert.emits(con, 'dataRow', function(msg){ - assert.equal(msg.fields[0], 1); - assert.emits(con, 'dataRow', function(msg){ - assert.equal(msg.fields[0], 2); - assert.emits(con, 'commandComplete', function(){ - con.sync(); - }); - assert.emits(con, 'readyForQuery', function(){ - con.end(); - }); - }); - }); + }) + + con.bind() + con.execute() + con.flush() + + assert.emits(con, 'parseComplete') + assert.emits(con, 'bindComplete') + assert.emits(con, 'dataRow') + assert.emits(con, 'commandComplete', function () { + con.sync() + }) + assert.emits(con, 'readyForQuery', function () { + con.end() + }) + }) +}) + +test('sending many flushes', function () { + helper.connect(function (con) { + assert.emits(con, 'parseComplete', function () { + con.bind() + con.flush() + }) + + assert.emits(con, 'bindComplete', function () { + con.execute() + con.flush() + }) + + assert.emits(con, 'dataRow', function (msg) { + assert.equal(msg.fields[0], 1) + assert.emits(con, 'dataRow', function (msg) { + assert.equal(msg.fields[0], 2) + assert.emits(con, 'commandComplete', function () { + con.sync() + }) + assert.emits(con, 'readyForQuery', function () { + con.end() + }) + }) + }) con.parse({ - text: "select * from ids order by id" - }); + text: 'select * from ids order by id' + }) - con.flush(); - - }); -}); + con.flush() + }) +}) diff --git a/test/integration/connection/copy-tests.js b/test/integration/connection/copy-tests.js index 2dfbc6070..c11632c37 100644 --- a/test/integration/connection/copy-tests.js +++ b/test/integration/connection/copy-tests.js @@ -1,45 +1,45 @@ -"use strict"; -var helper = require(__dirname+"/test-helper"); -var assert = require('assert'); +'use strict' +var helper = require(__dirname + '/test-helper') +var assert = require('assert') test('COPY FROM events check', function () { - helper.connect(function (con) { - var stdinStream = con.query('COPY person FROM STDIN'); + helper.connect(function (con) { + var stdinStream = con.query('COPY person FROM STDIN') con.on('copyInResponse', function () { - con.endCopyFrom(); - }); + con.endCopyFrom() + }) assert.emits(con, 'copyInResponse', function () { - con.endCopyFrom(); + con.endCopyFrom() }, - "backend should emit copyInResponse after COPY FROM query" - ); + 'backend should emit copyInResponse after COPY FROM query' + ) assert.emits(con, 'commandComplete', function () { - con.end(); + con.end() }, - "backend should emit commandComplete after COPY FROM stream ends" + 'backend should emit commandComplete after COPY FROM stream ends' ) - }); -}); + }) +}) test('COPY TO events check', function () { helper.connect(function (con) { - var stdoutStream = con.query('COPY person TO STDOUT'); + var stdoutStream = con.query('COPY person TO STDOUT') assert.emits(con, 'copyOutResponse', function () { }, - "backend should emit copyOutResponse after COPY TO query" - ); + 'backend should emit copyOutResponse after COPY TO query' + ) assert.emits(con, 'copyData', function () { }, - "backend should emit copyData on every data row" - ); + 'backend should emit copyData on every data row' + ) assert.emits(con, 'copyDone', function () { - con.end(); + con.end() }, - "backend should emit copyDone after all data rows" - ); - }); -}); + 'backend should emit copyDone after all data rows' + ) + }) +}) diff --git a/test/integration/connection/notification-tests.js b/test/integration/connection/notification-tests.js index dd11904d6..347b7ee89 100644 --- a/test/integration/connection/notification-tests.js +++ b/test/integration/connection/notification-tests.js @@ -1,16 +1,16 @@ -"use strict"; -var helper = require(__dirname + '/test-helper'); -//http://www.postgresql.org/docs/8.3/static/libpq-notify.html -test('recieves notification from same connection with no payload', function() { - helper.connect(function(con) { - con.query('LISTEN boom'); - assert.emits(con, 'readyForQuery', function() { - con.query("NOTIFY boom"); - assert.emits(con, 'notification', function(msg) { - assert.equal(msg.payload, ""); +'use strict' +var helper = require(__dirname + '/test-helper') +// http://www.postgresql.org/docs/8.3/static/libpq-notify.html +test('recieves notification from same connection with no payload', function () { + helper.connect(function (con) { + con.query('LISTEN boom') + assert.emits(con, 'readyForQuery', function () { + con.query('NOTIFY boom') + assert.emits(con, 'notification', function (msg) { + assert.equal(msg.payload, '') assert.equal(msg.channel, 'boom') - con.end(); - }); - }); - }); -}); + con.end() + }) + }) + }) +}) diff --git a/test/integration/connection/query-tests.js b/test/integration/connection/query-tests.js index 6216c55aa..70c39c322 100644 --- a/test/integration/connection/query-tests.js +++ b/test/integration/connection/query-tests.js @@ -1,26 +1,26 @@ -"use strict"; -var helper = require(__dirname+"/test-helper"); -var assert = require('assert'); +'use strict' +var helper = require(__dirname + '/test-helper') +var assert = require('assert') -var rows = []; -//testing the low level 1-1 mapping api of client to postgres messages -//it's cumbersome to use the api this way -test('simple query', function() { - helper.connect(function(con) { - con.query('select * from ids'); - assert.emits(con, 'dataRow'); - con.on('dataRow', function(msg) { - rows.push(msg.fields); - }); - assert.emits(con, 'readyForQuery', function() { - con.end(); - }); - }); -}); +var rows = [] +// testing the low level 1-1 mapping api of client to postgres messages +// it's cumbersome to use the api this way +test('simple query', function () { + helper.connect(function (con) { + con.query('select * from ids') + assert.emits(con, 'dataRow') + con.on('dataRow', function (msg) { + rows.push(msg.fields) + }) + assert.emits(con, 'readyForQuery', function () { + con.end() + }) + }) +}) -process.on('exit', function() { - assert.equal(rows.length, 2); - assert.equal(rows[0].length, 1); - assert.strictEqual(String(rows[0] [0]), '1'); - assert.strictEqual(String(rows[1] [0]), '2'); -}); +process.on('exit', function () { + assert.equal(rows.length, 2) + assert.equal(rows[0].length, 1) + assert.strictEqual(String(rows[0][0]), '1') + assert.strictEqual(String(rows[1][0]), '2') +}) diff --git a/test/integration/connection/test-helper.js b/test/integration/connection/test-helper.js index d053e39ab..71bcfb2e0 100644 --- a/test/integration/connection/test-helper.js +++ b/test/integration/connection/test-helper.js @@ -1,43 +1,43 @@ -"use strict"; -var net = require('net'); -var helper = require(__dirname+'/../test-helper'); -var Connection = require(__dirname + '/../../../lib/connection'); -var connect = function(callback) { - var username = helper.args.user; - var database = helper.args.database; - var con = new Connection({stream: new net.Stream()}); - con.on('error', function(error){ - console.log(error); - throw new Error("Connection error"); - }); - con.connect(helper.args.port || '5432', helper.args.host || 'localhost'); - con.once('connect', function() { +'use strict' +var net = require('net') +var helper = require(__dirname + '/../test-helper') +var Connection = require(__dirname + '/../../../lib/connection') +var connect = function (callback) { + var username = helper.args.user + var database = helper.args.database + var con = new Connection({stream: new net.Stream()}) + con.on('error', function (error) { + console.log(error) + throw new Error('Connection error') + }) + con.connect(helper.args.port || '5432', helper.args.host || 'localhost') + con.once('connect', function () { con.startup({ user: username, database: database - }); - con.once('authenticationCleartextPassword', function(){ - con.password(helper.args.password); - }); - con.once('authenticationMD5Password', function(msg){ - //need js client even if native client is included - var client = require(__dirname +"/../../../lib/client"); - var inner = client.md5(helper.args.password+helper.args.user); - var outer = client.md5(inner + msg.salt.toString('binary')); - con.password("md5"+outer); - }); - con.once('readyForQuery', function() { - con.query('create temp table ids(id integer)'); - con.once('readyForQuery', function() { - con.query('insert into ids(id) values(1); insert into ids(id) values(2);'); - con.once('readyForQuery', function() { - callback(con); - }); - }); - }); - }); -}; + }) + con.once('authenticationCleartextPassword', function () { + con.password(helper.args.password) + }) + con.once('authenticationMD5Password', function (msg) { + // need js client even if native client is included + var client = require(__dirname + '/../../../lib/client') + var inner = client.md5(helper.args.password + helper.args.user) + var outer = client.md5(inner + msg.salt.toString('binary')) + con.password('md5' + outer) + }) + con.once('readyForQuery', function () { + con.query('create temp table ids(id integer)') + con.once('readyForQuery', function () { + con.query('insert into ids(id) values(1); insert into ids(id) values(2);') + con.once('readyForQuery', function () { + callback(con) + }) + }) + }) + }) +} module.exports = { connect: connect -}; +} diff --git a/test/integration/domain-tests.js b/test/integration/domain-tests.js index 5d4db53c2..a02f3942a 100644 --- a/test/integration/domain-tests.js +++ b/test/integration/domain-tests.js @@ -1,4 +1,4 @@ -"use strict"; +'use strict' var async = require('async') var helper = require('./test-helper') diff --git a/test/integration/gh-issues/130-tests.js b/test/integration/gh-issues/130-tests.js index bc1f3b742..b3e2a2252 100644 --- a/test/integration/gh-issues/130-tests.js +++ b/test/integration/gh-issues/130-tests.js @@ -1,23 +1,23 @@ -"use strict"; -var helper = require(__dirname + '/../test-helper'); -var exec = require('child_process').exec; +'use strict' +var helper = require(__dirname + '/../test-helper') +var exec = require('child_process').exec -helper.pg.defaults.poolIdleTimeout = 1000; +helper.pg.defaults.poolIdleTimeout = 1000 const pool = new helper.pg.Pool() -pool.connect(function(err,client) { - client.query("SELECT pg_backend_pid()", function(err, result) { - var pid = result.rows[0].pg_backend_pid; - var psql = 'psql'; - if (helper.args.host) psql = psql+' -h '+helper.args.host; - if (helper.args.port) psql = psql+' -p '+helper.args.port; - if (helper.args.user) psql = psql+' -U '+helper.args.user; - exec(psql+' -c "select pg_terminate_backend('+pid+')" template1', assert.calls(function (error, stdout, stderr) { - assert.isNull(error); - })); - }); -}); +pool.connect(function (err, client) { + client.query('SELECT pg_backend_pid()', function (err, result) { + var pid = result.rows[0].pg_backend_pid + var psql = 'psql' + if (helper.args.host) psql = psql + ' -h ' + helper.args.host + if (helper.args.port) psql = psql + ' -p ' + helper.args.port + if (helper.args.user) psql = psql + ' -U ' + helper.args.user + exec(psql + ' -c "select pg_terminate_backend(' + pid + ')" template1', assert.calls(function (error, stdout, stderr) { + assert.isNull(error) + })) + }) +}) -pool.on('error', function(err, client) { - //swallow errors -}); +pool.on('error', function (err, client) { + // swallow errors +}) diff --git a/test/integration/gh-issues/131-tests.js b/test/integration/gh-issues/131-tests.js index f56834e26..87a7b241f 100644 --- a/test/integration/gh-issues/131-tests.js +++ b/test/integration/gh-issues/131-tests.js @@ -1,20 +1,20 @@ -"use strict"; -var helper = require('../test-helper'); -var pg = helper.pg; +'use strict' +var helper = require('../test-helper') +var pg = helper.pg var suite = new helper.Suite() suite.test('parsing array decimal results', function (done) { const pool = new pg.Pool() pool.connect(assert.calls(function (err, client, release) { - assert(!err); - client.query("CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])"); - client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log); + assert(!err) + client.query('CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])') + client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log) client.query('SELECT decimals FROM why', assert.success(function (result) { - assert.lengthIs(result.rows[0].decimals, 3); - assert.equal(result.rows[0].decimals[0], 0.1); - assert.equal(result.rows[0].decimals[1], 0.05); - assert.equal(result.rows[0].decimals[2], 3.654); + assert.lengthIs(result.rows[0].decimals, 3) + assert.equal(result.rows[0].decimals[0], 0.1) + assert.equal(result.rows[0].decimals[1], 0.05) + assert.equal(result.rows[0].decimals[2], 3.654) release() pool.end(done) })) diff --git a/test/integration/gh-issues/199-tests.js b/test/integration/gh-issues/199-tests.js index 60637fb19..bb93d4260 100644 --- a/test/integration/gh-issues/199-tests.js +++ b/test/integration/gh-issues/199-tests.js @@ -1,22 +1,22 @@ -"use strict"; -var helper = require('../test-helper'); -var client = helper.client(); +'use strict' +var helper = require('../test-helper') +var client = helper.client() -client.query('CREATE TEMP TABLE arrtest (n integer, s varchar)'); -client.query("INSERT INTO arrtest VALUES (4, 'foo'), (5, 'bar'), (6, 'baz');"); +client.query('CREATE TEMP TABLE arrtest (n integer, s varchar)') +client.query("INSERT INTO arrtest VALUES (4, 'foo'), (5, 'bar'), (6, 'baz');") var qText = "SELECT \ ARRAY[1, 2, 3] AS b,\ ARRAY['xx', 'yy', 'zz'] AS c,\ ARRAY(SELECT n FROM arrtest) AS d,\ -ARRAY(SELECT s FROM arrtest) AS e;"; +ARRAY(SELECT s FROM arrtest) AS e;" -client.query(qText, function(err, result) { - if(err) throw err; - var row = result.rows[0]; - for(var key in row) { - assert.equal(typeof row[key], 'object'); - assert.equal(row[key].length, 3); +client.query(qText, function (err, result) { + if (err) throw err + var row = result.rows[0] + for (var key in row) { + assert.equal(typeof row[key], 'object') + assert.equal(row[key].length, 3) } - client.end(); -}); + client.end() +}) diff --git a/test/integration/gh-issues/507-tests.js b/test/integration/gh-issues/507-tests.js index 62bec47ce..dadc1c83f 100644 --- a/test/integration/gh-issues/507-tests.js +++ b/test/integration/gh-issues/507-tests.js @@ -1,13 +1,13 @@ -"use strict"; -var helper = require(__dirname + "/../test-helper"); -var pg = helper.pg; +'use strict' +var helper = require(__dirname + '/../test-helper') +var pg = helper.pg -new helper.Suite().test('parsing array results', function(cb) { +new helper.Suite().test('parsing array results', function (cb) { const pool = new pg.Pool() - pool.connect(assert.success(function(client, done) { + pool.connect(assert.success(function (client, done) { client.query('CREATE TEMP TABLE test_table(bar integer, "baz\'s" integer)') client.query('INSERT INTO test_table(bar, "baz\'s") VALUES(1, 1), (2, 2)') - client.query('SELECT * FROM test_table', function(err, res) { + client.query('SELECT * FROM test_table', function (err, res) { assert.equal(res.rows[0]["baz's"], 1) assert.equal(res.rows[1]["baz's"], 2) done() diff --git a/test/integration/gh-issues/600-tests.js b/test/integration/gh-issues/600-tests.js index 263e48d0c..ea6154e3f 100644 --- a/test/integration/gh-issues/600-tests.js +++ b/test/integration/gh-issues/600-tests.js @@ -1,51 +1,51 @@ -"use strict"; -var async = require('async'); -var helper = require('../test-helper'); +'use strict' +var async = require('async') +var helper = require('../test-helper') const suite = new helper.Suite() -var db = helper.client(); +var db = helper.client() -function createTableFoo(callback){ - db.query("create temp table foo(column1 int, column2 int)", callback); +function createTableFoo (callback) { + db.query('create temp table foo(column1 int, column2 int)', callback) } -function createTableBar(callback){ - db.query("create temp table bar(column1 text, column2 text)", callback); +function createTableBar (callback) { + db.query('create temp table bar(column1 text, column2 text)', callback) } -function insertDataFoo(callback){ - db.query({ - name: 'insertFoo', - text: 'insert into foo values($1,$2)', - values:['one','two'] - }, callback ); +function insertDataFoo (callback) { + db.query({ + name: 'insertFoo', + text: 'insert into foo values($1,$2)', + values: ['one', 'two'] + }, callback) } -function insertDataBar(callback){ - db.query({ - name: 'insertBar', - text: 'insert into bar values($1,$2)', - values:['one','two'] - }, callback ); +function insertDataBar (callback) { + db.query({ + name: 'insertBar', + text: 'insert into bar values($1,$2)', + values: ['one', 'two'] + }, callback) } -function startTransaction(callback) { - db.query('BEGIN', callback); +function startTransaction (callback) { + db.query('BEGIN', callback) } -function endTransaction(callback) { - db.query('COMMIT', callback); +function endTransaction (callback) { + db.query('COMMIT', callback) } -function doTransaction(callback) { +function doTransaction (callback) { // The transaction runs startTransaction, then all queries, then endTransaction, // no matter if there has been an error in a query in the middle. - startTransaction(function() { - insertDataFoo(function() { - insertDataBar(function() { - endTransaction( callback ); - }); - }); - }); + startTransaction(function () { + insertDataFoo(function () { + insertDataBar(function () { + endTransaction(callback) + }) + }) + }) } var steps = [ @@ -55,27 +55,26 @@ var steps = [ insertDataBar ] -suite.test('test if query fails', function(done) { - async.series(steps, assert.success(function() { +suite.test('test if query fails', function (done) { + async.series(steps, assert.success(function () { db.end() done() })) }) -suite.test('test if prepare works but bind fails', function(done) { - var client = helper.client(); +suite.test('test if prepare works but bind fails', function (done) { + var client = helper.client() var q = { text: 'SELECT $1::int as name', values: ['brian'], name: 'test' - }; - client.query(q, assert.calls(function(err, res) { - q.values = [1]; - client.query(q, assert.calls(function(err, res) { - assert.ifError(err); - client.end(); + } + client.query(q, assert.calls(function (err, res) { + q.values = [1] + client.query(q, assert.calls(function (err, res) { + assert.ifError(err) + client.end() done() - })); - })); -}); - + })) + })) +}) diff --git a/test/integration/gh-issues/675-tests.js b/test/integration/gh-issues/675-tests.js index b162b9df8..2e281ecc6 100644 --- a/test/integration/gh-issues/675-tests.js +++ b/test/integration/gh-issues/675-tests.js @@ -1,30 +1,30 @@ -"use strict"; -var helper = require('../test-helper'); -var assert = require('assert'); +'use strict' +var helper = require('../test-helper') +var assert = require('assert') const pool = new helper.pg.Pool() -pool.connect(function(err, client, done) { - if (err) throw err; +pool.connect(function (err, client, done) { + if (err) throw err - var c = 'CREATE TEMP TABLE posts (body TEXT)'; + var c = 'CREATE TEMP TABLE posts (body TEXT)' - client.query(c, function(err) { - if (err) throw err; + client.query(c, function (err) { + if (err) throw err - c = 'INSERT INTO posts (body) VALUES ($1) RETURNING *'; + c = 'INSERT INTO posts (body) VALUES ($1) RETURNING *' - var body = Buffer.from('foo'); - client.query(c, [body], function(err) { - if (err) throw err; + var body = Buffer.from('foo') + client.query(c, [body], function (err) { + if (err) throw err - body = Buffer.from([]); - client.query(c, [body], function(err, res) { - done(); + body = Buffer.from([]) + client.query(c, [body], function (err, res) { + done() - if (err) throw err; + if (err) throw err assert.equal(res.rows[0].body, '') - pool.end(); - }); - }); - }); -}); + pool.end() + }) + }) + }) +}) diff --git a/test/integration/gh-issues/787-tests.js b/test/integration/gh-issues/787-tests.js index 83ea85f3c..456c86463 100644 --- a/test/integration/gh-issues/787-tests.js +++ b/test/integration/gh-issues/787-tests.js @@ -1,13 +1,13 @@ -"use strict"; -var helper = require('../test-helper'); +'use strict' +var helper = require('../test-helper') const pool = new helper.pg.Pool() -pool.connect(function(err,client) { +pool.connect(function (err, client) { var q = { name: 'This is a super long query name just so I can test that an error message is properly spit out to console.error without throwing an exception or anything', text: 'SELECT NOW()' - }; - client.query(q, function() { - client.end(); - }); -}); + } + client.query(q, function () { + client.end() + }) +}) diff --git a/test/integration/gh-issues/882-tests.js b/test/integration/gh-issues/882-tests.js index 154f9e96a..6b4a3e2e6 100644 --- a/test/integration/gh-issues/882-tests.js +++ b/test/integration/gh-issues/882-tests.js @@ -1,9 +1,9 @@ -"use strict"; -//client should not hang on an empty query -var helper = require('../test-helper'); -var client = helper.client(); -client.query({ name: 'foo1', text: null}); -client.query({ name: 'foo2', text: ' ' }); -client.query({ name: 'foo3', text: '' }, function(err, res) { - client.end(); -}); +'use strict' +// client should not hang on an empty query +var helper = require('../test-helper') +var client = helper.client() +client.query({ name: 'foo1', text: null}) +client.query({ name: 'foo2', text: ' ' }) +client.query({ name: 'foo3', text: '' }, function (err, res) { + client.end() +}) diff --git a/test/integration/test-helper.js b/test/integration/test-helper.js index 56ea43ed5..ca844de33 100644 --- a/test/integration/test-helper.js +++ b/test/integration/test-helper.js @@ -1,28 +1,27 @@ -"use strict"; -var helper = require('./../test-helper'); +'use strict' +var helper = require('./../test-helper') -if(helper.args.native) { - Client = require('./../../lib/native'); - helper.Client = Client; - helper.pg = helper.pg.native; +if (helper.args.native) { + Client = require('./../../lib/native') + helper.Client = Client + helper.pg = helper.pg.native } -//creates a client from cli parameters -helper.client = function(cb) { - var client = new Client(); - client.connect(cb); - return client; -}; - -var semver = require('semver'); -helper.versionGTE = function(client, versionString, callback) { - client.query('SELECT version()', assert.calls(function(err, result) { - if(err) return callback(err); - var version = result.rows[0].version.split(' ')[1]; - return callback(null, semver.gte(version, versionString)); - })); -}; +// creates a client from cli parameters +helper.client = function (cb) { + var client = new Client() + client.connect(cb) + return client +} -//export parent helper stuffs -module.exports = helper; +var semver = require('semver') +helper.versionGTE = function (client, versionString, callback) { + client.query('SELECT version()', assert.calls(function (err, result) { + if (err) return callback(err) + var version = result.rows[0].version.split(' ')[1] + return callback(null, semver.gte(version, versionString)) + })) +} +// export parent helper stuffs +module.exports = helper diff --git a/test/native/callback-api-tests.js b/test/native/callback-api-tests.js index a0a77795b..a7fff1181 100644 --- a/test/native/callback-api-tests.js +++ b/test/native/callback-api-tests.js @@ -1,34 +1,34 @@ -"use strict"; -var domain = require('domain'); -var helper = require("./../test-helper"); -var Client = require("./../../lib/native"); +'use strict' +var domain = require('domain') +var helper = require('./../test-helper') +var Client = require('./../../lib/native') const suite = new helper.Suite() -suite.test('fires callback with results', function(done) { - var client = new Client(helper.config); - client.connect(); - client.query('SELECT 1 as num', assert.calls(function(err, result) { - assert(!err); - assert.equal(result.rows[0].num, 1); - assert.strictEqual(result.rowCount, 1); - client.query('SELECT * FROM person WHERE name = $1', ['Brian'], assert.calls(function(err, result) { - assert(!err); - assert.equal(result.rows[0].name, 'Brian'); - client.end(done); +suite.test('fires callback with results', function (done) { + var client = new Client(helper.config) + client.connect() + client.query('SELECT 1 as num', assert.calls(function (err, result) { + assert(!err) + assert.equal(result.rows[0].num, 1) + assert.strictEqual(result.rowCount, 1) + client.query('SELECT * FROM person WHERE name = $1', ['Brian'], assert.calls(function (err, result) { + assert(!err) + assert.equal(result.rows[0].name, 'Brian') + client.end(done) })) - })); + })) }) -suite.test('preserves domain', function(done) { - var dom = domain.create(); +suite.test('preserves domain', function (done) { + var dom = domain.create() - dom.run(function() { - var client = new Client(helper.config); - assert.ok(dom === require('domain').active, 'domain is active'); + dom.run(function () { + var client = new Client(helper.config) + assert.ok(dom === require('domain').active, 'domain is active') client.connect() - client.query('select 1', function() { - assert.ok(dom === require('domain').active, 'domain is still active'); - client.end(done); - }); - }); + client.query('select 1', function () { + assert.ok(dom === require('domain').active, 'domain is still active') + client.end(done) + }) + }) }) diff --git a/test/native/evented-api-tests.js b/test/native/evented-api-tests.js index 8a7c19b42..02a00cff4 100644 --- a/test/native/evented-api-tests.js +++ b/test/native/evented-api-tests.js @@ -1,34 +1,34 @@ -"use strict"; -var helper = require("../test-helper"); -var Client = require("../../lib/native"); -var Query = Client.Query; +'use strict' +var helper = require('../test-helper') +var Client = require('../../lib/native') +var Query = Client.Query -var setupClient = function() { - var client = new Client(helper.config); - client.connect(); - client.query("CREATE TEMP TABLE boom(name varchar(10), age integer)"); - client.query("INSERT INTO boom(name, age) VALUES('Aaron', 26)"); - client.query("INSERT INTO boom(name, age) VALUES('Brian', 28)"); - return client; +var setupClient = function () { + var client = new Client(helper.config) + client.connect() + client.query('CREATE TEMP TABLE boom(name varchar(10), age integer)') + client.query("INSERT INTO boom(name, age) VALUES('Aaron', 26)") + client.query("INSERT INTO boom(name, age) VALUES('Brian', 28)") + return client } -test('multiple results', function() { - test('queued queries', function() { - var client = setupClient(); - var q = client.query(new Query("SELECT name FROM BOOM")); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'Aaron'); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, "Brian"); +test('multiple results', function () { + test('queued queries', function () { + var client = setupClient() + var q = client.query(new Query('SELECT name FROM BOOM')) + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Aaron') + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Brian') }) }) - assert.emits(q, 'end', function() { - test('query with config', function() { - var q2 = client.query(new Query({text:'SELECT 1 as num'})); - assert.emits(q2, 'row', function(row) { - assert.strictEqual(row.num, 1); - assert.emits(q2, 'end', function() { - client.end(); + assert.emits(q, 'end', function () { + test('query with config', function () { + var q2 = client.query(new Query({text: 'SELECT 1 as num'})) + assert.emits(q2, 'row', function (row) { + assert.strictEqual(row.num, 1) + assert.emits(q2, 'end', function () { + client.end() }) }) }) @@ -36,55 +36,55 @@ test('multiple results', function() { }) }) -test('parameterized queries', function() { - test('with a single string param', function() { - var client = setupClient(); - var q = client.query(new Query("SELECT * FROM boom WHERE name = $1", ['Aaron'])); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'Aaron'); +test('parameterized queries', function () { + test('with a single string param', function () { + var client = setupClient() + var q = client.query(new Query('SELECT * FROM boom WHERE name = $1', ['Aaron'])) + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Aaron') + }) + assert.emits(q, 'end', function () { + client.end() }) - assert.emits(q, 'end', function() { - client.end(); - }); }) - test('with object config for query', function() { - var client = setupClient(); + test('with object config for query', function () { + var client = setupClient() var q = client.query(new Query({ - text: "SELECT name FROM boom WHERE name = $1", + text: 'SELECT name FROM boom WHERE name = $1', values: ['Brian'] - })); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'Brian'); + })) + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Brian') }) - assert.emits(q, 'end', function() { - client.end(); + assert.emits(q, 'end', function () { + client.end() }) }) - test('multiple parameters', function() { - var client = setupClient(); - var q = client.query(new Query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name', ['Aaron', 'Brian'])); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'Aaron'); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'Brian'); - assert.emits(q, 'end', function() { - client.end(); + test('multiple parameters', function () { + var client = setupClient() + var q = client.query(new Query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name', ['Aaron', 'Brian'])) + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Aaron') + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Brian') + assert.emits(q, 'end', function () { + client.end() }) }) }) }) - test('integer parameters', function() { - var client = setupClient(); - var q = client.query(new Query('SELECT * FROM boom WHERE age > $1', [27])); - assert.emits(q, 'row', function(row) { - assert.equal(row.name, 'Brian'); - assert.equal(row.age, 28); - }); - assert.emits(q, 'end', function() { - client.end(); + test('integer parameters', function () { + var client = setupClient() + var q = client.query(new Query('SELECT * FROM boom WHERE age > $1', [27])) + assert.emits(q, 'row', function (row) { + assert.equal(row.name, 'Brian') + assert.equal(row.age, 28) + }) + assert.emits(q, 'end', function () { + client.end() }) }) }) diff --git a/test/native/missing-native.js b/test/native/missing-native.js index d8474287f..35dad3f0b 100644 --- a/test/native/missing-native.js +++ b/test/native/missing-native.js @@ -1,7 +1,7 @@ -"use strict"; -//this test assumes it has been run from the Makefile -//and that node_modules/pg-native has been deleted +'use strict' +// this test assumes it has been run from the Makefile +// and that node_modules/pg-native has been deleted -var assert = require('assert'); +var assert = require('assert') -assert.equal(require('../../lib').native, null); +assert.equal(require('../../lib').native, null) diff --git a/test/native/native-vs-js-error-tests.js b/test/native/native-vs-js-error-tests.js index 59c6bb94d..842e01aae 100644 --- a/test/native/native-vs-js-error-tests.js +++ b/test/native/native-vs-js-error-tests.js @@ -1,21 +1,21 @@ -"use strict"; +'use strict' var assert = require('assert') -var Client = require('../../lib/client'); -var NativeClient = require('../../lib/native'); +var Client = require('../../lib/client') +var NativeClient = require('../../lib/native') -var client = new Client(); -var nativeClient = new NativeClient(); +var client = new Client() +var nativeClient = new NativeClient() -client.connect(); +client.connect() nativeClient.connect((err) => { client.query('SELECT alsdkfj', (err) => { - client.end(); + client.end() nativeClient.query('SELECT lkdasjfasd', (nativeErr) => { - for(var key in nativeErr) { + for (var key in nativeErr) { assert.equal(err[key], nativeErr[key], `Expected err.${key} to equal nativeErr.${key}`) } - nativeClient.end(); - }); - }); -}); + nativeClient.end() + }) + }) +}) diff --git a/test/native/stress-tests.js b/test/native/stress-tests.js index 32477cb8c..49904b12a 100644 --- a/test/native/stress-tests.js +++ b/test/native/stress-tests.js @@ -1,51 +1,51 @@ -"use strict"; -var helper = require(__dirname + "/../test-helper"); -var Client = require(__dirname + "/../../lib/native"); -var Query = Client.Query; +'use strict' +var helper = require(__dirname + '/../test-helper') +var Client = require(__dirname + '/../../lib/native') +var Query = Client.Query -test('many rows', function() { - var client = new Client(helper.config); - client.connect(); - var q = client.query(new Query("SELECT * FROM person")); - var rows = []; - q.on('row', function(row) { +test('many rows', function () { + var client = new Client(helper.config) + client.connect() + var q = client.query(new Query('SELECT * FROM person')) + var rows = [] + q.on('row', function (row) { rows.push(row) - }); - assert.emits(q, 'end', function() { - client.end(); - assert.lengthIs(rows, 26); }) -}); + assert.emits(q, 'end', function () { + client.end() + assert.lengthIs(rows, 26) + }) +}) -test('many queries', function() { - var client = new Client(helper.config); - client.connect(); - var count = 0; - var expected = 100; - for(var i = 0; i < expected; i++) { - var q = client.query(new Query("SELECT * FROM person")); - assert.emits(q, 'end', function() { - count++; - }); +test('many queries', function () { + var client = new Client(helper.config) + client.connect() + var count = 0 + var expected = 100 + for (var i = 0; i < expected; i++) { + var q = client.query(new Query('SELECT * FROM person')) + assert.emits(q, 'end', function () { + count++ + }) } - assert.emits(client, 'drain', function() { - client.end(); - assert.equal(count, expected); - }); -}); + assert.emits(client, 'drain', function () { + client.end() + assert.equal(count, expected) + }) +}) -test('many clients', function() { - var clients = []; - for(var i = 0; i < 10; i++) { - clients.push(new Client(helper.config)); +test('many clients', function () { + var clients = [] + for (var i = 0; i < 10; i++) { + clients.push(new Client(helper.config)) } - clients.forEach(function(client) { - client.connect(); - for(var i = 0; i < 20; i++) { - client.query('SELECT * FROM person'); + clients.forEach(function (client) { + client.connect() + for (var i = 0; i < 20; i++) { + client.query('SELECT * FROM person') } - assert.emits(client, 'drain', function() { - client.end(); + assert.emits(client, 'drain', function () { + client.end() }) }) }) diff --git a/test/suite.js b/test/suite.js index da6492fb6..5de9b281f 100644 --- a/test/suite.js +++ b/test/suite.js @@ -1,16 +1,16 @@ -"use strict"; -'use strict'; +'use strict' +'use strict' const async = require('async') class Test { - constructor(name, cb) { + constructor (name, cb) { this.name = name this.action = cb this.timeout = 5000 } - run(cb) { + run (cb) { try { this._run(cb) } catch (e) { @@ -18,7 +18,7 @@ class Test { } } - _run(cb) { + _run (cb) { if (!this.action) { console.log(`${this.name} skipped`) return cb() @@ -38,13 +38,13 @@ class Test { } class Suite { - constructor(name) { + constructor (name) { console.log('') this._queue = async.queue(this.run.bind(this), 1) this._queue.drain = () => { } } - run(test, cb) { + run (test, cb) { process.stdout.write(' ' + test.name + ' ') if (!test.action) { process.stdout.write('? - SKIPPED\n') @@ -69,7 +69,7 @@ class Suite { }) } - test(name, cb) { + test (name, cb) { const test = new Test(name, cb) this._queue.push(test) } diff --git a/test/test-buffers.js b/test/test-buffers.js index 0351559a9..9873a3100 100644 --- a/test/test-buffers.js +++ b/test/test-buffers.js @@ -1,58 +1,58 @@ -"use strict"; -require(__dirname+'/test-helper'); -//http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html +'use strict' +require(__dirname + '/test-helper') +// http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html -var buffers = {}; -buffers.readyForQuery = function() { +var buffers = {} +buffers.readyForQuery = function () { return new BufferList() .add(Buffer.from('I')) - .join(true,'Z'); -}; + .join(true, 'Z') +} -buffers.authenticationOk = function() { +buffers.authenticationOk = function () { return new BufferList() .addInt32(0) - .join(true, 'R'); -}; + .join(true, 'R') +} -buffers.authenticationCleartextPassword = function() { +buffers.authenticationCleartextPassword = function () { return new BufferList() .addInt32(3) - .join(true, 'R'); -}; + .join(true, 'R') +} -buffers.authenticationMD5Password = function() { +buffers.authenticationMD5Password = function () { return new BufferList() .addInt32(5) - .add(Buffer.from([1,2,3,4])) - .join(true, 'R'); -}; + .add(Buffer.from([1, 2, 3, 4])) + .join(true, 'R') +} -buffers.parameterStatus = function(name, value) { +buffers.parameterStatus = function (name, value) { return new BufferList() .addCString(name) .addCString(value) - .join(true, 'S'); -}; + .join(true, 'S') +} -buffers.backendKeyData = function(processID, secretKey) { +buffers.backendKeyData = function (processID, secretKey) { return new BufferList() .addInt32(processID) .addInt32(secretKey) - .join(true, 'K'); -}; + .join(true, 'K') +} -buffers.commandComplete = function(string) { +buffers.commandComplete = function (string) { return new BufferList() .addCString(string) - .join(true, 'C'); -}; - -buffers.rowDescription = function(fields) { - fields = fields || []; - var buf = new BufferList(); - buf.addInt16(fields.length); - fields.forEach(function(field) { + .join(true, 'C') +} + +buffers.rowDescription = function (fields) { + fields = fields || [] + var buf = new BufferList() + buf.addInt16(fields.length) + fields.forEach(function (field) { buf.addCString(field.name) .addInt32(field.tableID || 0) .addInt16(field.attributeNumber || 0) @@ -60,66 +60,66 @@ buffers.rowDescription = function(fields) { .addInt16(field.dataTypeSize || 0) .addInt32(field.typeModifier || 0) .addInt16(field.formatCode || 0) - }); - return buf.join(true, 'T'); -}; - -buffers.dataRow = function(columns) { - columns = columns || []; - var buf = new BufferList(); - buf.addInt16(columns.length); - columns.forEach(function(col) { - if(col == null) { - buf.addInt32(-1); + }) + return buf.join(true, 'T') +} + +buffers.dataRow = function (columns) { + columns = columns || [] + var buf = new BufferList() + buf.addInt16(columns.length) + columns.forEach(function (col) { + if (col == null) { + buf.addInt32(-1) } else { - var strBuf = Buffer.from(col, 'utf8'); - buf.addInt32(strBuf.length); - buf.add(strBuf); + var strBuf = Buffer.from(col, 'utf8') + buf.addInt32(strBuf.length) + buf.add(strBuf) } - }); - return buf.join(true, 'D'); -}; + }) + return buf.join(true, 'D') +} -buffers.error = function(fields) { - return errorOrNotice(fields).join(true, 'E'); -}; +buffers.error = function (fields) { + return errorOrNotice(fields).join(true, 'E') +} -buffers.notice = function(fields) { - return errorOrNotice(fields).join(true, 'N'); -}; +buffers.notice = function (fields) { + return errorOrNotice(fields).join(true, 'N') +} -var errorOrNotice = function(fields) { - fields = fields || []; - var buf = new BufferList(); - fields.forEach(function(field) { - buf.addChar(field.type); - buf.addCString(field.value); - }); - return buf.add(Buffer.from([0]));//terminator +var errorOrNotice = function (fields) { + fields = fields || [] + var buf = new BufferList() + fields.forEach(function (field) { + buf.addChar(field.type) + buf.addCString(field.value) + }) + return buf.add(Buffer.from([0]))// terminator } -buffers.parseComplete = function() { - return new BufferList().join(true, '1'); -}; +buffers.parseComplete = function () { + return new BufferList().join(true, '1') +} -buffers.bindComplete = function() { - return new BufferList().join(true, '2'); -}; +buffers.bindComplete = function () { + return new BufferList().join(true, '2') +} -buffers.notification = function(id, channel, payload) { +buffers.notification = function (id, channel, payload) { return new BufferList() .addInt32(id) .addCString(channel) .addCString(payload) .join(true, 'A') -}; +} -buffers.emptyQuery = function() { - return new BufferList().join(true, 'I'); -}; +buffers.emptyQuery = function () { + return new BufferList().join(true, 'I') +} -buffers.portalSuspended = function() { - return new BufferList().join(true, 's'); -}; +buffers.portalSuspended = function () { + return new BufferList().join(true, 's') +} -module.exports = buffers; +module.exports = buffers diff --git a/test/test-helper.js b/test/test-helper.js index 3bfc5177b..2f39be2aa 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -1,171 +1,170 @@ -"use strict"; -//make assert a global... -global.assert = require('assert'); -var EventEmitter = require('events').EventEmitter; -var sys = require('util'); +'use strict' +// make assert a global... +global.assert = require('assert') +var EventEmitter = require('events').EventEmitter +var sys = require('util') var BufferList = require('./buffer-list') const Suite = require('./suite') -const args = require('./cli'); +const args = require('./cli') -var Connection = require('./../lib/connection'); +var Connection = require('./../lib/connection') -global.Client = require('./../lib').Client; +global.Client = require('./../lib').Client -process.on('uncaughtException', function(d) { +process.on('uncaughtException', function (d) { if ('stack' in d && 'message' in d) { - console.log("Message: " + d.message); - console.log(d.stack); + console.log('Message: ' + d.message) + console.log(d.stack) } else { - console.log(d); + console.log(d) } - process.exit(-1); -}); + process.exit(-1) +}) -assert.same = function(actual, expected) { - for(var key in expected) { - assert.equal(actual[key], expected[key]); +assert.same = function (actual, expected) { + for (var key in expected) { + assert.equal(actual[key], expected[key]) } -}; +} -assert.emits = function(item, eventName, callback, message) { - var called = false; - var id = setTimeout(function() { - test("Should have called '" + eventName + "' event", function() { +assert.emits = function (item, eventName, callback, message) { + var called = false + var id = setTimeout(function () { + test("Should have called '" + eventName + "' event", function () { assert.ok(called, message || "Expected '" + eventName + "' to be called.") - }); - },5000); + }) + }, 5000) - item.once(eventName, function() { + item.once(eventName, function () { if (eventName === 'error') { // belt and braces test to ensure all error events return an error assert.ok(arguments[0] instanceof Error, - "Expected error events to throw instances of Error but found: " + sys.inspect(arguments[0])); + 'Expected error events to throw instances of Error but found: ' + sys.inspect(arguments[0])) } - called = true; - clearTimeout(id); - assert.ok(true); - if(callback) { - callback.apply(item, arguments); + called = true + clearTimeout(id) + assert.ok(true) + if (callback) { + callback.apply(item, arguments) } - }); -}; + }) +} -assert.UTCDate = function(actual, year, month, day, hours, min, sec, milisecond) { - var actualYear = actual.getUTCFullYear(); - assert.equal(actualYear, year, "expected year " + year + " but got " + actualYear); +assert.UTCDate = function (actual, year, month, day, hours, min, sec, milisecond) { + var actualYear = actual.getUTCFullYear() + assert.equal(actualYear, year, 'expected year ' + year + ' but got ' + actualYear) - var actualMonth = actual.getUTCMonth(); - assert.equal(actualMonth, month, "expected month " + month + " but got " + actualMonth); + var actualMonth = actual.getUTCMonth() + assert.equal(actualMonth, month, 'expected month ' + month + ' but got ' + actualMonth) - var actualDate = actual.getUTCDate(); - assert.equal(actualDate, day, "expected day " + day + " but got " + actualDate); + var actualDate = actual.getUTCDate() + assert.equal(actualDate, day, 'expected day ' + day + ' but got ' + actualDate) - var actualHours = actual.getUTCHours(); - assert.equal(actualHours, hours, "expected hours " + hours + " but got " + actualHours); + var actualHours = actual.getUTCHours() + assert.equal(actualHours, hours, 'expected hours ' + hours + ' but got ' + actualHours) - var actualMin = actual.getUTCMinutes(); - assert.equal(actualMin, min, "expected min " + min + " but got " + actualMin); + var actualMin = actual.getUTCMinutes() + assert.equal(actualMin, min, 'expected min ' + min + ' but got ' + actualMin) - var actualSec = actual.getUTCSeconds(); - assert.equal(actualSec, sec, "expected sec " + sec + " but got " + actualSec); + var actualSec = actual.getUTCSeconds() + assert.equal(actualSec, sec, 'expected sec ' + sec + ' but got ' + actualSec) - var actualMili = actual.getUTCMilliseconds(); - assert.equal(actualMili, milisecond, "expected milisecond " + milisecond + " but got " + actualMili); -}; + var actualMili = actual.getUTCMilliseconds() + assert.equal(actualMili, milisecond, 'expected milisecond ' + milisecond + ' but got ' + actualMili) +} -assert.equalBuffers = function(actual, expected) { - if(actual.length != expected.length) { +assert.equalBuffers = function (actual, expected) { + if (actual.length != expected.length) { spit(actual, expected) - assert.equal(actual.length, expected.length); + assert.equal(actual.length, expected.length) } - for(var i = 0; i < actual.length; i++) { - if(actual[i] != expected[i]) { + for (var i = 0; i < actual.length; i++) { + if (actual[i] != expected[i]) { spit(actual, expected) } - assert.equal(actual[i],expected[i]); + assert.equal(actual[i], expected[i]) } -}; +} -assert.empty = function(actual) { - assert.lengthIs(actual, 0); -}; +assert.empty = function (actual) { + assert.lengthIs(actual, 0) +} -assert.success = function(callback) { - if(callback.length === 1 || callback.length === 0) { - return assert.calls(function(err, arg) { - if(err) { - console.log(err); +assert.success = function (callback) { + if (callback.length === 1 || callback.length === 0) { + return assert.calls(function (err, arg) { + if (err) { + console.log(err) } - assert(!err); - callback(arg); - }); + assert(!err) + callback(arg) + }) } else if (callback.length === 2) { - return assert.calls(function(err, arg1, arg2) { - if(err) { - console.log(err); + return assert.calls(function (err, arg1, arg2) { + if (err) { + console.log(err) } - assert(!err); - callback(arg1, arg2); - }); + assert(!err) + callback(arg1, arg2) + }) } else { - throw new Error('need to preserve arrity of wrapped function'); + throw new Error('need to preserve arrity of wrapped function') } } -assert.throws = function(offender) { +assert.throws = function (offender) { try { - offender(); + offender() } catch (e) { - assert.ok(e instanceof Error, "Expected " + offender + " to throw instances of Error"); - return; + assert.ok(e instanceof Error, 'Expected ' + offender + ' to throw instances of Error') + return } - assert.ok(false, "Expected " + offender + " to throw exception"); + assert.ok(false, 'Expected ' + offender + ' to throw exception') } -assert.lengthIs = function(actual, expectedLength) { - assert.equal(actual.length, expectedLength); -}; +assert.lengthIs = function (actual, expectedLength) { + assert.equal(actual.length, expectedLength) +} -var expect = function(callback, timeout) { - var executed = false; - timeout = timeout || parseInt(process.env.TEST_TIMEOUT) || 5000; - var id = setTimeout(function() { +var expect = function (callback, timeout) { + var executed = false + timeout = timeout || parseInt(process.env.TEST_TIMEOUT) || 5000 + var id = setTimeout(function () { assert.ok(executed, - "Expected execution of function to be fired within " + timeout - + " milliseconds " + - + " (hint: export TEST_TIMEOUT=" - + " to change timeout globally)" - + callback.toString()); + 'Expected execution of function to be fired within ' + timeout + + ' milliseconds ' + + +' (hint: export TEST_TIMEOUT=' + + ' to change timeout globally)' + + callback.toString()) }, timeout) - if(callback.length < 3) { - return function(err, queryResult) { - clearTimeout(id); + if (callback.length < 3) { + return function (err, queryResult) { + clearTimeout(id) if (err) { - assert.ok(err instanceof Error, "Expected errors to be instances of Error: " + sys.inspect(err)); + assert.ok(err instanceof Error, 'Expected errors to be instances of Error: ' + sys.inspect(err)) } callback.apply(this, arguments) } - } else if(callback.length == 3) { - return function(err, arg1, arg2) { - clearTimeout(id); + } else if (callback.length == 3) { + return function (err, arg1, arg2) { + clearTimeout(id) if (err) { - assert.ok(err instanceof Error, "Expected errors to be instances of Error: " + sys.inspect(err)); + assert.ok(err instanceof Error, 'Expected errors to be instances of Error: ' + sys.inspect(err)) } callback.apply(this, arguments) } } else { - throw new Error("Unsupported arrity " + callback.length); + throw new Error('Unsupported arrity ' + callback.length) } - } -assert.calls = expect; +assert.calls = expect -assert.isNull = function(item, message) { - message = message || "expected " + item + " to be null"; - assert.ok(item === null, message); -}; +assert.isNull = function (item, message) { + message = message || 'expected ' + item + ' to be null' + assert.ok(item === null, message) +} const getMode = () => { if (args.native) return 'native' @@ -173,70 +172,69 @@ const getMode = () => { return '' } -global.test = function(name, action) { - test.testCount ++; - test[name] = action; - var result = test[name](); - if(result === false) { - process.stdout.write('?'); - }else{ - process.stdout.write('.'); +global.test = function (name, action) { + test.testCount ++ + test[name] = action + var result = test[name]() + if (result === false) { + process.stdout.write('?') + } else { + process.stdout.write('.') } -}; +} -//print out the filename -process.stdout.write(require('path').basename(process.argv[1])); -if(args.binary) process.stdout.write(' (binary)'); -if(args.native) process.stdout.write(' (native)'); +// print out the filename +process.stdout.write(require('path').basename(process.argv[1])) +if (args.binary) process.stdout.write(' (binary)') +if (args.native) process.stdout.write(' (native)') -process.on('exit', function() { +process.on('exit', function () { console.log('') }) -process.on('uncaughtException', function(err) { - console.error("\n %s", err.stack || err.toString()) - //causes xargs to abort right away - process.exit(255); -}); +process.on('uncaughtException', function (err) { + console.error('\n %s', err.stack || err.toString()) + // causes xargs to abort right away + process.exit(255) +}) -var count = 0; +var count = 0 -var Sink = function(expected, timeout, callback) { - var defaultTimeout = 5000; - if(typeof timeout == 'function') { - callback = timeout; - timeout = defaultTimeout; +var Sink = function (expected, timeout, callback) { + var defaultTimeout = 5000 + if (typeof timeout === 'function') { + callback = timeout + timeout = defaultTimeout } - timeout = timeout || defaultTimeout; - var internalCount = 0; - var kill = function() { - assert.ok(false, "Did not reach expected " + expected + " with an idle timeout of " + timeout); + timeout = timeout || defaultTimeout + var internalCount = 0 + var kill = function () { + assert.ok(false, 'Did not reach expected ' + expected + ' with an idle timeout of ' + timeout) } - var killTimeout = setTimeout(kill, timeout); + var killTimeout = setTimeout(kill, timeout) return { - add: function(count) { - count = count || 1; - internalCount += count; + add: function (count) { + count = count || 1 + internalCount += count clearTimeout(killTimeout) - if(internalCount < expected) { + if (internalCount < expected) { killTimeout = setTimeout(kill, timeout) - } - else { - assert.equal(internalCount, expected); - callback(); + } else { + assert.equal(internalCount, expected) + callback() } } } } -var getTimezoneOffset = Date.prototype.getTimezoneOffset; +var getTimezoneOffset = Date.prototype.getTimezoneOffset -var setTimezoneOffset = function(minutesOffset) { - Date.prototype.getTimezoneOffset = function () { return minutesOffset; }; +var setTimezoneOffset = function (minutesOffset) { + Date.prototype.getTimezoneOffset = function () { return minutesOffset } } -var resetTimezoneOffset = function() { - Date.prototype.getTimezoneOffset = getTimezoneOffset; +var resetTimezoneOffset = function () { + Date.prototype.getTimezoneOffset = getTimezoneOffset } module.exports = { @@ -249,6 +247,4 @@ module.exports = { Client: Client, setTimezoneOffset: setTimezoneOffset, resetTimezoneOffset: resetTimezoneOffset -}; - - +} diff --git a/test/unit/client/cleartext-password-tests.js b/test/unit/client/cleartext-password-tests.js index 67e7c67b8..cd8dbb005 100644 --- a/test/unit/client/cleartext-password-tests.js +++ b/test/unit/client/cleartext-password-tests.js @@ -1,23 +1,21 @@ -"use strict"; +'use strict' -const createClient = require('./test-helper').createClient; +const createClient = require('./test-helper').createClient /* * TODO: Add _some_ comments to explain what it is we're testing, and how the * code-being-tested works behind the scenes. */ -test('cleartext password authentication', function(){ - - var client = createClient(); - client.password = "!"; - client.connection.stream.packets = []; - client.connection.emit('authenticationCleartextPassword'); - test('responds with password', function() { - var packets = client.connection.stream.packets; - assert.lengthIs(packets, 1); - var packet = packets[0]; - assert.equalBuffers(packet, [0x70, 0, 0, 0, 6, 33, 0]); - }); - -}); +test('cleartext password authentication', function () { + var client = createClient() + client.password = '!' + client.connection.stream.packets = [] + client.connection.emit('authenticationCleartextPassword') + test('responds with password', function () { + var packets = client.connection.stream.packets + assert.lengthIs(packets, 1) + var packet = packets[0] + assert.equalBuffers(packet, [0x70, 0, 0, 0, 6, 33, 0]) + }) +}) diff --git a/test/unit/client/configuration-tests.js b/test/unit/client/configuration-tests.js index bf007ee74..9c1fadc80 100644 --- a/test/unit/client/configuration-tests.js +++ b/test/unit/client/configuration-tests.js @@ -1,171 +1,167 @@ -"use strict"; -require(__dirname+'/test-helper'); - -var pguser = process.env['PGUSER'] || process.env.USER; -var pgdatabase = process.env['PGDATABASE'] || process.env.USER; -var pgport = process.env['PGPORT'] || 5432; - -test('client settings', function() { - - test('defaults', function() { - var client = new Client(); - assert.equal(client.user, pguser); - assert.equal(client.database, pgdatabase); - assert.equal(client.port, pgport); - assert.equal(client.ssl, false); - }); - - test('custom', function() { - var user = 'brian'; - var database = 'pgjstest'; - var password = 'boom'; +'use strict' +require(__dirname + '/test-helper') + +var pguser = process.env['PGUSER'] || process.env.USER +var pgdatabase = process.env['PGDATABASE'] || process.env.USER +var pgport = process.env['PGPORT'] || 5432 + +test('client settings', function () { + test('defaults', function () { + var client = new Client() + assert.equal(client.user, pguser) + assert.equal(client.database, pgdatabase) + assert.equal(client.port, pgport) + assert.equal(client.ssl, false) + }) + + test('custom', function () { + var user = 'brian' + var database = 'pgjstest' + var password = 'boom' var client = new Client({ user: user, database: database, port: 321, password: password, ssl: true - }); + }) - assert.equal(client.user, user); - assert.equal(client.database, database); - assert.equal(client.port, 321); - assert.equal(client.password, password); - assert.equal(client.ssl, true); - }); + assert.equal(client.user, user) + assert.equal(client.database, database) + assert.equal(client.port, 321) + assert.equal(client.password, password) + assert.equal(client.ssl, true) + }) - test('custom ssl default on', function() { - var old = process.env.PGSSLMODE; - process.env.PGSSLMODE = "prefer"; + test('custom ssl default on', function () { + var old = process.env.PGSSLMODE + process.env.PGSSLMODE = 'prefer' - var client = new Client(); - process.env.PGSSLMODE = old; + var client = new Client() + process.env.PGSSLMODE = old - assert.equal(client.ssl, true); - }); + assert.equal(client.ssl, true) + }) - test('custom ssl force off', function() { - var old = process.env.PGSSLMODE; - process.env.PGSSLMODE = "prefer"; + test('custom ssl force off', function () { + var old = process.env.PGSSLMODE + process.env.PGSSLMODE = 'prefer' var client = new Client({ ssl: false - }); - process.env.PGSSLMODE = old; - - assert.equal(client.ssl, false); - }); - -}); + }) + process.env.PGSSLMODE = old -test('initializing from a config string', function() { + assert.equal(client.ssl, false) + }) +}) +test('initializing from a config string', function () { test('uses connectionString property', function () { var client = new Client({ connectionString: 'postgres://brian:pass@host1:333/databasename' }) - assert.equal(client.user, 'brian'); - assert.equal(client.password, "pass"); - assert.equal(client.host, "host1"); - assert.equal(client.port, 333); - assert.equal(client.database, "databasename"); + assert.equal(client.user, 'brian') + assert.equal(client.password, 'pass') + assert.equal(client.host, 'host1') + assert.equal(client.port, 333) + assert.equal(client.database, 'databasename') }) - test('uses the correct values from the config string', function() { - var client = new Client("postgres://brian:pass@host1:333/databasename") - assert.equal(client.user, 'brian'); - assert.equal(client.password, "pass"); - assert.equal(client.host, "host1"); - assert.equal(client.port, 333); - assert.equal(client.database, "databasename"); - }); - - test('uses the correct values from the config string with space in password', function() { - var client = new Client("postgres://brian:pass word@host1:333/databasename") - assert.equal(client.user, 'brian'); - assert.equal(client.password, "pass word"); - assert.equal(client.host, "host1"); - assert.equal(client.port, 333); - assert.equal(client.database, "databasename"); - }); - - test('when not including all values the defaults are used', function() { - var client = new Client("postgres://host1"); - assert.equal(client.user, process.env['PGUSER'] || process.env.USER); - assert.equal(client.password, process.env['PGPASSWORD'] || null); - assert.equal(client.host, "host1"); - assert.equal(client.port, process.env['PGPORT'] || 5432); - assert.equal(client.database, process.env['PGDATABASE'] || process.env.USER); - }); - - test('when not including all values the environment variables are used', function() { - var envUserDefined = process.env['PGUSER'] !== undefined; - var envPasswordDefined = process.env['PGPASSWORD'] !== undefined; - var envDBDefined = process.env['PGDATABASE'] !== undefined; - var envHostDefined = process.env['PGHOST'] !== undefined; - var envPortDefined = process.env['PGPORT'] !== undefined; - - var savedEnvUser = process.env['PGUSER']; - var savedEnvPassword = process.env['PGPASSWORD']; - var savedEnvDB = process.env['PGDATABASE']; - var savedEnvHost = process.env['PGHOST']; - var savedEnvPort = process.env['PGPORT']; - - process.env['PGUSER'] = 'utUser1'; - process.env['PGPASSWORD'] = 'utPass1'; - process.env['PGDATABASE'] = 'utDB1'; - process.env['PGHOST'] = 'utHost1'; - process.env['PGPORT'] = 5464; - - var client = new Client("postgres://host1"); - assert.equal(client.user, process.env['PGUSER']); - assert.equal(client.password, process.env['PGPASSWORD']); - assert.equal(client.host, "host1"); - assert.equal(client.port, process.env['PGPORT']); - assert.equal(client.database, process.env['PGDATABASE']); + test('uses the correct values from the config string', function () { + var client = new Client('postgres://brian:pass@host1:333/databasename') + assert.equal(client.user, 'brian') + assert.equal(client.password, 'pass') + assert.equal(client.host, 'host1') + assert.equal(client.port, 333) + assert.equal(client.database, 'databasename') + }) + + test('uses the correct values from the config string with space in password', function () { + var client = new Client('postgres://brian:pass word@host1:333/databasename') + assert.equal(client.user, 'brian') + assert.equal(client.password, 'pass word') + assert.equal(client.host, 'host1') + assert.equal(client.port, 333) + assert.equal(client.database, 'databasename') + }) + + test('when not including all values the defaults are used', function () { + var client = new Client('postgres://host1') + assert.equal(client.user, process.env['PGUSER'] || process.env.USER) + assert.equal(client.password, process.env['PGPASSWORD'] || null) + assert.equal(client.host, 'host1') + assert.equal(client.port, process.env['PGPORT'] || 5432) + assert.equal(client.database, process.env['PGDATABASE'] || process.env.USER) + }) + + test('when not including all values the environment variables are used', function () { + var envUserDefined = process.env['PGUSER'] !== undefined + var envPasswordDefined = process.env['PGPASSWORD'] !== undefined + var envDBDefined = process.env['PGDATABASE'] !== undefined + var envHostDefined = process.env['PGHOST'] !== undefined + var envPortDefined = process.env['PGPORT'] !== undefined + + var savedEnvUser = process.env['PGUSER'] + var savedEnvPassword = process.env['PGPASSWORD'] + var savedEnvDB = process.env['PGDATABASE'] + var savedEnvHost = process.env['PGHOST'] + var savedEnvPort = process.env['PGPORT'] + + process.env['PGUSER'] = 'utUser1' + process.env['PGPASSWORD'] = 'utPass1' + process.env['PGDATABASE'] = 'utDB1' + process.env['PGHOST'] = 'utHost1' + process.env['PGPORT'] = 5464 + + var client = new Client('postgres://host1') + assert.equal(client.user, process.env['PGUSER']) + assert.equal(client.password, process.env['PGPASSWORD']) + assert.equal(client.host, 'host1') + assert.equal(client.port, process.env['PGPORT']) + assert.equal(client.database, process.env['PGDATABASE']) if (envUserDefined) { - process.env['PGUSER'] = savedEnvUser; + process.env['PGUSER'] = savedEnvUser } else { - delete process.env['PGUSER']; + delete process.env['PGUSER'] } if (envPasswordDefined) { - process.env['PGPASSWORD'] = savedEnvPassword; + process.env['PGPASSWORD'] = savedEnvPassword } else { - delete process.env['PGPASSWORD']; + delete process.env['PGPASSWORD'] } if (envDBDefined) { - process.env['PGDATABASE'] = savedEnvDB; + process.env['PGDATABASE'] = savedEnvDB } else { - delete process.env['PGDATABASE']; + delete process.env['PGDATABASE'] } if (envHostDefined) { - process.env['PGHOST'] = savedEnvHost; + process.env['PGHOST'] = savedEnvHost } else { - delete process.env['PGHOST']; + delete process.env['PGHOST'] } if (envPortDefined) { - process.env['PGPORT'] = savedEnvPort; + process.env['PGPORT'] = savedEnvPort } else { - delete process.env['PGPORT']; + delete process.env['PGPORT'] } - }); -}); - -test('calls connect correctly on connection', function() { - var client = new Client("/tmp"); - var usedPort = ""; - var usedHost = ""; - client.connection.connect = function(port, host) { - usedPort = port; - usedHost = host; - }; - client.connect(); - assert.equal(usedPort, "/tmp/.s.PGSQL." + pgport); - assert.strictEqual(usedHost, undefined); -}); - + }) +}) + +test('calls connect correctly on connection', function () { + var client = new Client('/tmp') + var usedPort = '' + var usedHost = '' + client.connection.connect = function (port, host) { + usedPort = port + usedHost = host + } + client.connect() + assert.equal(usedPort, '/tmp/.s.PGSQL.' + pgport) + assert.strictEqual(usedHost, undefined) +}) diff --git a/test/unit/client/early-disconnect-tests.js b/test/unit/client/early-disconnect-tests.js index c8d7fbc59..35a587d99 100644 --- a/test/unit/client/early-disconnect-tests.js +++ b/test/unit/client/early-disconnect-tests.js @@ -1,17 +1,17 @@ -"use strict"; -var helper = require('./test-helper'); -var net = require('net'); -var pg = require('../../../lib/index.js'); +'use strict' +var helper = require('./test-helper') +var net = require('net') +var pg = require('../../../lib/index.js') /* console.log() messages show up in `make test` output. TODO: fix it. */ -var server = net.createServer(function(c) { - c.destroy(); - server.close(); -}); +var server = net.createServer(function (c) { + c.destroy() + server.close() +}) -server.listen(7777, function() { - var client = new pg.Client('postgres://localhost:7777'); - client.connect(assert.calls(function(err) { - assert(err); - })); -}); +server.listen(7777, function () { + var client = new pg.Client('postgres://localhost:7777') + client.connect(assert.calls(function (err) { + assert(err) + })) +}) diff --git a/test/unit/client/escape-tests.js b/test/unit/client/escape-tests.js index 7ea640fcb..8229a3a37 100644 --- a/test/unit/client/escape-tests.js +++ b/test/unit/client/escape-tests.js @@ -1,73 +1,73 @@ -"use strict"; -var helper = require(__dirname + '/test-helper'); - -function createClient(callback) { - var client = new Client(helper.config); - client.connect(function(err) { - return callback(client); - }); +'use strict' +var helper = require(__dirname + '/test-helper') + +function createClient (callback) { + var client = new Client(helper.config) + client.connect(function (err) { + return callback(client) + }) } -var testLit = function(testName, input, expected) { - test(testName, function(){ - var client = new Client(helper.config); - var actual = client.escapeLiteral(input); - assert.equal(expected, actual); - }); -}; - -var testIdent = function(testName, input, expected) { - test(testName, function(){ - var client = new Client(helper.config); - var actual = client.escapeIdentifier(input); - assert.equal(expected, actual); - }); -}; +var testLit = function (testName, input, expected) { + test(testName, function () { + var client = new Client(helper.config) + var actual = client.escapeLiteral(input) + assert.equal(expected, actual) + }) +} + +var testIdent = function (testName, input, expected) { + test(testName, function () { + var client = new Client(helper.config) + var actual = client.escapeIdentifier(input) + assert.equal(expected, actual) + }) +} testLit('escapeLiteral: no special characters', - 'hello world', "'hello world'"); + 'hello world', "'hello world'") testLit('escapeLiteral: contains double quotes only', - 'hello " world', "'hello \" world'"); + 'hello " world', "'hello \" world'") testLit('escapeLiteral: contains single quotes only', - 'hello \' world', "'hello \'\' world'"); + 'hello \' world', "'hello \'\' world'") testLit('escapeLiteral: contains backslashes only', - 'hello \\ world', " E'hello \\\\ world'"); + 'hello \\ world', " E'hello \\\\ world'") testLit('escapeLiteral: contains single quotes and double quotes', - 'hello \' " world', "'hello '' \" world'"); + 'hello \' " world', "'hello '' \" world'") testLit('escapeLiteral: contains double quotes and backslashes', - 'hello \\ " world', " E'hello \\\\ \" world'"); + 'hello \\ " world', " E'hello \\\\ \" world'") testLit('escapeLiteral: contains single quotes and backslashes', - 'hello \\ \' world', " E'hello \\\\ '' world'"); + 'hello \\ \' world', " E'hello \\\\ '' world'") testLit('escapeLiteral: contains single quotes, double quotes, and backslashes', - 'hello \\ \' " world', " E'hello \\\\ '' \" world'"); + 'hello \\ \' " world', " E'hello \\\\ '' \" world'") testIdent('escapeIdentifier: no special characters', - 'hello world', '"hello world"'); + 'hello world', '"hello world"') testIdent('escapeIdentifier: contains double quotes only', - 'hello " world', '"hello "" world"'); + 'hello " world', '"hello "" world"') testIdent('escapeIdentifier: contains single quotes only', - 'hello \' world', '"hello \' world"'); + 'hello \' world', '"hello \' world"') testIdent('escapeIdentifier: contains backslashes only', - 'hello \\ world', '"hello \\ world"'); + 'hello \\ world', '"hello \\ world"') testIdent('escapeIdentifier: contains single quotes and double quotes', - 'hello \' " world', '"hello \' "" world"'); + 'hello \' " world', '"hello \' "" world"') testIdent('escapeIdentifier: contains double quotes and backslashes', - 'hello \\ " world', '"hello \\ "" world"'); + 'hello \\ " world', '"hello \\ "" world"') testIdent('escapeIdentifier: contains single quotes and backslashes', - 'hello \\ \' world', '"hello \\ \' world"'); + 'hello \\ \' world', '"hello \\ \' world"') testIdent('escapeIdentifier: contains single quotes, double quotes, and backslashes', - 'hello \\ \' " world', '"hello \\ \' "" world"'); + 'hello \\ \' " world', '"hello \\ \' "" world"') diff --git a/test/unit/client/md5-password-tests.js b/test/unit/client/md5-password-tests.js index 63a0398d1..26e233ed5 100644 --- a/test/unit/client/md5-password-tests.js +++ b/test/unit/client/md5-password-tests.js @@ -1,26 +1,26 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') var utils = require('../../../lib/utils') -test('md5 authentication', function() { - var client = helper.createClient(); - client.password = "!"; - var salt = Buffer.from([1, 2, 3, 4]); - client.connection.emit('authenticationMD5Password', {salt: salt}); +test('md5 authentication', function () { + var client = helper.createClient() + client.password = '!' + var salt = Buffer.from([1, 2, 3, 4]) + client.connection.emit('authenticationMD5Password', {salt: salt}) - test('responds', function() { - assert.lengthIs(client.connection.stream.packets, 1); - test('should have correct encrypted data', function() { - var encrypted = utils.md5(client.password + client.user); - encrypted = utils.md5(encrypted + salt.toString('binary')); - var password = "md5" + encrypted - //how do we want to test this? + test('responds', function () { + assert.lengthIs(client.connection.stream.packets, 1) + test('should have correct encrypted data', function () { + var encrypted = utils.md5(client.password + client.user) + encrypted = utils.md5(encrypted + salt.toString('binary')) + var password = 'md5' + encrypted + // how do we want to test this? assert.equalBuffers(client.connection.stream.packets[0], new BufferList() - .addCString(password).join(true,'p')); - }); - }); -}); + .addCString(password).join(true, 'p')) + }) + }) +}) -test('md5 of utf-8 strings', function() { - assert.equal(utils.md5('😊'), '5deda34cd95f304948d2bc1b4a62c11e'); -}); +test('md5 of utf-8 strings', function () { + assert.equal(utils.md5('😊'), '5deda34cd95f304948d2bc1b4a62c11e') +}) diff --git a/test/unit/client/notification-tests.js b/test/unit/client/notification-tests.js index dab8f6087..5ca9df226 100644 --- a/test/unit/client/notification-tests.js +++ b/test/unit/client/notification-tests.js @@ -1,11 +1,10 @@ -"use strict"; -var helper = require(__dirname + "/test-helper"); +'use strict' +var helper = require(__dirname + '/test-helper') -test('passes connection notification', function() { - var client = helper.client(); - assert.emits(client, 'notice', function(msg) { - assert.equal(msg, "HAY!!"); +test('passes connection notification', function () { + var client = helper.client() + assert.emits(client, 'notice', function (msg) { + assert.equal(msg, 'HAY!!') }) - client.connection.emit('notice', "HAY!!"); + client.connection.emit('notice', 'HAY!!') }) - diff --git a/test/unit/client/prepared-statement-tests.js b/test/unit/client/prepared-statement-tests.js index 50327bf44..0dc9e80a1 100644 --- a/test/unit/client/prepared-statement-tests.js +++ b/test/unit/client/prepared-statement-tests.js @@ -1,88 +1,88 @@ -"use strict"; -var helper = require('./test-helper'); +'use strict' +var helper = require('./test-helper') var Query = require('../../../lib/query') -var client = helper.client(); -var con = client.connection; -var parseArg = null; -con.parse = function(arg) { - parseArg = arg; - process.nextTick(function() { - con.emit('parseComplete'); - }); -}; +var client = helper.client() +var con = client.connection +var parseArg = null +con.parse = function (arg) { + parseArg = arg + process.nextTick(function () { + con.emit('parseComplete') + }) +} -var bindArg = null; -con.bind = function(arg) { - bindArg = arg; - process.nextTick(function(){ - con.emit('bindComplete'); - }); -}; +var bindArg = null +con.bind = function (arg) { + bindArg = arg + process.nextTick(function () { + con.emit('bindComplete') + }) +} -var executeArg = null; -con.execute = function(arg) { - executeArg = arg; - process.nextTick(function() { - con.emit('rowData',{ fields: [] }); - con.emit('commandComplete', { text: "" }); - }); -}; +var executeArg = null +con.execute = function (arg) { + executeArg = arg + process.nextTick(function () { + con.emit('rowData', { fields: [] }) + con.emit('commandComplete', { text: '' }) + }) +} -var describeArg = null; -con.describe = function(arg) { - describeArg = arg; - process.nextTick(function() { - con.emit('rowDescription', { fields: [] }); - }); -}; +var describeArg = null +con.describe = function (arg) { + describeArg = arg + process.nextTick(function () { + con.emit('rowDescription', { fields: [] }) + }) +} -var syncCalled = false; -con.flush = function() { -}; -con.sync = function() { - syncCalled = true; - process.nextTick(function() { - con.emit('readyForQuery'); - }); -}; +var syncCalled = false +con.flush = function () { +} +con.sync = function () { + syncCalled = true + process.nextTick(function () { + con.emit('readyForQuery') + }) +} -test('bound command', function() { - test('simple, unnamed bound command', function() { - assert.ok(client.connection.emit('readyForQuery')); +test('bound command', function () { + test('simple, unnamed bound command', function () { + assert.ok(client.connection.emit('readyForQuery')) var query = client.query(new Query({ text: 'select * from X where name = $1', values: ['hi'] - })); + })) - assert.emits(query,'end', function() { - test('parse argument', function() { - assert.equal(parseArg.name, null); - assert.equal(parseArg.text, 'select * from X where name = $1'); - assert.equal(parseArg.types, null); - }); + assert.emits(query, 'end', function () { + test('parse argument', function () { + assert.equal(parseArg.name, null) + assert.equal(parseArg.text, 'select * from X where name = $1') + assert.equal(parseArg.types, null) + }) - test('bind argument', function() { - assert.equal(bindArg.statement, null); - assert.equal(bindArg.portal, null); - assert.lengthIs(bindArg.values, 1); + test('bind argument', function () { + assert.equal(bindArg.statement, null) + assert.equal(bindArg.portal, null) + assert.lengthIs(bindArg.values, 1) assert.equal(bindArg.values[0], 'hi') - }); + }) - test('describe argument', function() { - assert.equal(describeArg.type, 'P'); - assert.equal(describeArg.name, ""); - }); + test('describe argument', function () { + assert.equal(describeArg.type, 'P') + assert.equal(describeArg.name, '') + }) - test('execute argument', function() { - assert.equal(executeArg.portal, null); - assert.equal(executeArg.rows, null); - }); + test('execute argument', function () { + assert.equal(executeArg.portal, null) + assert.equal(executeArg.rows, null) + }) - test('sync called', function() { - assert.ok(syncCalled); - }); - }); - }); -}); + test('sync called', function () { + assert.ok(syncCalled) + }) + }) + }) +}) diff --git a/test/unit/client/query-queue-tests.js b/test/unit/client/query-queue-tests.js index 2aa3b6b0a..62069c011 100644 --- a/test/unit/client/query-queue-tests.js +++ b/test/unit/client/query-queue-tests.js @@ -1,53 +1,53 @@ -"use strict"; -var helper = require(__dirname + '/test-helper'); -var Connection = require(__dirname + '/../../../lib/connection'); +'use strict' +var helper = require(__dirname + '/test-helper') +var Connection = require(__dirname + '/../../../lib/connection') -test('drain', function() { - var con = new Connection({stream: "NO"}); - var client = new Client({connection:con}); - con.connect = function() { - con.emit('connect'); - }; - con.query = function() { - }; - client.connect(); +test('drain', function () { + var con = new Connection({stream: 'NO'}) + var client = new Client({connection: con}) + con.connect = function () { + con.emit('connect') + } + con.query = function () { + } + client.connect() - var raisedDrain = false; - client.on('drain', function() { - raisedDrain = true; - }); + var raisedDrain = false + client.on('drain', function () { + raisedDrain = true + }) - client.query("hello"); - client.query("sup"); - client.query('boom'); + client.query('hello') + client.query('sup') + client.query('boom') - test("with pending queries", function() { - test("does not emit drain", function() { - assert.equal(raisedDrain, false); - }); - }); + test('with pending queries', function () { + test('does not emit drain', function () { + assert.equal(raisedDrain, false) + }) + }) - test("after some queries executed", function() { - con.emit('readyForQuery'); - test("does not emit drain", function() { - assert.equal(raisedDrain, false); - }); - }); + test('after some queries executed', function () { + con.emit('readyForQuery') + test('does not emit drain', function () { + assert.equal(raisedDrain, false) + }) + }) - test("when all queries are sent", function() { - con.emit('readyForQuery'); - con.emit('readyForQuery'); - test("does not emit drain", function() { - assert.equal(raisedDrain, false); - }); - }); + test('when all queries are sent', function () { + con.emit('readyForQuery') + con.emit('readyForQuery') + test('does not emit drain', function () { + assert.equal(raisedDrain, false) + }) + }) - test("after last query finishes", function() { - con.emit('readyForQuery'); - test("emits drain", function() { - process.nextTick(function() { - assert.ok(raisedDrain); + test('after last query finishes', function () { + con.emit('readyForQuery') + test('emits drain', function () { + process.nextTick(function () { + assert.ok(raisedDrain) }) - }); - }); -}); + }) + }) +}) diff --git a/test/unit/client/result-metadata-tests.js b/test/unit/client/result-metadata-tests.js index c3f26620b..59b83443e 100644 --- a/test/unit/client/result-metadata-tests.js +++ b/test/unit/client/result-metadata-tests.js @@ -1,38 +1,37 @@ -"use strict"; -var helper = require(__dirname + "/test-helper") +'use strict' +var helper = require(__dirname + '/test-helper') -var testForTag = function(tagText, callback) { - test('includes command tag data for tag ' + tagText, function() { - - var client = helper.client(); +var testForTag = function (tagText, callback) { + test('includes command tag data for tag ' + tagText, function () { + var client = helper.client() client.connection.emit('readyForQuery') - var query = client.query("whatever", assert.calls((err, result) => { - assert.ok(result != null, "should pass something to this event") + var query = client.query('whatever', assert.calls((err, result) => { + assert.ok(result != null, 'should pass something to this event') callback(result) - })); + })) assert.lengthIs(client.connection.queries, 1) client.connection.emit('commandComplete', { text: tagText - }); + }) - client.connection.emit('readyForQuery'); + client.connection.emit('readyForQuery') }) } -var check = function(oid, rowCount, command) { - return function(result) { - if(oid != null) { - assert.equal(result.oid, oid); +var check = function (oid, rowCount, command) { + return function (result) { + if (oid != null) { + assert.equal(result.oid, oid) } - assert.equal(result.rowCount, rowCount); - assert.equal(result.command, command); + assert.equal(result.rowCount, rowCount) + assert.equal(result.command, command) } } -testForTag("INSERT 0 3", check(0, 3, "INSERT")); -testForTag("INSERT 841 1", check(841, 1, "INSERT")); -testForTag("DELETE 10", check(null, 10, "DELETE")); -testForTag("UPDATE 11", check(null, 11, "UPDATE")); -testForTag("SELECT 20", check(null, 20, "SELECT")); +testForTag('INSERT 0 3', check(0, 3, 'INSERT')) +testForTag('INSERT 841 1', check(841, 1, 'INSERT')) +testForTag('DELETE 10', check(null, 10, 'DELETE')) +testForTag('UPDATE 11', check(null, 11, 'UPDATE')) +testForTag('SELECT 20', check(null, 20, 'SELECT')) diff --git a/test/unit/client/simple-query-tests.js b/test/unit/client/simple-query-tests.js index 29ab00123..363c44dbe 100644 --- a/test/unit/client/simple-query-tests.js +++ b/test/unit/client/simple-query-tests.js @@ -1,129 +1,123 @@ -"use strict"; -var helper = require(__dirname + "/test-helper"); +'use strict' +var helper = require(__dirname + '/test-helper') var Query = require('../../../lib/query') -test('executing query', function() { - - test("queing query", function() { - - test('when connection is ready', function() { - var client = helper.client(); - assert.empty(client.connection.queries); - client.connection.emit('readyForQuery'); - client.query('yes'); - assert.lengthIs(client.connection.queries, 1); - assert.equal(client.connection.queries, 'yes'); - }); - - test('when connection is not ready', function() { - var client = helper.client(); - - test('query is not sent', function() { - client.query('boom'); - assert.empty(client.connection.queries); - }); - - test('sends query to connection once ready', function() { - assert.ok(client.connection.emit('readyForQuery')); - assert.lengthIs(client.connection.queries, 1); - assert.equal(client.connection.queries[0], "boom"); - }); - - }); - - test("multiple in the queue", function() { - var client = helper.client(); - var connection = client.connection; - var queries = connection.queries; - client.query('one'); - client.query('two'); - client.query('three'); - assert.empty(queries); - - test("after one ready for query",function() { - connection.emit('readyForQuery'); - assert.lengthIs(queries, 1); - assert.equal(queries[0], "one"); - }); - - test('after two ready for query', function() { - connection.emit('readyForQuery'); - assert.lengthIs(queries, 2); - }); - - test("after a bunch more", function() { - connection.emit('readyForQuery'); - connection.emit('readyForQuery'); - connection.emit('readyForQuery'); - assert.lengthIs(queries, 3); - assert.equal(queries[0], "one"); - assert.equal(queries[1], 'two'); - assert.equal(queries[2], 'three'); - }); - }); - }); - - test("query event binding and flow", function() { - var client = helper.client(); - var con = client.connection; - var query = client.query(new Query('whatever')); - - test("has no queries sent before ready", function() { - assert.empty(con.queries); - }); - - test('sends query on readyForQuery event', function() { - con.emit('readyForQuery'); - assert.lengthIs(con.queries, 1); - assert.equal(con.queries[0], 'whatever'); - }); - - test('handles rowDescription message', function() { - var handled = con.emit('rowDescription',{ +test('executing query', function () { + test('queing query', function () { + test('when connection is ready', function () { + var client = helper.client() + assert.empty(client.connection.queries) + client.connection.emit('readyForQuery') + client.query('yes') + assert.lengthIs(client.connection.queries, 1) + assert.equal(client.connection.queries, 'yes') + }) + + test('when connection is not ready', function () { + var client = helper.client() + + test('query is not sent', function () { + client.query('boom') + assert.empty(client.connection.queries) + }) + + test('sends query to connection once ready', function () { + assert.ok(client.connection.emit('readyForQuery')) + assert.lengthIs(client.connection.queries, 1) + assert.equal(client.connection.queries[0], 'boom') + }) + }) + + test('multiple in the queue', function () { + var client = helper.client() + var connection = client.connection + var queries = connection.queries + client.query('one') + client.query('two') + client.query('three') + assert.empty(queries) + + test('after one ready for query', function () { + connection.emit('readyForQuery') + assert.lengthIs(queries, 1) + assert.equal(queries[0], 'one') + }) + + test('after two ready for query', function () { + connection.emit('readyForQuery') + assert.lengthIs(queries, 2) + }) + + test('after a bunch more', function () { + connection.emit('readyForQuery') + connection.emit('readyForQuery') + connection.emit('readyForQuery') + assert.lengthIs(queries, 3) + assert.equal(queries[0], 'one') + assert.equal(queries[1], 'two') + assert.equal(queries[2], 'three') + }) + }) + }) + + test('query event binding and flow', function () { + var client = helper.client() + var con = client.connection + var query = client.query(new Query('whatever')) + + test('has no queries sent before ready', function () { + assert.empty(con.queries) + }) + + test('sends query on readyForQuery event', function () { + con.emit('readyForQuery') + assert.lengthIs(con.queries, 1) + assert.equal(con.queries[0], 'whatever') + }) + + test('handles rowDescription message', function () { + var handled = con.emit('rowDescription', { fields: [{ name: 'boom' }] - }); - assert.ok(handled, "should have handlded rowDescription"); - }); + }) + assert.ok(handled, 'should have handlded rowDescription') + }) - test('handles dataRow messages', function() { - assert.emits(query, 'row', function(row) { - assert.equal(row['boom'], "hi"); - }); + test('handles dataRow messages', function () { + assert.emits(query, 'row', function (row) { + assert.equal(row['boom'], 'hi') + }) - var handled = con.emit('dataRow', { fields: ["hi"] }); - assert.ok(handled, "should have handled first data row message"); + var handled = con.emit('dataRow', { fields: ['hi'] }) + assert.ok(handled, 'should have handled first data row message') - assert.emits(query, 'row', function(row) { - assert.equal(row['boom'], "bye"); - }); + assert.emits(query, 'row', function (row) { + assert.equal(row['boom'], 'bye') + }) - var handledAgain = con.emit('dataRow', { fields: ["bye"] }); - assert.ok(handledAgain, "should have handled seciond data row message"); - }); + var handledAgain = con.emit('dataRow', { fields: ['bye'] }) + assert.ok(handledAgain, 'should have handled seciond data row message') + }) - //multiple command complete messages will be sent - //when multiple queries are in a simple command - test('handles command complete messages', function() { + // multiple command complete messages will be sent + // when multiple queries are in a simple command + test('handles command complete messages', function () { con.emit('commandComplete', { text: 'INSERT 31 1' - }); - }); - - test('removes itself after another readyForQuery message', function() { - return false; - assert.emits(query, "end", function(msg) { - //TODO do we want to check the complete messages? - }); - con.emit("readyForQuery"); - //this would never actually happen - ['dataRow','rowDescription', 'commandComplete'].forEach(function(msg) { - assert.equal(con.emit(msg), false, "Should no longer be picking up '"+ msg +"' messages"); - }); - }); - - }); - -}); - + }) + }) + + test('removes itself after another readyForQuery message', function () { + return false + assert.emits(query, 'end', function (msg) { + // TODO do we want to check the complete messages? + }) + con.emit('readyForQuery'); + // this would never actually happen + ['dataRow', 'rowDescription', 'commandComplete'].forEach(function (msg) { + assert.equal(con.emit(msg), false, "Should no longer be picking up '" + msg + "' messages") + }) + }) + }) +}) diff --git a/test/unit/client/stream-and-query-error-interaction-tests.js b/test/unit/client/stream-and-query-error-interaction-tests.js index 0815fccd1..af0e09a64 100644 --- a/test/unit/client/stream-and-query-error-interaction-tests.js +++ b/test/unit/client/stream-and-query-error-interaction-tests.js @@ -1,29 +1,29 @@ -"use strict"; -var helper = require(__dirname + '/test-helper'); -var Connection = require(__dirname + '/../../../lib/connection'); -var Client = require(__dirname + '/../../../lib/client'); +'use strict' +var helper = require(__dirname + '/test-helper') +var Connection = require(__dirname + '/../../../lib/connection') +var Client = require(__dirname + '/../../../lib/client') -test('emits end when not in query', function() { - var stream = new (require('events').EventEmitter)(); - stream.write = function() { - //NOOP +test('emits end when not in query', function () { + var stream = new (require('events').EventEmitter)() + stream.write = function () { + // NOOP } - var client = new Client({connection: new Connection({stream: stream})}); - client.connect(assert.calls(function() { - client.query('SELECT NOW()', assert.calls(function(err, result) { - assert(err); - })); - })); - assert.emits(client, 'error'); - assert.emits(client, 'end'); - client.connection.emit('connect'); - process.nextTick(function() { - client.connection.emit('readyForQuery'); - assert.equal(client.queryQueue.length, 0); - assert(client.activeQuery, 'client should have issued query'); - process.nextTick(function() { - stream.emit('close'); - }); - }); -}); + var client = new Client({connection: new Connection({stream: stream})}) + client.connect(assert.calls(function () { + client.query('SELECT NOW()', assert.calls(function (err, result) { + assert(err) + })) + })) + assert.emits(client, 'error') + assert.emits(client, 'end') + client.connection.emit('connect') + process.nextTick(function () { + client.connection.emit('readyForQuery') + assert.equal(client.queryQueue.length, 0) + assert(client.activeQuery, 'client should have issued query') + process.nextTick(function () { + stream.emit('close') + }) + }) +}) diff --git a/test/unit/client/test-helper.js b/test/unit/client/test-helper.js index fe1765d68..24f94df3b 100644 --- a/test/unit/client/test-helper.js +++ b/test/unit/client/test-helper.js @@ -1,21 +1,21 @@ -"use strict"; -var helper = require('../test-helper'); -var Connection = require('../../../lib/connection'); +'use strict' +var helper = require('../test-helper') +var Connection = require('../../../lib/connection') -var makeClient = function() { - var connection = new Connection({stream: "no"}); - connection.startup = function() {}; - connection.connect = function() {}; - connection.query = function(text) { - this.queries.push(text); - }; - connection.queries = []; - var client = new Client({connection: connection}); - client.connect(); - client.connection.emit('connect'); - return client; -}; +var makeClient = function () { + var connection = new Connection({stream: 'no'}) + connection.startup = function () {} + connection.connect = function () {} + connection.query = function (text) { + this.queries.push(text) + } + connection.queries = [] + var client = new Client({connection: connection}) + client.connect() + client.connection.emit('connect') + return client +} module.exports = Object.assign({ client: makeClient -}, helper); +}, helper) diff --git a/test/unit/client/throw-in-type-parser-tests.js b/test/unit/client/throw-in-type-parser-tests.js index 06580eb0e..24883241c 100644 --- a/test/unit/client/throw-in-type-parser-tests.js +++ b/test/unit/client/throw-in-type-parser-tests.js @@ -1,70 +1,69 @@ -"use strict"; -var helper = require("./test-helper"); -var Query = require("../../../lib/query"); -var types = require("pg-types"); +'use strict' +var helper = require('./test-helper') +var Query = require('../../../lib/query') +var types = require('pg-types') -const suite = new helper.Suite(); +const suite = new helper.Suite() -var typeParserError = new Error("TEST: Throw in type parsers"); +var typeParserError = new Error('TEST: Throw in type parsers') -types.setTypeParser("special oid that will throw", function() { - throw typeParserError; -}); +types.setTypeParser('special oid that will throw', function () { + throw typeParserError +}) const emitFakeEvents = con => { setImmediate(() => { - con.emit("readyForQuery"); + con.emit('readyForQuery') - con.emit("rowDescription", { + con.emit('rowDescription', { fields: [ { - name: "boom", - dataTypeID: "special oid that will throw" + name: 'boom', + dataTypeID: 'special oid that will throw' } ] - }); + }) - con.emit("dataRow", { fields: ["hi"] }); - con.emit("dataRow", { fields: ["hi"] }); - con.emit("commandComplete", { text: "INSERT 31 1" }); - con.emit("readyForQuery"); - }); -}; + con.emit('dataRow', { fields: ['hi'] }) + con.emit('dataRow', { fields: ['hi'] }) + con.emit('commandComplete', { text: 'INSERT 31 1' }) + con.emit('readyForQuery') + }) +} -suite.test("emits error", function(done) { - var handled; - var client = helper.client(); - var con = client.connection; - var query = client.query(new Query("whatever")); +suite.test('emits error', function (done) { + var handled + var client = helper.client() + var con = client.connection + var query = client.query(new Query('whatever')) emitFakeEvents(con) - assert.emits(query, "error", function(err) { - assert.equal(err, typeParserError); - done(); - }); -}); + assert.emits(query, 'error', function (err) { + assert.equal(err, typeParserError) + done() + }) +}) -suite.test("calls callback with error", function(done) { - var handled; +suite.test('calls callback with error', function (done) { + var handled - var callbackCalled = 0; + var callbackCalled = 0 - var client = helper.client(); - var con = client.connection; - emitFakeEvents(con); - var query = client.query("whatever", function(err) { - assert.equal(err, typeParserError); - done(); - }); - -}); + var client = helper.client() + var con = client.connection + emitFakeEvents(con) + var query = client.query('whatever', function (err) { + assert.equal(err, typeParserError) + done() + }) +}) -suite.test("rejects promise with error", function(done) { - var client = helper.client(); - var con = client.connection; - emitFakeEvents(con); - client.query("whatever").catch(err => { - assert.equal(err, typeParserError); - done(); - }); -}); +suite.test('rejects promise with error', function (done) { + var client = helper.client() + var con = client.connection + emitFakeEvents(con) + client.query('whatever').catch(err => { + assert.equal(err, typeParserError) + done() + }) +}) diff --git a/test/unit/connection-parameters/creation-tests.js b/test/unit/connection-parameters/creation-tests.js index f0268a137..aa39a038b 100644 --- a/test/unit/connection-parameters/creation-tests.js +++ b/test/unit/connection-parameters/creation-tests.js @@ -1,55 +1,55 @@ -"use strict"; -var helper = require(__dirname + '/../test-helper'); -var assert = require('assert'); -var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters'); -var defaults = require(__dirname + '/../../../lib').defaults; - -//clear process.env -for(var key in process.env) { - delete process.env[key]; +'use strict' +var helper = require(__dirname + '/../test-helper') +var assert = require('assert') +var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters') +var defaults = require(__dirname + '/../../../lib').defaults + +// clear process.env +for (var key in process.env) { + delete process.env[key] } -test('ConnectionParameters construction', function() { - assert.ok(new ConnectionParameters(), 'with null config'); - assert.ok(new ConnectionParameters({user: 'asdf'}), 'with config object'); - assert.ok(new ConnectionParameters('postgres://localhost/postgres'), 'with connection string'); -}); - -var compare = function(actual, expected, type) { - assert.equal(actual.user, expected.user, type + ' user'); - assert.equal(actual.database, expected.database, type + ' database'); - assert.equal(actual.port, expected.port, type + ' port'); - assert.equal(actual.host, expected.host, type + ' host'); - assert.equal(actual.password, expected.password, type + ' password'); - assert.equal(actual.binary, expected.binary, type + ' binary'); -}; - -test('ConnectionParameters initializing from defaults', function() { - var subject = new ConnectionParameters(); - compare(subject, defaults, 'defaults'); - assert.ok(subject.isDomainSocket === false); -}); - -test('ConnectionParameters initializing from defaults with connectionString set', function() { +test('ConnectionParameters construction', function () { + assert.ok(new ConnectionParameters(), 'with null config') + assert.ok(new ConnectionParameters({user: 'asdf'}), 'with config object') + assert.ok(new ConnectionParameters('postgres://localhost/postgres'), 'with connection string') +}) + +var compare = function (actual, expected, type) { + assert.equal(actual.user, expected.user, type + ' user') + assert.equal(actual.database, expected.database, type + ' database') + assert.equal(actual.port, expected.port, type + ' port') + assert.equal(actual.host, expected.host, type + ' host') + assert.equal(actual.password, expected.password, type + ' password') + assert.equal(actual.binary, expected.binary, type + ' binary') +} + +test('ConnectionParameters initializing from defaults', function () { + var subject = new ConnectionParameters() + compare(subject, defaults, 'defaults') + assert.ok(subject.isDomainSocket === false) +}) + +test('ConnectionParameters initializing from defaults with connectionString set', function () { var config = { - user : 'brians-are-the-best', - database : 'scoobysnacks', - port : 7777, - password : 'mypassword', - host : 'foo.bar.net', - binary : defaults.binary - }; - - var original_value = defaults.connectionString; + user: 'brians-are-the-best', + database: 'scoobysnacks', + port: 7777, + password: 'mypassword', + host: 'foo.bar.net', + binary: defaults.binary + } + + var original_value = defaults.connectionString // Just changing this here doesn't actually work because it's no longer in scope when viewed inside of // of ConnectionParameters() so we have to pass in the defaults explicitly to test it - defaults.connectionString = 'postgres://brians-are-the-best:mypassword@foo.bar.net:7777/scoobysnacks'; - var subject = new ConnectionParameters(defaults); - defaults.connectionString = original_value; - compare(subject, config, 'defaults-connectionString'); -}); + defaults.connectionString = 'postgres://brians-are-the-best:mypassword@foo.bar.net:7777/scoobysnacks' + var subject = new ConnectionParameters(defaults) + defaults.connectionString = original_value + compare(subject, config, 'defaults-connectionString') +}) -test('ConnectionParameters initializing from config', function() { +test('ConnectionParameters initializing from config', function () { var config = { user: 'brian', database: 'home', @@ -61,58 +61,58 @@ test('ConnectionParameters initializing from config', function() { ssl: { asdf: 'blah' } - }; - var subject = new ConnectionParameters(config); - compare(subject, config, 'config'); - assert.ok(subject.isDomainSocket === false); -}); - -test('escape spaces if present', function() { - var subject = new ConnectionParameters('postgres://localhost/post gres'); - assert.equal(subject.database, 'post gres'); -}); - -test('do not double escape spaces', function() { - var subject = new ConnectionParameters('postgres://localhost/post%20gres'); - assert.equal(subject.database, 'post gres'); -}); - -test('initializing with unix domain socket', function() { - var subject = new ConnectionParameters('/var/run/'); - assert.ok(subject.isDomainSocket); - assert.equal(subject.host, '/var/run/'); - assert.equal(subject.database, defaults.user); -}); - -test('initializing with unix domain socket and a specific database, the simple way', function() { - var subject = new ConnectionParameters('/var/run/ mydb'); - assert.ok(subject.isDomainSocket); - assert.equal(subject.host, '/var/run/'); - assert.equal(subject.database, 'mydb'); -}); - -test('initializing with unix domain socket, the health way', function() { - var subject = new ConnectionParameters('socket:/some path/?db=my[db]&encoding=utf8'); - assert.ok(subject.isDomainSocket); - assert.equal(subject.host, '/some path/'); - assert.equal(subject.database, 'my[db]', 'must to be escaped and unescaped trough "my%5Bdb%5D"'); - assert.equal(subject.client_encoding, 'utf8'); -}); - -test('initializing with unix domain socket, the escaped health way', function() { - var subject = new ConnectionParameters('socket:/some%20path/?db=my%2Bdb&encoding=utf8'); - assert.ok(subject.isDomainSocket); - assert.equal(subject.host, '/some path/'); - assert.equal(subject.database, 'my+db'); - assert.equal(subject.client_encoding, 'utf8'); -}); - -test('libpq connection string building', function() { - var checkForPart = function(array, part) { - assert.ok(array.indexOf(part) > -1, array.join(" ") + " did not contain " + part); + } + var subject = new ConnectionParameters(config) + compare(subject, config, 'config') + assert.ok(subject.isDomainSocket === false) +}) + +test('escape spaces if present', function () { + var subject = new ConnectionParameters('postgres://localhost/post gres') + assert.equal(subject.database, 'post gres') +}) + +test('do not double escape spaces', function () { + var subject = new ConnectionParameters('postgres://localhost/post%20gres') + assert.equal(subject.database, 'post gres') +}) + +test('initializing with unix domain socket', function () { + var subject = new ConnectionParameters('/var/run/') + assert.ok(subject.isDomainSocket) + assert.equal(subject.host, '/var/run/') + assert.equal(subject.database, defaults.user) +}) + +test('initializing with unix domain socket and a specific database, the simple way', function () { + var subject = new ConnectionParameters('/var/run/ mydb') + assert.ok(subject.isDomainSocket) + assert.equal(subject.host, '/var/run/') + assert.equal(subject.database, 'mydb') +}) + +test('initializing with unix domain socket, the health way', function () { + var subject = new ConnectionParameters('socket:/some path/?db=my[db]&encoding=utf8') + assert.ok(subject.isDomainSocket) + assert.equal(subject.host, '/some path/') + assert.equal(subject.database, 'my[db]', 'must to be escaped and unescaped trough "my%5Bdb%5D"') + assert.equal(subject.client_encoding, 'utf8') +}) + +test('initializing with unix domain socket, the escaped health way', function () { + var subject = new ConnectionParameters('socket:/some%20path/?db=my%2Bdb&encoding=utf8') + assert.ok(subject.isDomainSocket) + assert.equal(subject.host, '/some path/') + assert.equal(subject.database, 'my+db') + assert.equal(subject.client_encoding, 'utf8') +}) + +test('libpq connection string building', function () { + var checkForPart = function (array, part) { + assert.ok(array.indexOf(part) > -1, array.join(' ') + ' did not contain ' + part) } - test('builds simple string', function() { + test('builds simple string', function () { var config = { user: 'brian', password: 'xyz', @@ -120,132 +120,131 @@ test('libpq connection string building', function() { host: 'localhost', database: 'bam' } - var subject = new ConnectionParameters(config); - subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert(!err); - var parts = constring.split(" "); - checkForPart(parts, "user='brian'"); - checkForPart(parts, "password='xyz'"); - checkForPart(parts, "port='888'"); - checkForPart(parts, "hostaddr='127.0.0.1'"); - checkForPart(parts, "dbname='bam'"); - })); - }); - - test('builds dns string', function() { + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString(assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, "password='xyz'") + checkForPart(parts, "port='888'") + checkForPart(parts, "hostaddr='127.0.0.1'") + checkForPart(parts, "dbname='bam'") + })) + }) + + test('builds dns string', function () { var config = { user: 'brian', password: 'asdf', port: 5432, host: 'localhost' - }; - var subject = new ConnectionParameters(config); - subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert(!err); - var parts = constring.split(" "); - checkForPart(parts, "user='brian'"); - checkForPart(parts, "hostaddr='127.0.0.1'"); - })); - }); - - test('error when dns fails', function() { + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString(assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, "hostaddr='127.0.0.1'") + })) + }) + + test('error when dns fails', function () { var config = { user: 'brian', password: 'asf', port: 5432, host: 'asdlfkjasldfkksfd#!$!!!!..com' - }; - var subject = new ConnectionParameters(config); - subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert.ok(err); + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString(assert.calls(function (err, constring) { + assert.ok(err) assert.isNull(constring) - })); - }); + })) + }) - test('connecting to unix domain socket', function() { + test('connecting to unix domain socket', function () { var config = { user: 'brian', password: 'asf', port: 5432, host: '/tmp/' - }; - var subject = new ConnectionParameters(config); - subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert(!err); - var parts = constring.split(" "); - checkForPart(parts, "user='brian'"); - checkForPart(parts, "host='/tmp/'"); - })); - }); - - test('config contains quotes and backslashes', function() { + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString(assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, "host='/tmp/'") + })) + }) + + test('config contains quotes and backslashes', function () { var config = { user: 'not\\brian', password: 'bad\'chars', port: 5432, host: '/tmp/' - }; - var subject = new ConnectionParameters(config); - subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert(!err); - var parts = constring.split(" "); - checkForPart(parts, "user='not\\\\brian'"); - checkForPart(parts, "password='bad\\'chars'"); - })); - }); - - test("encoding can be specified by config", function() { + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString(assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='not\\\\brian'") + checkForPart(parts, "password='bad\\'chars'") + })) + }) + + test('encoding can be specified by config', function () { var config = { - client_encoding: "utf-8" + client_encoding: 'utf-8' } - var subject = new ConnectionParameters(config); - subject.getLibpqConnectionString(assert.calls(function(err, constring) { - assert(!err); - var parts = constring.split(" "); - checkForPart(parts, "client_encoding='utf-8'"); - })); + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString(assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "client_encoding='utf-8'") + })) }) test('password contains < and/or > characters', function () { - return false; + return false var sourceConfig = { - user:'brian', + user: 'brian', password: 'helloe', port: 5432, host: 'localhost', database: 'postgres' } - var connectionString = 'postgres://' + sourceConfig.user + ':' + sourceConfig.password + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database; - var subject = new ConnectionParameters(connectionString); - assert.equal(subject.password, sourceConfig.password); - }); - - test('username or password contains weird characters', function() { - var defaults = require('../../../lib/defaults'); - defaults.ssl = true; - var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000'; - var subject = new ConnectionParameters(strang); - assert.equal(subject.user, 'my f%irst name'); - assert.equal(subject.password, 'is&%awesome!'); - assert.equal(subject.host, 'localhost'); - assert.equal(subject.ssl, true); - }); - - test("url is properly encoded", function() { - var encoded = "pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl"; - var subject = new ConnectionParameters(encoded); - assert.equal(subject.user, "bi%na%%ry "); - assert.equal(subject.password, "s@f#"); - assert.equal(subject.host, 'localhost'); - assert.equal(subject.database, " u%20rl"); - }); - - test('ssl is set on client', function() { + var connectionString = 'postgres://' + sourceConfig.user + ':' + sourceConfig.password + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database + var subject = new ConnectionParameters(connectionString) + assert.equal(subject.password, sourceConfig.password) + }) + + test('username or password contains weird characters', function () { + var defaults = require('../../../lib/defaults') + defaults.ssl = true + var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000' + var subject = new ConnectionParameters(strang) + assert.equal(subject.user, 'my f%irst name') + assert.equal(subject.password, 'is&%awesome!') + assert.equal(subject.host, 'localhost') + assert.equal(subject.ssl, true) + }) + + test('url is properly encoded', function () { + var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl' + var subject = new ConnectionParameters(encoded) + assert.equal(subject.user, 'bi%na%%ry ') + assert.equal(subject.password, 's@f#') + assert.equal(subject.host, 'localhost') + assert.equal(subject.database, ' u%20rl') + }) + + test('ssl is set on client', function () { var Client = require('../../../lib/client') - var defaults = require('../../../lib/defaults'); - defaults.ssl = true; + var defaults = require('../../../lib/defaults') + defaults.ssl = true var c = new Client('postgres://user@password:host/database') assert(c.ssl, 'Client should have ssl enabled via defaults') }) - -}); +}) diff --git a/test/unit/connection-parameters/environment-variable-tests.js b/test/unit/connection-parameters/environment-variable-tests.js index 2f41fecdc..2c5e503d6 100644 --- a/test/unit/connection-parameters/environment-variable-tests.js +++ b/test/unit/connection-parameters/environment-variable-tests.js @@ -1,115 +1,113 @@ -"use strict"; -var helper = require(__dirname + '/../test-helper'); -var assert = require('assert'); -var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters'); -var defaults = require(__dirname + '/../../../lib').defaults; - -//clear process.env -var realEnv = {}; -for(var key in process.env) { - realEnv[key] = process.env[key]; - delete process.env[key]; +'use strict' +var helper = require(__dirname + '/../test-helper') +var assert = require('assert') +var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters') +var defaults = require(__dirname + '/../../../lib').defaults + +// clear process.env +var realEnv = {} +for (var key in process.env) { + realEnv[key] = process.env[key] + delete process.env[key] } -test('ConnectionParameters initialized from environment variables', function(t) { - process.env['PGHOST'] = 'local'; - process.env['PGUSER'] = 'bmc2'; - process.env['PGPORT'] = 7890; - process.env['PGDATABASE'] = 'allyerbase'; - process.env['PGPASSWORD'] = 'open'; - - var subject = new ConnectionParameters(); - assert.equal(subject.host, 'local', 'env host'); - assert.equal(subject.user, 'bmc2', 'env user'); - assert.equal(subject.port, 7890, 'env port'); - assert.equal(subject.database, 'allyerbase', 'env database'); - assert.equal(subject.password, 'open', 'env password'); -}); - -test('ConnectionParameters initialized from mix', function(t) { - delete process.env['PGPASSWORD']; - delete process.env['PGDATABASE']; +test('ConnectionParameters initialized from environment variables', function (t) { + process.env['PGHOST'] = 'local' + process.env['PGUSER'] = 'bmc2' + process.env['PGPORT'] = 7890 + process.env['PGDATABASE'] = 'allyerbase' + process.env['PGPASSWORD'] = 'open' + + var subject = new ConnectionParameters() + assert.equal(subject.host, 'local', 'env host') + assert.equal(subject.user, 'bmc2', 'env user') + assert.equal(subject.port, 7890, 'env port') + assert.equal(subject.database, 'allyerbase', 'env database') + assert.equal(subject.password, 'open', 'env password') +}) + +test('ConnectionParameters initialized from mix', function (t) { + delete process.env['PGPASSWORD'] + delete process.env['PGDATABASE'] var subject = new ConnectionParameters({ user: 'testing', database: 'zugzug' - }); - assert.equal(subject.host, 'local', 'env host'); - assert.equal(subject.user, 'testing', 'config user'); - assert.equal(subject.port, 7890, 'env port'); - assert.equal(subject.database, 'zugzug', 'config database'); - assert.equal(subject.password, defaults.password, 'defaults password'); -}); - -//clear process.env -for(var key in process.env) { - delete process.env[key]; -} + }) + assert.equal(subject.host, 'local', 'env host') + assert.equal(subject.user, 'testing', 'config user') + assert.equal(subject.port, 7890, 'env port') + assert.equal(subject.database, 'zugzug', 'config database') + assert.equal(subject.password, defaults.password, 'defaults password') +}) -test('connection string parsing', function(t) { - var string = 'postgres://brian:pw@boom:381/lala'; - var subject = new ConnectionParameters(string); - assert.equal(subject.host, 'boom', 'string host'); - assert.equal(subject.user, 'brian', 'string user'); - assert.equal(subject.password, 'pw', 'string password'); - assert.equal(subject.port, 381, 'string port'); - assert.equal(subject.database, 'lala', 'string database'); -}); - -test('connection string parsing - ssl', function(t) { - var string = 'postgres://brian:pw@boom:381/lala?ssl=true'; - var subject = new ConnectionParameters(string); - assert.equal(subject.ssl, true, 'ssl'); - - string = 'postgres://brian:pw@boom:381/lala?ssl=1'; - subject = new ConnectionParameters(string); - assert.equal(subject.ssl, true, 'ssl'); - - string = 'postgres://brian:pw@boom:381/lala?other&ssl=true'; - subject = new ConnectionParameters(string); - assert.equal(subject.ssl, true, 'ssl'); - - string = 'postgres://brian:pw@boom:381/lala?ssl=0'; - subject = new ConnectionParameters(string); - assert.equal(!!subject.ssl, false, 'ssl'); - - string = 'postgres://brian:pw@boom:381/lala'; - subject = new ConnectionParameters(string); - assert.equal(!!subject.ssl, false, 'ssl'); -}); - -//clear process.env -for(var key in process.env) { - delete process.env[key]; +// clear process.env +for (var key in process.env) { + delete process.env[key] } +test('connection string parsing', function (t) { + var string = 'postgres://brian:pw@boom:381/lala' + var subject = new ConnectionParameters(string) + assert.equal(subject.host, 'boom', 'string host') + assert.equal(subject.user, 'brian', 'string user') + assert.equal(subject.password, 'pw', 'string password') + assert.equal(subject.port, 381, 'string port') + assert.equal(subject.database, 'lala', 'string database') +}) + +test('connection string parsing - ssl', function (t) { + var string = 'postgres://brian:pw@boom:381/lala?ssl=true' + var subject = new ConnectionParameters(string) + assert.equal(subject.ssl, true, 'ssl') + + string = 'postgres://brian:pw@boom:381/lala?ssl=1' + subject = new ConnectionParameters(string) + assert.equal(subject.ssl, true, 'ssl') -test('ssl is false by default', function() { + string = 'postgres://brian:pw@boom:381/lala?other&ssl=true' + subject = new ConnectionParameters(string) + assert.equal(subject.ssl, true, 'ssl') + + string = 'postgres://brian:pw@boom:381/lala?ssl=0' + subject = new ConnectionParameters(string) + assert.equal(!!subject.ssl, false, 'ssl') + + string = 'postgres://brian:pw@boom:381/lala' + subject = new ConnectionParameters(string) + assert.equal(!!subject.ssl, false, 'ssl') +}) + +// clear process.env +for (var key in process.env) { + delete process.env[key] +} + +test('ssl is false by default', function () { var subject = new ConnectionParameters() assert.equal(subject.ssl, false) }) -var testVal = function(mode, expected) { - //clear process.env - for(var key in process.env) { - delete process.env[key]; +var testVal = function (mode, expected) { + // clear process.env + for (var key in process.env) { + delete process.env[key] } - process.env.PGSSLMODE = mode; - test('ssl is ' + expected + ' when $PGSSLMODE=' + mode, function() { - var subject = new ConnectionParameters(); - assert.equal(subject.ssl, expected); - }); -}; - -testVal('', false); -testVal('disable', false); -testVal('allow', false); -testVal('prefer', true); -testVal('require', true); -testVal('verify-ca', true); -testVal('verify-full', true); - - -//restore process.env -for(var key in realEnv) { - process.env[key] = realEnv[key]; + process.env.PGSSLMODE = mode + test('ssl is ' + expected + ' when $PGSSLMODE=' + mode, function () { + var subject = new ConnectionParameters() + assert.equal(subject.ssl, expected) + }) +} + +testVal('', false) +testVal('disable', false) +testVal('allow', false) +testVal('prefer', true) +testVal('require', true) +testVal('verify-ca', true) +testVal('verify-full', true) + +// restore process.env +for (var key in realEnv) { + process.env[key] = realEnv[key] } diff --git a/test/unit/connection/error-tests.js b/test/unit/connection/error-tests.js index 20952a693..19674608c 100644 --- a/test/unit/connection/error-tests.js +++ b/test/unit/connection/error-tests.js @@ -1,31 +1,31 @@ -"use strict"; -var helper = require(__dirname + '/test-helper'); -var Connection = require(__dirname + '/../../../lib/connection'); -test("connection emits stream errors", function() { - var con = new Connection({stream: new MemoryStream()}); - assert.emits(con, 'error', function(err) { - assert.equal(err.message, "OMG!"); - }); - con.connect(); - con.stream.emit('error', new Error("OMG!")); -}); +'use strict' +var helper = require(__dirname + '/test-helper') +var Connection = require(__dirname + '/../../../lib/connection') +test('connection emits stream errors', function () { + var con = new Connection({stream: new MemoryStream()}) + assert.emits(con, 'error', function (err) { + assert.equal(err.message, 'OMG!') + }) + con.connect() + con.stream.emit('error', new Error('OMG!')) +}) -test('connection emits ECONNRESET errors during normal operation', function() { - var con = new Connection({stream: new MemoryStream()}); - con.connect(); - assert.emits(con, 'error', function(err) { - assert.equal(err.code, 'ECONNRESET'); - }); - var e = new Error('Connection Reset'); - e.code = 'ECONNRESET'; - con.stream.emit('error', e); -}); +test('connection emits ECONNRESET errors during normal operation', function () { + var con = new Connection({stream: new MemoryStream()}) + con.connect() + assert.emits(con, 'error', function (err) { + assert.equal(err.code, 'ECONNRESET') + }) + var e = new Error('Connection Reset') + e.code = 'ECONNRESET' + con.stream.emit('error', e) +}) -test('connection does not emit ECONNRESET errors during disconnect', function() { - var con = new Connection({stream: new MemoryStream()}); - con.connect(); - var e = new Error('Connection Reset'); - e.code = 'ECONNRESET'; - con.end(); - con.stream.emit('error', e); -}); +test('connection does not emit ECONNRESET errors during disconnect', function () { + var con = new Connection({stream: new MemoryStream()}) + con.connect() + var e = new Error('Connection Reset') + e.code = 'ECONNRESET' + con.end() + con.stream.emit('error', e) +}) diff --git a/test/unit/connection/inbound-parser-tests.js b/test/unit/connection/inbound-parser-tests.js index 86266b22e..0eaefcc45 100644 --- a/test/unit/connection/inbound-parser-tests.js +++ b/test/unit/connection/inbound-parser-tests.js @@ -1,29 +1,29 @@ -"use strict"; -require(__dirname+'/test-helper'); -var Connection = require(__dirname + '/../../../lib/connection'); -var buffers = require(__dirname + '/../../test-buffers'); -var PARSE = function(buffer) { - return new Parser(buffer).parse(); -}; - -var authOkBuffer = buffers.authenticationOk(); -var paramStatusBuffer = buffers.parameterStatus('client_encoding', 'UTF8'); -var readyForQueryBuffer = buffers.readyForQuery(); -var backendKeyDataBuffer = buffers.backendKeyData(1,2); -var commandCompleteBuffer = buffers.commandComplete("SELECT 3"); -var parseCompleteBuffer = buffers.parseComplete(); -var bindCompleteBuffer = buffers.bindComplete(); -var portalSuspendedBuffer = buffers.portalSuspended(); - -var addRow = function(bufferList, name, offset) { - return bufferList.addCString(name) //field name - .addInt32(offset++) //table id - .addInt16(offset++) //attribute of column number - .addInt32(offset++) //objectId of field's data type - .addInt16(offset++) //datatype size - .addInt32(offset++) //type modifier - .addInt16(0) //format code, 0 => text -}; +'use strict' +require(__dirname + '/test-helper') +var Connection = require(__dirname + '/../../../lib/connection') +var buffers = require(__dirname + '/../../test-buffers') +var PARSE = function (buffer) { + return new Parser(buffer).parse() +} + +var authOkBuffer = buffers.authenticationOk() +var paramStatusBuffer = buffers.parameterStatus('client_encoding', 'UTF8') +var readyForQueryBuffer = buffers.readyForQuery() +var backendKeyDataBuffer = buffers.backendKeyData(1, 2) +var commandCompleteBuffer = buffers.commandComplete('SELECT 3') +var parseCompleteBuffer = buffers.parseComplete() +var bindCompleteBuffer = buffers.bindComplete() +var portalSuspendedBuffer = buffers.portalSuspended() + +var addRow = function (bufferList, name, offset) { + return bufferList.addCString(name) // field name + .addInt32(offset++) // table id + .addInt16(offset++) // attribute of column number + .addInt32(offset++) // objectId of field's data type + .addInt16(offset++) // datatype size + .addInt32(offset++) // type modifier + .addInt16(0) // format code, 0 => text +} var row1 = { name: 'id', @@ -33,11 +33,11 @@ var row1 = { dataTypeSize: 4, typeModifier: 5, formatCode: 0 -}; -var oneRowDescBuff = new buffers.rowDescription([row1]); -row1.name = 'bang'; +} +var oneRowDescBuff = new buffers.rowDescription([row1]) +row1.name = 'bang' -var twoRowBuf = new buffers.rowDescription([row1,{ +var twoRowBuf = new buffers.rowDescription([row1, { name: 'whoah', tableID: 10, attributeNumber: 11, @@ -47,144 +47,142 @@ var twoRowBuf = new buffers.rowDescription([row1,{ formatCode: 0 }]) - var emptyRowFieldBuf = new BufferList() .addInt16(0) - .join(true, 'D'); + .join(true, 'D') -var emptyRowFieldBuf = buffers.dataRow(); +var emptyRowFieldBuf = buffers.dataRow() var oneFieldBuf = new BufferList() - .addInt16(1) //number of fields - .addInt32(5) //length of bytes of fields + .addInt16(1) // number of fields + .addInt32(5) // length of bytes of fields .addCString('test') - .join(true, 'D'); - -var oneFieldBuf = buffers.dataRow(['test']); + .join(true, 'D') +var oneFieldBuf = buffers.dataRow(['test']) var expectedAuthenticationOkayMessage = { name: 'authenticationOk', length: 8 -}; +} var expectedParameterStatusMessage = { name: 'parameterStatus', parameterName: 'client_encoding', parameterValue: 'UTF8', length: 25 -}; +} var expectedBackendKeyDataMessage = { name: 'backendKeyData', processID: 1, secretKey: 2 -}; +} var expectedReadyForQueryMessage = { name: 'readyForQuery', length: 5, status: 'I' -}; +} var expectedCommandCompleteMessage = { length: 13, - text: "SELECT 3" -}; + text: 'SELECT 3' +} var emptyRowDescriptionBuffer = new BufferList() - .addInt16(0) //number of fields - .join(true,'T'); + .addInt16(0) // number of fields + .join(true, 'T') var expectedEmptyRowDescriptionMessage = { name: 'rowDescription', length: 6, fieldCount: 0 -}; +} var expectedOneRowMessage = { name: 'rowDescription', length: 27, fieldCount: 1 -}; +} var expectedTwoRowMessage = { name: 'rowDescription', length: 53, fieldCount: 2 -}; +} -var testForMessage = function(buffer, expectedMessage) { - var lastMessage = {}; - test('recieves and parses ' + expectedMessage.name, function() { - var stream = new MemoryStream(); +var testForMessage = function (buffer, expectedMessage) { + var lastMessage = {} + test('recieves and parses ' + expectedMessage.name, function () { + var stream = new MemoryStream() var client = new Connection({ stream: stream - }); - client.connect(); + }) + client.connect() - client.on('message',function(msg) { - lastMessage = msg; - }); + client.on('message', function (msg) { + lastMessage = msg + }) - client.on(expectedMessage.name, function() { - client.removeAllListeners(expectedMessage.name); - }); + client.on(expectedMessage.name, function () { + client.removeAllListeners(expectedMessage.name) + }) - stream.emit('data', buffer); - assert.same(lastMessage, expectedMessage); - }); - return lastMessage; -}; + stream.emit('data', buffer) + assert.same(lastMessage, expectedMessage) + }) + return lastMessage +} -var plainPasswordBuffer = buffers.authenticationCleartextPassword(); -var md5PasswordBuffer = buffers.authenticationMD5Password(); +var plainPasswordBuffer = buffers.authenticationCleartextPassword() +var md5PasswordBuffer = buffers.authenticationMD5Password() var expectedPlainPasswordMessage = { name: 'authenticationCleartextPassword' -}; +} var expectedMD5PasswordMessage = { name: 'authenticationMD5Password' -}; +} -var notificationResponseBuffer = buffers.notification(4, 'hi', 'boom'); +var notificationResponseBuffer = buffers.notification(4, 'hi', 'boom') var expectedNotificationResponseMessage = { name: 'notification', processId: 4, channel: 'hi', payload: 'boom' -}; - -test('Connection', function() { - testForMessage(authOkBuffer, expectedAuthenticationOkayMessage); - testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage); - var msg = testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage); - test('md5 has right salt', function() { - assert.equalBuffers(msg.salt, Buffer.from([1,2,3,4])); - }); - testForMessage(paramStatusBuffer, expectedParameterStatusMessage); - testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage); - testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage); - testForMessage(commandCompleteBuffer,expectedCommandCompleteMessage); - testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage); - test('empty row message', function() { - var message = testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage); - test('has no fields', function() { - assert.equal(message.fields.length, 0); - }); - }); - - test("no data message", function() { +} + +test('Connection', function () { + testForMessage(authOkBuffer, expectedAuthenticationOkayMessage) + testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage) + var msg = testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage) + test('md5 has right salt', function () { + assert.equalBuffers(msg.salt, Buffer.from([1, 2, 3, 4])) + }) + testForMessage(paramStatusBuffer, expectedParameterStatusMessage) + testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage) + testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage) + testForMessage(commandCompleteBuffer, expectedCommandCompleteMessage) + testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage) + test('empty row message', function () { + var message = testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage) + test('has no fields', function () { + assert.equal(message.fields.length, 0) + }) + }) + + test('no data message', function () { testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), { name: 'noData' - }); - }); - - test('one row message', function() { - var message = testForMessage(oneRowDescBuff, expectedOneRowMessage); - test('has one field', function() { - assert.equal(message.fields.length, 1); - }); - test('has correct field info', function() { + }) + }) + + test('one row message', function () { + var message = testForMessage(oneRowDescBuff, expectedOneRowMessage) + test('has one field', function () { + assert.equal(message.fields.length, 1) + }) + test('has correct field info', function () { assert.same(message.fields[0], { name: 'id', tableID: 1, @@ -193,16 +191,16 @@ test('Connection', function() { dataTypeSize: 4, dataTypeModifier: 5, format: 'text' - }); - }); - }); - - test('two row message', function() { - var message = testForMessage(twoRowBuf, expectedTwoRowMessage); - test('has two fields', function() { - assert.equal(message.fields.length, 2); - }); - test('has correct first field', function() { + }) + }) + }) + + test('two row message', function () { + var message = testForMessage(twoRowBuf, expectedTwoRowMessage) + test('has two fields', function () { + assert.equal(message.fields.length, 2) + }) + test('has correct first field', function () { assert.same(message.fields[0], { name: 'bang', tableID: 1, @@ -212,8 +210,8 @@ test('Connection', function() { dataTypeModifier: 5, format: 'text' }) - }); - test('has correct second field', function() { + }) + test('has correct second field', function () { assert.same(message.fields[1], { name: 'whoah', tableID: 10, @@ -222,98 +220,95 @@ test('Connection', function() { dataTypeSize: 13, dataTypeModifier: 14, format: 'text' - }); - }); - - }); - - test('parsing rows', function() { + }) + }) + }) - test('parsing empty row', function() { + test('parsing rows', function () { + test('parsing empty row', function () { var message = testForMessage(emptyRowFieldBuf, { name: 'dataRow', fieldCount: 0 - }); - test('has 0 fields', function() { - assert.equal(message.fields.length, 0); - }); - }); + }) + test('has 0 fields', function () { + assert.equal(message.fields.length, 0) + }) + }) - test('parsing data row with fields', function() { + test('parsing data row with fields', function () { var message = testForMessage(oneFieldBuf, { name: 'dataRow', fieldCount: 1 - }); - test('has 1 field', function() { - assert.equal(message.fields.length, 1); - }); - - test('field is correct', function() { - assert.equal(message.fields[0],'test'); - }); - }); + }) + test('has 1 field', function () { + assert.equal(message.fields.length, 1) + }) - }); + test('field is correct', function () { + assert.equal(message.fields[0], 'test') + }) + }) + }) - test('notice message', function() { - //this uses the same logic as error message - var buff = buffers.notice([{type: 'C', value: 'code'}]); + test('notice message', function () { + // this uses the same logic as error message + var buff = buffers.notice([{type: 'C', value: 'code'}]) testForMessage(buff, { name: 'notice', code: 'code' - }); - }); + }) + }) - test('error messages', function() { - test('with no fields', function() { - var msg = testForMessage(buffers.error(),{ + test('error messages', function () { + test('with no fields', function () { + var msg = testForMessage(buffers.error(), { name: 'error' - }); - }); + }) + }) - test('with all the fields', function() { + test('with all the fields', function () { var buffer = buffers.error([{ type: 'S', value: 'ERROR' - },{ + }, { type: 'C', value: 'code' - },{ + }, { type: 'M', value: 'message' - },{ + }, { type: 'D', value: 'details' - },{ + }, { type: 'H', value: 'hint' - },{ + }, { type: 'P', value: '100' - },{ + }, { type: 'p', value: '101' - },{ + }, { type: 'q', value: 'query' - },{ + }, { type: 'W', value: 'where' - },{ + }, { type: 'F', value: 'file' - },{ + }, { type: 'L', value: 'line' - },{ + }, { type: 'R', value: 'routine' - },{ - type: 'Z', //ignored + }, { + type: 'Z', // ignored value: 'alsdkf' - }]); + }]) - testForMessage(buffer,{ + testForMessage(buffer, { name: 'error', severity: 'ERROR', code: 'code', @@ -327,150 +322,148 @@ test('Connection', function() { file: 'file', line: 'line', routine: 'routine' - }); - }); - }); + }) + }) + }) - test('parses parse complete command', function() { + test('parses parse complete command', function () { testForMessage(parseCompleteBuffer, { name: 'parseComplete' - }); - }); + }) + }) - test('parses bind complete command', function() { + test('parses bind complete command', function () { testForMessage(bindCompleteBuffer, { name: 'bindComplete' - }); - }); + }) + }) - test('parses portal suspended message', function() { + test('parses portal suspended message', function () { testForMessage(portalSuspendedBuffer, { name: 'portalSuspended' - }); - }); + }) + }) - test('parses replication start message', function() { + test('parses replication start message', function () { testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { name: 'replicationStart', length: 4 - }); - }); -}); - -//since the data message on a stream can randomly divide the incomming -//tcp packets anywhere, we need to make sure we can parse every single -//split on a tcp message -test('split buffer, single message parsing', function() { - var fullBuffer = buffers.dataRow([null, "bang", "zug zug", null, "!"]); - var stream = new MemoryStream(); - stream.readyState = 'open'; + }) + }) +}) + +// since the data message on a stream can randomly divide the incomming +// tcp packets anywhere, we need to make sure we can parse every single +// split on a tcp message +test('split buffer, single message parsing', function () { + var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']) + var stream = new MemoryStream() + stream.readyState = 'open' var client = new Connection({ stream: stream - }); - client.connect(); - var message = null; - client.on('message', function(msg) { - message = msg; - }); - - test('parses when full buffer comes in', function() { - stream.emit('data', fullBuffer); - assert.lengthIs(message.fields, 5); - assert.equal(message.fields[0], null); - assert.equal(message.fields[1], "bang"); - assert.equal(message.fields[2], "zug zug"); - assert.equal(message.fields[3], null); - assert.equal(message.fields[4], "!"); - }); - - var testMessageRecievedAfterSpiltAt = function(split) { - var firstBuffer = Buffer.alloc(fullBuffer.length-split); - var secondBuffer = Buffer.alloc(fullBuffer.length-firstBuffer.length); - fullBuffer.copy(firstBuffer, 0, 0); - fullBuffer.copy(secondBuffer, 0, firstBuffer.length); - stream.emit('data', firstBuffer); - stream.emit('data', secondBuffer); - assert.lengthIs(message.fields, 5); - assert.equal(message.fields[0], null); - assert.equal(message.fields[1], "bang"); - assert.equal(message.fields[2], "zug zug"); - assert.equal(message.fields[3], null); - assert.equal(message.fields[4], "!"); - - }; - - test('parses when split in the middle', function() { - testMessageRecievedAfterSpiltAt(6); - }); - - test('parses when split at end', function() { - testMessageRecievedAfterSpiltAt(2); - }); - - test('parses when split at beginning', function() { - testMessageRecievedAfterSpiltAt(fullBuffer.length - 2); - testMessageRecievedAfterSpiltAt(fullBuffer.length - 1); - testMessageRecievedAfterSpiltAt(fullBuffer.length - 5); - }); -}); - -test('split buffer, multiple message parsing', function() { - var dataRowBuffer = buffers.dataRow(['!']); - var readyForQueryBuffer = buffers.readyForQuery(); - var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length); - dataRowBuffer.copy(fullBuffer, 0, 0); - readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0); - - var messages = []; - var stream = new MemoryStream(); + }) + client.connect() + var message = null + client.on('message', function (msg) { + message = msg + }) + + test('parses when full buffer comes in', function () { + stream.emit('data', fullBuffer) + assert.lengthIs(message.fields, 5) + assert.equal(message.fields[0], null) + assert.equal(message.fields[1], 'bang') + assert.equal(message.fields[2], 'zug zug') + assert.equal(message.fields[3], null) + assert.equal(message.fields[4], '!') + }) + + var testMessageRecievedAfterSpiltAt = function (split) { + var firstBuffer = Buffer.alloc(fullBuffer.length - split) + var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) + fullBuffer.copy(firstBuffer, 0, 0) + fullBuffer.copy(secondBuffer, 0, firstBuffer.length) + stream.emit('data', firstBuffer) + stream.emit('data', secondBuffer) + assert.lengthIs(message.fields, 5) + assert.equal(message.fields[0], null) + assert.equal(message.fields[1], 'bang') + assert.equal(message.fields[2], 'zug zug') + assert.equal(message.fields[3], null) + assert.equal(message.fields[4], '!') + } + + test('parses when split in the middle', function () { + testMessageRecievedAfterSpiltAt(6) + }) + + test('parses when split at end', function () { + testMessageRecievedAfterSpiltAt(2) + }) + + test('parses when split at beginning', function () { + testMessageRecievedAfterSpiltAt(fullBuffer.length - 2) + testMessageRecievedAfterSpiltAt(fullBuffer.length - 1) + testMessageRecievedAfterSpiltAt(fullBuffer.length - 5) + }) +}) + +test('split buffer, multiple message parsing', function () { + var dataRowBuffer = buffers.dataRow(['!']) + var readyForQueryBuffer = buffers.readyForQuery() + var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length) + dataRowBuffer.copy(fullBuffer, 0, 0) + readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0) + + var messages = [] + var stream = new MemoryStream() var client = new Connection({ stream: stream - }); - client.connect(); - client.on('message', function(msg) { - messages.push(msg); - }); - - - var verifyMessages = function() { - assert.lengthIs(messages, 2); - assert.same(messages[0],{ + }) + client.connect() + client.on('message', function (msg) { + messages.push(msg) + }) + + var verifyMessages = function () { + assert.lengthIs(messages, 2) + assert.same(messages[0], { name: 'dataRow', fieldCount: 1 - }); - assert.equal(messages[0].fields[0],'!'); - assert.same(messages[1],{ + }) + assert.equal(messages[0].fields[0], '!') + assert.same(messages[1], { name: 'readyForQuery' - }); - messages = []; - }; - //sanity check - test('recieves both messages when packet is not split', function() { - stream.emit('data', fullBuffer); - verifyMessages(); - }); - var splitAndVerifyTwoMessages = function(split) { - var firstBuffer = Buffer.alloc(fullBuffer.length-split); - var secondBuffer = Buffer.alloc(fullBuffer.length-firstBuffer.length); - fullBuffer.copy(firstBuffer, 0, 0); - fullBuffer.copy(secondBuffer, 0, firstBuffer.length); - stream.emit('data', firstBuffer); - stream.emit('data', secondBuffer); - }; - - test('recieves both messages when packet is split', function() { - test('in the middle', function() { - splitAndVerifyTwoMessages(11); - }); - test('at the front', function() { - splitAndVerifyTwoMessages(fullBuffer.length-1); - splitAndVerifyTwoMessages(fullBuffer.length-4); - splitAndVerifyTwoMessages(fullBuffer.length-6); - }); - - test('at the end', function() { - splitAndVerifyTwoMessages(8); - splitAndVerifyTwoMessages(1); - }); - }); -}); + }) + messages = [] + } + // sanity check + test('recieves both messages when packet is not split', function () { + stream.emit('data', fullBuffer) + verifyMessages() + }) + var splitAndVerifyTwoMessages = function (split) { + var firstBuffer = Buffer.alloc(fullBuffer.length - split) + var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) + fullBuffer.copy(firstBuffer, 0, 0) + fullBuffer.copy(secondBuffer, 0, firstBuffer.length) + stream.emit('data', firstBuffer) + stream.emit('data', secondBuffer) + } + + test('recieves both messages when packet is split', function () { + test('in the middle', function () { + splitAndVerifyTwoMessages(11) + }) + test('at the front', function () { + splitAndVerifyTwoMessages(fullBuffer.length - 1) + splitAndVerifyTwoMessages(fullBuffer.length - 4) + splitAndVerifyTwoMessages(fullBuffer.length - 6) + }) + + test('at the end', function () { + splitAndVerifyTwoMessages(8) + splitAndVerifyTwoMessages(1) + }) + }) +}) diff --git a/test/unit/connection/outbound-sending-tests.js b/test/unit/connection/outbound-sending-tests.js index 69642957d..e9e148c14 100644 --- a/test/unit/connection/outbound-sending-tests.js +++ b/test/unit/connection/outbound-sending-tests.js @@ -1,22 +1,22 @@ -"use strict"; -require(__dirname + "/test-helper"); -var Connection = require(__dirname + '/../../../lib/connection'); -var stream = new MemoryStream(); +'use strict' +require(__dirname + '/test-helper') +var Connection = require(__dirname + '/../../../lib/connection') +var stream = new MemoryStream() var con = new Connection({ stream: stream -}); +}) -assert.received = function(stream, buffer) { - assert.lengthIs(stream.packets, 1); - var packet = stream.packets.pop(); - assert.equalBuffers(packet, buffer); -}; +assert.received = function (stream, buffer) { + assert.lengthIs(stream.packets, 1) + var packet = stream.packets.pop() + assert.equalBuffers(packet, buffer) +} -test("sends startup message", function() { +test('sends startup message', function () { con.startup({ user: 'brian', database: 'bang' - }); + }) assert.received(stream, new BufferList() .addInt16(3) .addInt16(0) @@ -27,175 +27,174 @@ test("sends startup message", function() { .addCString('client_encoding') .addCString("'utf-8'") .addCString('').join(true)) -}); +}) -test('sends password message', function() { - con.password("!"); - assert.received(stream, new BufferList().addCString("!").join(true,'p')); -}); +test('sends password message', function () { + con.password('!') + assert.received(stream, new BufferList().addCString('!').join(true, 'p')) +}) -test('sends query message', function() { - var txt = 'select * from boom'; - con.query(txt); - assert.received(stream, new BufferList().addCString(txt).join(true,'Q')); -}); +test('sends query message', function () { + var txt = 'select * from boom' + con.query(txt) + assert.received(stream, new BufferList().addCString(txt).join(true, 'Q')) +}) -test('sends parse message', function() { - con.parse({text: '!'}); +test('sends parse message', function () { + con.parse({text: '!'}) var expected = new BufferList() - .addCString("") - .addCString("!") - .addInt16(0).join(true, 'P'); - assert.received(stream, expected); -}); + .addCString('') + .addCString('!') + .addInt16(0).join(true, 'P') + assert.received(stream, expected) +}) -test('sends parse message with named query', function() { +test('sends parse message with named query', function () { con.parse({ name: 'boom', text: 'select * from boom', types: [] - }); + }) var expected = new BufferList() - .addCString("boom") - .addCString("select * from boom") - .addInt16(0).join(true,'P'); - assert.received(stream, expected); + .addCString('boom') + .addCString('select * from boom') + .addInt16(0).join(true, 'P') + assert.received(stream, expected) - test('with multiple parameters', function() { + test('with multiple parameters', function () { con.parse({ name: 'force', text: 'select * from bang where name = $1', - types: [1, 2, 3 ,4] - }); + types: [1, 2, 3, 4] + }) var expected = new BufferList() - .addCString("force") - .addCString("select * from bang where name = $1") + .addCString('force') + .addCString('select * from bang where name = $1') .addInt16(4) .addInt32(1) .addInt32(2) .addInt32(3) - .addInt32(4).join(true,'P'); - assert.received(stream, expected); - }); -}); + .addInt32(4).join(true, 'P') + assert.received(stream, expected) + }) +}) -test('bind messages', function() { - test('with no values', function() { - con.bind(); +test('bind messages', function () { + test('with no values', function () { + con.bind() var expectedBuffer = new BufferList() - .addCString("") - .addCString("") + .addCString('') + .addCString('') .addInt16(0) .addInt16(0) .addInt16(0) - .join(true,"B"); - assert.received(stream, expectedBuffer); - }); + .join(true, 'B') + assert.received(stream, expectedBuffer) + }) - test('with named statement, portal, and values', function() { + test('with named statement, portal, and values', function () { con.bind({ portal: 'bang', statement: 'woo', values: ['1', 'hi', null, 'zing'] - }); + }) var expectedBuffer = new BufferList() - .addCString('bang') //portal name - .addCString('woo') //statement name + .addCString('bang') // portal name + .addCString('woo') // statement name .addInt16(0) .addInt16(4) .addInt32(1) - .add(Buffer.from("1")) + .add(Buffer.from('1')) .addInt32(2) - .add(Buffer.from("hi")) + .add(Buffer.from('hi')) .addInt32(-1) .addInt32(4) .add(Buffer.from('zing')) .addInt16(0) - .join(true, 'B'); - assert.received(stream, expectedBuffer); - }); -}); + .join(true, 'B') + assert.received(stream, expectedBuffer) + }) +}) -test('with named statement, portal, and buffer value', function() { +test('with named statement, portal, and buffer value', function () { con.bind({ portal: 'bang', statement: 'woo', values: ['1', 'hi', null, Buffer.from('zing', 'utf8')] - }); + }) var expectedBuffer = new BufferList() - .addCString('bang') //portal name - .addCString('woo') //statement name - .addInt16(4)//value count - .addInt16(0)//string - .addInt16(0)//string - .addInt16(0)//string - .addInt16(1)//binary + .addCString('bang') // portal name + .addCString('woo') // statement name + .addInt16(4)// value count + .addInt16(0)// string + .addInt16(0)// string + .addInt16(0)// string + .addInt16(1)// binary .addInt16(4) .addInt32(1) - .add(Buffer.from("1")) + .add(Buffer.from('1')) .addInt32(2) - .add(Buffer.from("hi")) + .add(Buffer.from('hi')) .addInt32(-1) .addInt32(4) .add(Buffer.from('zing', 'UTF-8')) .addInt16(0) - .join(true, 'B'); - assert.received(stream, expectedBuffer); -}); - -test("sends execute message", function() { + .join(true, 'B') + assert.received(stream, expectedBuffer) +}) - test("for unamed portal with no row limit", function() { - con.execute(); +test('sends execute message', function () { + test('for unamed portal with no row limit', function () { + con.execute() var expectedBuffer = new BufferList() .addCString('') .addInt32(0) - .join(true,'E'); - assert.received(stream, expectedBuffer); - }); + .join(true, 'E') + assert.received(stream, expectedBuffer) + }) - test("for named portal with row limit", function() { + test('for named portal with row limit', function () { con.execute({ portal: 'my favorite portal', rows: 100 - }); + }) var expectedBuffer = new BufferList() - .addCString("my favorite portal") + .addCString('my favorite portal') .addInt32(100) - .join(true, 'E'); - assert.received(stream, expectedBuffer); - }); -}); - -test('sends flush command', function() { - con.flush(); - var expected = new BufferList().join(true, 'H'); - assert.received(stream, expected); -}); - -test('sends sync command', function() { - con.sync(); - var expected = new BufferList().join(true,'S'); - assert.received(stream, expected); -}); - -test('sends end command', function() { - con.end(); - var expected = Buffer.from([0x58, 0, 0, 0, 4]); - assert.received(stream, expected); -}); - -test('sends describe command',function() { - test('describe statement', function() { - con.describe({type: 'S', name: 'bang'}); + .join(true, 'E') + assert.received(stream, expectedBuffer) + }) +}) + +test('sends flush command', function () { + con.flush() + var expected = new BufferList().join(true, 'H') + assert.received(stream, expected) +}) + +test('sends sync command', function () { + con.sync() + var expected = new BufferList().join(true, 'S') + assert.received(stream, expected) +}) + +test('sends end command', function () { + con.end() + var expected = Buffer.from([0x58, 0, 0, 0, 4]) + assert.received(stream, expected) +}) + +test('sends describe command', function () { + test('describe statement', function () { + con.describe({type: 'S', name: 'bang'}) var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D') - assert.received(stream, expected); - }); - - test("describe unnamed portal", function() { - con.describe({type: 'P'}); - var expected = new BufferList().addChar('P').addCString("").join(true, "D"); - assert.received(stream, expected); - }); -}); + assert.received(stream, expected) + }) + + test('describe unnamed portal', function () { + con.describe({type: 'P'}) + var expected = new BufferList().addChar('P').addCString('').join(true, 'D') + assert.received(stream, expected) + }) +}) diff --git a/test/unit/connection/startup-tests.js b/test/unit/connection/startup-tests.js index ee20d679a..dc793e697 100644 --- a/test/unit/connection/startup-tests.js +++ b/test/unit/connection/startup-tests.js @@ -1,88 +1,84 @@ -"use strict"; -require(__dirname+'/test-helper'); -var Connection = require(__dirname + '/../../../lib/connection'); -test('connection can take existing stream', function() { - var stream = new MemoryStream(); - var con = new Connection({stream: stream}); - assert.equal(con.stream, stream); -}); - -test('using closed stream', function() { - var makeStream = function() { - var stream = new MemoryStream(); - stream.readyState = 'closed'; - stream.connect = function(port, host) { - this.connectCalled = true; - this.port = port; - this.host = host; +'use strict' +require(__dirname + '/test-helper') +var Connection = require(__dirname + '/../../../lib/connection') +test('connection can take existing stream', function () { + var stream = new MemoryStream() + var con = new Connection({stream: stream}) + assert.equal(con.stream, stream) +}) + +test('using closed stream', function () { + var makeStream = function () { + var stream = new MemoryStream() + stream.readyState = 'closed' + stream.connect = function (port, host) { + this.connectCalled = true + this.port = port + this.host = host } - return stream; - }; - - var stream = makeStream(); + return stream + } - var con = new Connection({stream: stream}); + var stream = makeStream() - con.connect(1234, 'bang'); - - test('makes stream connect', function() { - assert.equal(stream.connectCalled, true); - }); + var con = new Connection({stream: stream}) - test('uses configured port', function() { - assert.equal(stream.port, 1234); - }); + con.connect(1234, 'bang') - test('uses configured host', function() { - assert.equal(stream.host, 'bang'); - }); + test('makes stream connect', function () { + assert.equal(stream.connectCalled, true) + }) - test('after stream connects client emits connected event', function() { + test('uses configured port', function () { + assert.equal(stream.port, 1234) + }) - var hit = false; + test('uses configured host', function () { + assert.equal(stream.host, 'bang') + }) - con.once('connect', function() { - hit = true; - }); + test('after stream connects client emits connected event', function () { + var hit = false - assert.ok(stream.emit('connect')); - assert.ok(hit); - - }); + con.once('connect', function () { + hit = true + }) - test('after stream emits connected event init TCP-keepalive', function() { + assert.ok(stream.emit('connect')) + assert.ok(hit) + }) - var stream = makeStream(); - var con = new Connection({ stream: stream, keepAlive: true }); - con.connect(123, 'test'); + test('after stream emits connected event init TCP-keepalive', function () { + var stream = makeStream() + var con = new Connection({ stream: stream, keepAlive: true }) + con.connect(123, 'test') - var res = false; + var res = false - stream.setKeepAlive = function(bit) { - res = bit; - }; + stream.setKeepAlive = function (bit) { + res = bit + } - assert.ok(stream.emit('connect')); - setTimeout(function() { - assert.equal(res, true); + assert.ok(stream.emit('connect')) + setTimeout(function () { + assert.equal(res, true) }) - }); -}); - -test('using opened stream', function() { - var stream = new MemoryStream(); - stream.readyState = 'open'; - stream.connect = function() { - assert.ok(false, "Should not call open"); - }; - var con = new Connection({stream: stream}); - test('does not call open', function() { - var hit = false; - con.once('connect', function() { - hit = true; - }); - con.connect(); - assert.ok(hit); - }); - -}); + }) +}) + +test('using opened stream', function () { + var stream = new MemoryStream() + stream.readyState = 'open' + stream.connect = function () { + assert.ok(false, 'Should not call open') + } + var con = new Connection({stream: stream}) + test('does not call open', function () { + var hit = false + con.once('connect', function () { + hit = true + }) + con.connect() + assert.ok(hit) + }) +}) diff --git a/test/unit/connection/test-helper.js b/test/unit/connection/test-helper.js index 03d95a699..bcb4b25ca 100644 --- a/test/unit/connection/test-helper.js +++ b/test/unit/connection/test-helper.js @@ -1,2 +1,2 @@ -"use strict"; -require(__dirname+'/../test-helper') +'use strict' +require(__dirname + '/../test-helper') diff --git a/test/unit/test-helper.js b/test/unit/test-helper.js index 1dcac733e..6cd2d24e0 100644 --- a/test/unit/test-helper.js +++ b/test/unit/test-helper.js @@ -1,37 +1,36 @@ -"use strict"; -var EventEmitter = require('events').EventEmitter; +'use strict' +var EventEmitter = require('events').EventEmitter -var helper = require('../test-helper'); -var Connection = require('../../lib/connection'); +var helper = require('../test-helper') +var Connection = require('../../lib/connection') -global.MemoryStream = function() { - EventEmitter.call(this); - this.packets = []; -}; +global.MemoryStream = function () { + EventEmitter.call(this) + this.packets = [] +} +helper.sys.inherits(MemoryStream, EventEmitter) -helper.sys.inherits(MemoryStream, EventEmitter); +var p = MemoryStream.prototype -var p = MemoryStream.prototype; +p.write = function (packet) { + this.packets.push(packet) +} -p.write = function(packet) { - this.packets.push(packet); -}; +p.setKeepAlive = function () {} -p.setKeepAlive = function(){}; +p.writable = true -p.writable = true; - -const createClient = function() { - var stream = new MemoryStream(); - stream.readyState = "open"; +const createClient = function () { + var stream = new MemoryStream() + stream.readyState = 'open' var client = new Client({ connection: new Connection({stream: stream}) - }); - client.connect(); - return client; -}; + }) + client.connect() + return client +} module.exports = Object.assign({}, helper, { - createClient: createClient, -}); + createClient: createClient +}) diff --git a/test/unit/utils-tests.js b/test/unit/utils-tests.js index 893cf5b5d..8898481a1 100644 --- a/test/unit/utils-tests.js +++ b/test/unit/utils-tests.js @@ -1,36 +1,33 @@ -"use strict"; -var helper = require('./test-helper'); -var utils = require("./../../lib/utils"); -var defaults = require("./../../lib").defaults; +'use strict' +var helper = require('./test-helper') +var utils = require('./../../lib/utils') +var defaults = require('./../../lib').defaults - -test('ensure types is exported on root object', function() { +test('ensure types is exported on root object', function () { var pg = require('../../lib') assert(pg.types) assert(pg.types.getTypeParser) assert(pg.types.setTypeParser) }) -//this tests the monkey patching -//to ensure comptability with older -//versions of node -test("EventEmitter.once", function(t) { - - //an event emitter - var stream = new MemoryStream(); - - var callCount = 0; - stream.once('single', function() { - callCount++; - }); - - stream.emit('single'); - stream.emit('single'); - assert.equal(callCount, 1); -}); - +// this tests the monkey patching +// to ensure comptability with older +// versions of node +test('EventEmitter.once', function (t) { + // an event emitter + var stream = new MemoryStream() + + var callCount = 0 + stream.once('single', function () { + callCount++ + }) + + stream.emit('single') + stream.emit('single') + assert.equal(callCount, 1) +}) -test('normalizing query configs', function() { +test('normalizing query configs', function () { var config var callback = function () {} @@ -50,147 +47,147 @@ test('normalizing query configs', function() { assert.deepEqual(config, {text: 'TEXT', values: [10], callback: callback}) }) -test('prepareValues: buffer prepared properly', function() { - var buf = Buffer.from("quack"); - var out = utils.prepareValue(buf); - assert.strictEqual(buf, out); -}); +test('prepareValues: buffer prepared properly', function () { + var buf = Buffer.from('quack') + var out = utils.prepareValue(buf) + assert.strictEqual(buf, out) +}) -test('prepareValues: date prepared properly', function() { - helper.setTimezoneOffset(-330); +test('prepareValues: date prepared properly', function () { + helper.setTimezoneOffset(-330) - var date = new Date(2014, 1, 1, 11, 11, 1, 7); - var out = utils.prepareValue(date); - assert.strictEqual(out, "2014-02-01T11:11:01.007+05:30"); + var date = new Date(2014, 1, 1, 11, 11, 1, 7) + var out = utils.prepareValue(date) + assert.strictEqual(out, '2014-02-01T11:11:01.007+05:30') - helper.resetTimezoneOffset(); -}); + helper.resetTimezoneOffset() +}) -test('prepareValues: date prepared properly as UTC', function() { - defaults.parseInputDatesAsUTC = true; +test('prepareValues: date prepared properly as UTC', function () { + defaults.parseInputDatesAsUTC = true // make a date in the local timezone that represents a specific UTC point in time - var date = new Date(Date.UTC(2014, 1, 1, 11, 11, 1, 7)); - var out = utils.prepareValue(date); - assert.strictEqual(out, "2014-02-01T11:11:01.007+00:00"); + var date = new Date(Date.UTC(2014, 1, 1, 11, 11, 1, 7)) + var out = utils.prepareValue(date) + assert.strictEqual(out, '2014-02-01T11:11:01.007+00:00') - defaults.parseInputDatesAsUTC = false; -}); + defaults.parseInputDatesAsUTC = false +}) -test('prepareValues: undefined prepared properly', function() { - var out = utils.prepareValue(void 0); - assert.strictEqual(out, null); -}); +test('prepareValues: undefined prepared properly', function () { + var out = utils.prepareValue(void 0) + assert.strictEqual(out, null) +}) -test('prepareValue: null prepared properly', function() { - var out = utils.prepareValue(null); - assert.strictEqual(out, null); -}); +test('prepareValue: null prepared properly', function () { + var out = utils.prepareValue(null) + assert.strictEqual(out, null) +}) -test('prepareValue: true prepared properly', function() { - var out = utils.prepareValue(true); - assert.strictEqual(out, 'true'); -}); +test('prepareValue: true prepared properly', function () { + var out = utils.prepareValue(true) + assert.strictEqual(out, 'true') +}) -test('prepareValue: false prepared properly', function() { - var out = utils.prepareValue(false); - assert.strictEqual(out, 'false'); -}); +test('prepareValue: false prepared properly', function () { + var out = utils.prepareValue(false) + assert.strictEqual(out, 'false') +}) test('prepareValue: number prepared properly', function () { - var out = utils.prepareValue(3.042); - assert.strictEqual(out, '3.042'); -}); + var out = utils.prepareValue(3.042) + assert.strictEqual(out, '3.042') +}) -test('prepareValue: string prepared properly', function() { - var out = utils.prepareValue('big bad wolf'); - assert.strictEqual(out, 'big bad wolf'); -}); +test('prepareValue: string prepared properly', function () { + var out = utils.prepareValue('big bad wolf') + assert.strictEqual(out, 'big bad wolf') +}) -test('prepareValue: simple array prepared properly', function() { - var out = utils.prepareValue([1, null, 3, undefined, [5, 6, "squ,awk"]]); - assert.strictEqual(out, '{"1",NULL,"3",NULL,{"5","6","squ,awk"}}'); -}); +test('prepareValue: simple array prepared properly', function () { + var out = utils.prepareValue([1, null, 3, undefined, [5, 6, 'squ,awk']]) + assert.strictEqual(out, '{"1",NULL,"3",NULL,{"5","6","squ,awk"}}') +}) -test('prepareValue: complex array prepared properly', function() { - var out = utils.prepareValue([{ x: 42 }, { y: 84 }]); - assert.strictEqual(out, '{"{\\"x\\":42}","{\\"y\\":84}"}'); -}); +test('prepareValue: complex array prepared properly', function () { + var out = utils.prepareValue([{ x: 42 }, { y: 84 }]) + assert.strictEqual(out, '{"{\\"x\\":42}","{\\"y\\":84}"}') +}) -test('prepareValue: date array prepared properly', function() { - helper.setTimezoneOffset(-330); +test('prepareValue: date array prepared properly', function () { + helper.setTimezoneOffset(-330) - var date = new Date(2014, 1, 1, 11, 11, 1, 7); - var out = utils.prepareValue([date]); - assert.strictEqual(out, '{"2014-02-01T11:11:01.007+05:30"}'); + var date = new Date(2014, 1, 1, 11, 11, 1, 7) + var out = utils.prepareValue([date]) + assert.strictEqual(out, '{"2014-02-01T11:11:01.007+05:30"}') - helper.resetTimezoneOffset(); -}); + helper.resetTimezoneOffset() +}) -test('prepareValue: arbitrary objects prepared properly', function() { - var out = utils.prepareValue({ x: 42 }); - assert.strictEqual(out, '{"x":42}'); -}); +test('prepareValue: arbitrary objects prepared properly', function () { + var out = utils.prepareValue({ x: 42 }) + assert.strictEqual(out, '{"x":42}') +}) -test('prepareValue: objects with simple toPostgres prepared properly', function() { +test('prepareValue: objects with simple toPostgres prepared properly', function () { var customType = { - toPostgres: function() { - return "zomgcustom!"; + toPostgres: function () { + return 'zomgcustom!' } - }; - var out = utils.prepareValue(customType); - assert.strictEqual(out, "zomgcustom!"); -}); + } + var out = utils.prepareValue(customType) + assert.strictEqual(out, 'zomgcustom!') +}) -test('prepareValue: objects with complex toPostgres prepared properly', function() { - var buf = Buffer.from("zomgcustom!"); +test('prepareValue: objects with complex toPostgres prepared properly', function () { + var buf = Buffer.from('zomgcustom!') var customType = { - toPostgres: function() { - return [1, 2]; + toPostgres: function () { + return [1, 2] } - }; - var out = utils.prepareValue(customType); - assert.strictEqual(out, '{"1","2"}'); -}); + } + var out = utils.prepareValue(customType) + assert.strictEqual(out, '{"1","2"}') +}) -test('prepareValue: objects with toPostgres receive prepareValue', function() { +test('prepareValue: objects with toPostgres receive prepareValue', function () { var customRange = { - lower: { toPostgres: function() { return 5; } }, - upper: { toPostgres: function() { return 10; } }, - toPostgres: function(prepare) { - return "[" + prepare(this.lower) + "," + prepare(this.upper) + "]"; + lower: { toPostgres: function () { return 5 } }, + upper: { toPostgres: function () { return 10 } }, + toPostgres: function (prepare) { + return '[' + prepare(this.lower) + ',' + prepare(this.upper) + ']' } - }; - var out = utils.prepareValue(customRange); - assert.strictEqual(out, "[5,10]"); -}); + } + var out = utils.prepareValue(customRange) + assert.strictEqual(out, '[5,10]') +}) -test('prepareValue: objects with circular toPostgres rejected', function() { - var buf = Buffer.from("zomgcustom!"); +test('prepareValue: objects with circular toPostgres rejected', function () { + var buf = Buffer.from('zomgcustom!') var customType = { - toPostgres: function() { - return { toPostgres: function () { return customType; } }; + toPostgres: function () { + return { toPostgres: function () { return customType } } } - }; + } - //can't use `assert.throws` since we need to distinguish circular reference - //errors from call stack exceeded errors + // can't use `assert.throws` since we need to distinguish circular reference + // errors from call stack exceeded errors try { - utils.prepareValue(customType); + utils.prepareValue(customType) } catch (e) { - assert.ok(e.message.match(/circular/), "Expected circular reference error but got " + e); - return; + assert.ok(e.message.match(/circular/), 'Expected circular reference error but got ' + e) + return } - throw new Error("Expected prepareValue to throw exception"); -}); + throw new Error('Expected prepareValue to throw exception') +}) -test('prepareValue: can safely be used to map an array of values including those with toPostgres functions', function() { +test('prepareValue: can safely be used to map an array of values including those with toPostgres functions', function () { var customType = { - toPostgres: function() { - return "zomgcustom!"; + toPostgres: function () { + return 'zomgcustom!' } - }; - var values = [1, "test", customType] + } + var values = [1, 'test', customType] var out = values.map(utils.prepareValue) - assert.deepEqual(out, [1, "test", "zomgcustom!"]) + assert.deepEqual(out, [1, 'test', 'zomgcustom!']) }) From 28b330c88ebac2ea3ad565f8f2ce4ebe5c9a5579 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 15 Jul 2017 17:22:21 -0500 Subject: [PATCH 0267/1037] Add JS driver support for multiple results --- lib/query.js | 25 ++++++- .../client/multiple-results-tests.js | 69 +++++++++++++++++++ 2 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 test/integration/client/multiple-results-tests.js diff --git a/lib/query.js b/lib/query.js index 89bde080b..4d483ac7a 100644 --- a/lib/query.js +++ b/lib/query.js @@ -29,10 +29,14 @@ var Query = function (config, values, callback) { // use unique portal name each time this.portal = config.portal || '' this.callback = config.callback + this._rowMode = config.rowMode if (process.domain && config.callback) { this.callback = process.domain.bind(config.callback) } - this._result = new Result(config.rowMode, config.types) + this._result = new Result(this._rowMode, this.types) + + // potential for multiple results + this._results = this._result this.isPreparedStatement = false this._canceledDueToError = false this._promise = null @@ -54,10 +58,24 @@ Query.prototype.requiresPreparation = function () { return this.values.length > 0 } +Query.prototype._checkForMultirow = function () { + // if we already have a result with a command property + // then we've already executed one query in a multi-statement simple query + // turn our results into an array of results + if (this._result.command) { + if (!Array.isArray(this._results)) { + this._results = [this._result] + } + this._result = new Result(this._rowMode, this.types) + this._results.push(this._result) + } +} + // associates row metadata from the supplied // message with this query object // metadata used when parsing row results Query.prototype.handleRowDescription = function (msg) { + this._checkForMultirow() this._result.addFields(msg.fields) this._accumulateRows = this.callback || !this.listeners('row').length } @@ -83,6 +101,7 @@ Query.prototype.handleDataRow = function (msg) { } Query.prototype.handleCommandComplete = function (msg, con) { + this._checkForMultirow() this._result.addCommandComplete(msg) // need to sync after each command complete of a prepared statement if (this.isPreparedStatement) { @@ -104,9 +123,9 @@ Query.prototype.handleReadyForQuery = function (con) { return this.handleError(this._canceledDueToError, con) } if (this.callback) { - this.callback(null, this._result) + this.callback(null, this._results) } - this.emit('end', this._result) + this.emit('end', this._results) } Query.prototype.handleError = function (err, connection) { diff --git a/test/integration/client/multiple-results-tests.js b/test/integration/client/multiple-results-tests.js new file mode 100644 index 000000000..01dd9eaed --- /dev/null +++ b/test/integration/client/multiple-results-tests.js @@ -0,0 +1,69 @@ +'use strict' +const assert = require('assert') +const co = require('co') + +const helper = require('./test-helper') + +const suite = new helper.Suite('multiple result sets') + +suite.test('two select results work', co.wrap(function * () { + const client = new helper.Client() + yield client.connect() + + const results = yield client.query(`SELECT 'foo'::text as name; SELECT 'bar'::text as baz`) + assert(Array.isArray(results)) + + assert.equal(results[0].fields[0].name, 'name') + assert.deepEqual(results[0].rows, [{ name: 'foo' }]) + + assert.equal(results[1].fields[0].name, 'baz') + assert.deepEqual(results[1].rows, [{ baz: 'bar' }]) + + return client.end() +})) + +suite.test('multiple selects work', co.wrap(function * () { + const client = new helper.Client() + yield client.connect() + + const text = ` + SELECT * FROM generate_series(2, 4) as foo; + SELECT * FROM generate_series(8, 10) as bar; + SELECT * FROM generate_series(20, 22) as baz; + ` + + const results = yield client.query(text) + assert(Array.isArray(results)) + + assert.equal(results[0].fields[0].name, 'foo') + assert.deepEqual(results[0].rows, [{ foo: 2 }, { foo: 3 }, { foo: 4 }]) + + assert.equal(results[1].fields[0].name, 'bar') + assert.deepEqual(results[1].rows, [{ bar: 8 }, { bar: 9 }, { bar: 10 }]) + + assert.equal(results[2].fields[0].name, 'baz') + assert.deepEqual(results[2].rows, [{ baz: 20 }, { baz: 21 }, { baz: 22 }]) + + assert.equal(results.length, 3) + + return client.end() +})) + +suite.test('mixed queries and statements', co.wrap(function * () { + const client = new helper.Client() + yield client.connect() + + const text = ` + CREATE TEMP TABLE weather(type text); + INSERT INTO weather(type) VALUES ('rain'); + SELECT * FROM weather; + ` + + const results = yield client.query(text) + assert(Array.isArray(results)) + assert.equal(results[0].command, 'CREATE') + assert.equal(results[1].command, 'INSERT') + assert.equal(results[2].command, 'SELECT') + + return client.end() +})) From ac3102eea2e4b9f31e628cdd0a68d83ec2765724 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 16 Jul 2017 14:58:54 -0500 Subject: [PATCH 0268/1037] Add support for pg-native multi-row result --- lib/native/query.js | 24 +++++++++++-------- .../row-description-on-results-tests.js | 2 ++ test/integration/client/simple-query-tests.js | 11 +++++---- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/lib/native/query.js b/lib/native/query.js index c1a769154..576495aca 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -91,7 +91,7 @@ NativeQuery.prototype.submit = function (client) { this.native = client.native client.native.arrayMode = this._arrayMode - var after = function (err, rows) { + var after = function (err, rows, results) { client.native.arrayMode = false setImmediate(function () { self.emit('_done') @@ -102,22 +102,26 @@ NativeQuery.prototype.submit = function (client) { return self.handleError(err) } - var result = new NativeResult() - result.addCommandComplete(self.native.pq) - result.rows = rows - // emit row events for each row in the result if (self._emitRowEvents) { - rows.forEach(function (row) { - self.emit('row', row, result) - }) + if (results.length > 1) { + rows.forEach((rowOfRows, i) => { + rowOfRows.forEach(row => { + self.emit('row', row, results[i]) + }) + }) + } else { + rows.forEach(function (row) { + self.emit('row', row, results) + }) + } } // handle successful result self.state = 'end' - self.emit('end', result) + self.emit('end', results) if (self.callback) { - self.callback(null, result) + self.callback(null, results) } } diff --git a/test/integration/client/row-description-on-results-tests.js b/test/integration/client/row-description-on-results-tests.js index 108e51977..babf69128 100644 --- a/test/integration/client/row-description-on-results-tests.js +++ b/test/integration/client/row-description-on-results-tests.js @@ -7,6 +7,8 @@ var conInfo = helper.config var checkResult = function (result) { assert(result.fields) + console.log('YOU ARE HERE') + console.log('result!!', result) assert.equal(result.fields.length, 3) var fields = result.fields assert.equal(fields[0].name, 'now') diff --git a/test/integration/client/simple-query-tests.js b/test/integration/client/simple-query-tests.js index e46958f2d..d7f1916a5 100644 --- a/test/integration/client/simple-query-tests.js +++ b/test/integration/client/simple-query-tests.js @@ -49,16 +49,17 @@ test('prepared statements do not mutate params', function () { client.on('drain', client.end.bind(client)) + const rows = [] query.on('row', function (row, result) { assert.ok(result) - result.addRow(row) + rows.push(row) }) query.on('end', function (result) { - assert.lengthIs(result.rows, 26, 'result returned wrong number of rows') - assert.lengthIs(result.rows, result.rowCount) - assert.equal(result.rows[0].name, 'Aaron') - assert.equal(result.rows[25].name, 'Zanzabar') + assert.lengthIs(rows, 26, 'result returned wrong number of rows') + assert.lengthIs(rows, result.rowCount) + assert.equal(rows[0].name, 'Aaron') + assert.equal(rows[25].name, 'Zanzabar') }) }) From 111e08d0d77c30f9f0b8df4319df9aac47447aa5 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 16 Jul 2017 15:59:18 -0500 Subject: [PATCH 0269/1037] Cleanup --- lib/native/query.js | 1 - lib/native/result.js | 37 ------------------- package.json | 2 +- .../row-description-on-results-tests.js | 2 - 4 files changed, 1 insertion(+), 41 deletions(-) delete mode 100644 lib/native/result.js diff --git a/lib/native/query.js b/lib/native/query.js index 576495aca..dbcd56041 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -10,7 +10,6 @@ var EventEmitter = require('events').EventEmitter var util = require('util') var utils = require('../utils') -var NativeResult = require('./result') var NativeQuery = module.exports = function (config, values, callback) { EventEmitter.call(this) diff --git a/lib/native/result.js b/lib/native/result.js deleted file mode 100644 index ae9a97a1e..000000000 --- a/lib/native/result.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict' -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ - -var NativeResult = module.exports = function (pq) { - this.command = null - this.rowCount = 0 - this.rows = null - this.fields = null -} - -NativeResult.prototype.addCommandComplete = function (pq) { - this.command = pq.cmdStatus().split(' ')[0] - this.rowCount = parseInt(pq.cmdTuples(), 10) - var nfields = pq.nfields() - if (nfields < 1) return - - this.fields = [] - for (var i = 0; i < nfields; i++) { - this.fields.push({ - name: pq.fname(i), - dataTypeID: pq.ftype(i) - }) - } -} - -NativeResult.prototype.addRow = function (row) { - // This is empty to ensure pg code doesn't break when switching to pg-native - // pg-native loads all rows into the final result object by default. - // This is because libpg loads all rows into memory before passing the result - // to pg-native. -} diff --git a/package.json b/package.json index 070689726..7bfc3a980 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "eslint-plugin-standard": "3.0.1", "pg-copy-streams": "0.3.0" }, - "minNativeVersion": "1.7.0", + "minNativeVersion": "2.0", "scripts": { "test": "make test-all" }, diff --git a/test/integration/client/row-description-on-results-tests.js b/test/integration/client/row-description-on-results-tests.js index babf69128..108e51977 100644 --- a/test/integration/client/row-description-on-results-tests.js +++ b/test/integration/client/row-description-on-results-tests.js @@ -7,8 +7,6 @@ var conInfo = helper.config var checkResult = function (result) { assert(result.fields) - console.log('YOU ARE HERE') - console.log('result!!', result) assert.equal(result.fields.length, 3) var fields = result.fields assert.equal(fields[0].name, 'now') From f37acc4a6e227ee468bc7a07c1c5967838029a35 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 16 Jul 2017 16:02:15 -0500 Subject: [PATCH 0270/1037] Use valid semver in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7bfc3a980..9935b9cda 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "eslint-plugin-standard": "3.0.1", "pg-copy-streams": "0.3.0" }, - "minNativeVersion": "2.0", + "minNativeVersion": "2.0.0", "scripts": { "test": "make test-all" }, From f9390dab6b623cf305492920ffd799682b00ba08 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 16 Jul 2017 16:35:32 -0500 Subject: [PATCH 0271/1037] Re-implement changes from conflict --- lib/client.js | 4 ++-- lib/connection.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/client.js b/lib/client.js index d0052604e..107377c7b 100644 --- a/lib/client.js +++ b/lib/client.js @@ -40,11 +40,11 @@ var Client = function (config) { this.connection = c.connection || new Connection({ stream: c.stream, ssl: this.connectionParameters.ssl, - keepAlive: c.keepAlive || false + keepAlive: c.keepAlive || false, + encoding: this.connectionParameters.client_encoding || 'utf8' }) this.queryQueue = [] this.binary = c.binary || defaults.binary - this.encoding = 'utf8' this.processID = null this.secretKey = null this.ssl = this.connectionParameters.ssl || false diff --git a/lib/connection.js b/lib/connection.js index 2f13803e4..0f98cb062 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -25,7 +25,7 @@ var Connection = function (config) { this.lastOffset = 0 this.buffer = null this.offset = null - this.encoding = 'utf8' + this.encoding = config.encoding || 'utf8' this.parsedStatements = {} this.writer = new Writer() this.ssl = config.ssl || false From ca4ac9983aab7844ed5f068b8900052e1cd09652 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 16 Jul 2017 16:39:22 -0500 Subject: [PATCH 0272/1037] Re-implement other patch --- lib/utils.js | 14 ++++++++------ test/unit/utils-tests.js | 7 +++++++ 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index a83cdee9d..166cbddc6 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -32,6 +32,8 @@ function arrayString (val) { result = result + 'NULL' } else if (Array.isArray(val[i])) { result = result + arrayString(val[i]) + } else if (val[i] instanceof Buffer) { + result += '\\\\x' + val[i].toString('hex') } else { result += escapeElement(prepareValue(val[i])) } @@ -106,12 +108,12 @@ function dateToString (date) { function dateToStringUTC (date) { var ret = pad(date.getUTCFullYear(), 4) + '-' + - pad(date.getUTCMonth() + 1, 2) + '-' + - pad(date.getUTCDate(), 2) + 'T' + - pad(date.getUTCHours(), 2) + ':' + - pad(date.getUTCMinutes(), 2) + ':' + - pad(date.getUTCSeconds(), 2) + '.' + - pad(date.getUTCMilliseconds(), 3) + pad(date.getUTCMonth() + 1, 2) + '-' + + pad(date.getUTCDate(), 2) + 'T' + + pad(date.getUTCHours(), 2) + ':' + + pad(date.getUTCMinutes(), 2) + ':' + + pad(date.getUTCSeconds(), 2) + '.' + + pad(date.getUTCMilliseconds(), 3) return ret + '+00:00' } diff --git a/test/unit/utils-tests.js b/test/unit/utils-tests.js index 8898481a1..680b9fb50 100644 --- a/test/unit/utils-tests.js +++ b/test/unit/utils-tests.js @@ -139,6 +139,13 @@ test('prepareValue: objects with simple toPostgres prepared properly', function assert.strictEqual(out, 'zomgcustom!') }) +test('prepareValue: buffer array prepared properly', function() { + var buffer1 = Buffer.from('dead', 'hex') + var buffer2 = Buffer.from('beef', 'hex') + var out = utils.prepareValue([buffer1, buffer2]) + assert.strictEqual(out, '{\\\\xdead,\\\\xbeef}') + }) + test('prepareValue: objects with complex toPostgres prepared properly', function () { var buf = Buffer.from('zomgcustom!') var customType = { From 8a1da112e8bf6bfb1f6f184bc35417f014eab673 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 17 Jul 2017 22:07:58 -0500 Subject: [PATCH 0273/1037] Update changelog --- CHANGELOG.md | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56b294133..3bb1cf726 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,26 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.0.0 + +#### Breaking Changes + +- Drop support for node < `4.x`. +- Remove `pg.connect` `pg.end` and `pg.cancel` singleton methods. +- `Client#connect(callback)` now returns `undefined`. It used to return an event emitter. +- Upgrade [pg-pool](https://github.com/brianc/node-pg-pool) to `2.x`. +- Upgrade [pg-native](https://github.com/brianc/node-pg-native) to `2.x`. +- Standardize error message fields between JS and native driver. The only breaking changes were in the native driver as its field names were brought into alignment with the existing JS driver field names. +- Result from multi-statement text queries such as `SELECT 1; SELECT 2;` are now returned as an array of results instead of a single result with 1 array containing rows from both queries. + +[Please see here for a migration guide](https://node-postgres.com/guides/upgrading) + +#### Enhancements + +- Overhauled documentation: [https://node-postgres.com](https://node-postgres.com). +- Add `Client#connect() => Promise` and `Client#end() => Promise` calls. Promises are now returned from all async methods on clients _if and only if_ no callback was supplied to the method. +- Add `connectionTimeoutMillis` to pg-pool. + ### v6.2.0 - Add support for [parsing `replicationStart` messages](https://github.com/brianc/node-postgres/pull/1271/files). @@ -204,7 +224,7 @@ decimal | string | number (float) ``` For more information see https://github.com/brianc/node-postgres/pull/353 -If you are unhappy with these changes you can always [override the built in type parsing fairly easily](https://github.com/brianc/node-pg-parse-float). +If you are unhappy with these changes you can always [override the built in type parsing fairly easily](https://github.com/brianc/node-pg-parse-float). ### v1.3.0 From cbbd8d45a7779c4e59099d46d4e7c339327251da Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 17 Jul 2017 22:08:31 -0500 Subject: [PATCH 0274/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9935b9cda..5a1405038 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "6.2.4", + "version": "7.0.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 0c24ff3c12a2e1b2dd6d16a8192c64fd34dcd1e7 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 17 Jul 2017 22:24:06 -0500 Subject: [PATCH 0275/1037] Update readme --- README.md | 228 +++++------------------------------------------------- 1 file changed, 18 insertions(+), 210 deletions(-) diff --git a/README.md b/README.md index 679b5796d..aad42ce70 100644 --- a/README.md +++ b/README.md @@ -13,193 +13,9 @@ Non-blocking PostgreSQL client for node.js. Pure JavaScript and optional native $ npm install pg ``` -## Intro & Examples +## [Documentation](https://node-postgres.com) -There are 3 ways of executing queries - -1. Passing the query to a pool -2. Borrowing a client from a pool and executing the query with it -3. Obtaining an exclusive client and executing the query with it - -It is recommended to pass the query to a pool as often as possible. If that isn't possible, because of long and complex transactions for example, borrow a client from a pool. Just remember to initialize the pool only once in your code so you maximize reusability of connections. - -### Why pooling? - -If you're working on something like a web application which makes frequent queries you'll want to access the PostgreSQL server through a pool of clients. Why? For one thing, there is ~20-30 millisecond delay (YMMV) when connecting a new client to the PostgreSQL server because of the startup handshake. Furthermore, PostgreSQL can support only a limited number of clients...it depends on the amount of ram on your database server, but generally more than 100 clients at a time is a __very bad thing__. :tm: Additionally, PostgreSQL can only execute 1 query at a time per connected client, so pipelining all queries for all requests through a single, long-lived client will likely introduce a bottleneck into your application if you need high concurrency. - -With that in mind we can imagine a situation where you have a web server which connects and disconnects a new client for every web request or every query (don't do this!). If you get only 1 request at a time everything will seem to work fine, though it will be a touch slower due to the connection overhead. Once you get >100 simultaneous requests your web server will attempt to open 100 connections to the PostgreSQL backend and :boom: you'll run out of memory on the PostgreSQL server, your database will become unresponsive, your app will seem to hang, and everything will break. Boooo! - -__Good news__: node-postgres ships with built in client pooling. Client pooling allows your application to use a pool of already connected clients and reuse them for each request to your application. If your app needs to make more queries than there are available clients in the pool the queries will queue instead of overwhelming your database & causing a cascading failure. :thumbsup: - -node-postgres uses [pg-pool](https://github.com/brianc/node-pg-pool.git) to manage pooling. It bundles it and exports it for convenience. If you want, you can `require('pg-pool')` and use it directly - it's the same as the constructor exported at `pg.Pool`. - -It's __highly recommended__ you read the documentation for [pg-pool](https://github.com/brianc/node-pg-pool.git). - -[Here is an up & running quickly example](https://github.com/brianc/node-postgres/wiki/Example) - -For more information about `config.ssl` check [TLS (SSL) of nodejs](https://nodejs.org/dist/latest-v4.x/docs/api/tls.html) - -### Pooling example - -Let's create a pool in `./lib/db.js` which will be reused across the whole project - -```javascript -const pg = require('pg'); - -// create a config to configure both pooling behavior -// and client options -// note: all config is optional and the environment variables -// will be read if the config is not present -var config = { - user: 'foo', //env var: PGUSER - database: 'my_db', //env var: PGDATABASE - password: 'secret', //env var: PGPASSWORD - host: 'localhost', // Server hosting the postgres database - port: 5432, //env var: PGPORT - max: 10, // max number of clients in the pool - idleTimeoutMillis: 30000, // how long a client is allowed to remain idle before being closed -}; - -//this initializes a connection pool -//it will keep idle connections open for 30 seconds -//and set a limit of maximum 10 idle clients -const pool = new pg.Pool(config); - -pool.on('error', function (err, client) { - // if an error is encountered by a client while it sits idle in the pool - // the pool itself will emit an error event with both the error and - // the client which emitted the original error - // this is a rare occurrence but can happen if there is a network partition - // between your application and the database, the database restarts, etc. - // and so you might want to handle it and at least log it out - console.error('idle client error', err.message, err.stack); -}); - -//export the query method for passing queries to the pool -module.exports.query = function (text, values, callback) { - console.log('query:', text, values); - return pool.query(text, values, callback); -}; - -// the pool also supports checking out a client for -// multiple operations, such as a transaction -module.exports.connect = function (callback) { - return pool.connect(callback); -}; -``` - -Now if in `./foo.js` you want to pass a query to the pool - -```js -const pool = require('./lib/db'); - -//to run a query we just pass it to the pool -//after we're done nothing has to be taken care of -//we don't have to return any client to the pool or close a connection -pool.query('SELECT $1::int AS number', ['2'], function(err, res) { - if(err) { - return console.error('error running query', err); - } - - console.log('number:', res.rows[0].number); -}); -``` - -Or if in `./bar.js` you want borrow a client from the pool - -```js -const pool = require('./lib/db'); - -//ask for a client from the pool -pool.connect(function(err, client, done) { - if(err) { - return console.error('error fetching client from pool', err); - } - - //use the client for executing the query - client.query('SELECT $1::int AS number', ['1'], function(err, result) { - //call `done(err)` to release the client back to the pool (or destroy it if there is an error) - done(err); - - if(err) { - return console.error('error running query', err); - } - console.log(result.rows[0].number); - //output: 1 - }); -}); -``` - -For more examples, including how to use a connection pool with promises and async/await see the [example](https://github.com/brianc/node-postgres/wiki/Example) page in the wiki. - -### Obtaining an exclusive client, example - -```js -var pg = require('pg'); - -// instantiate a new client -// the client will read connection information from -// the same environment variables used by postgres cli tools -var client = new pg.Client(); - -// connect to our database -client.connect(function (err) { - if (err) throw err; - - // execute a query on our database - client.query('SELECT $1::text as name', ['brianc'], function (err, result) { - if (err) throw err; - - // just print the result to the console - console.log(result.rows[0]); // outputs: { name: 'brianc' } - - // disconnect the client - client.end(function (err) { - if (err) throw err; - }); - }); -}); - -``` - -## [More Documentation](https://github.com/brianc/node-postgres/wiki) - -## Native Bindings - -To install the [native bindings](https://github.com/brianc/node-pg-native.git): - -```sh -$ npm install pg pg-native -``` - - -node-postgres contains a pure JavaScript protocol implementation which is quite fast, but you can optionally use [native](https://github.com/brianc/node-pg-native) [bindings](https://github.com/brianc/node-libpq) for a 20-30% increase in parsing speed (YMMV). Both versions are adequate for production workloads. I personally use the pure JavaScript implementation because I like knowing what's going on all the way down to the binary on the socket, and it allows for some fancier [use](https://github.com/brianc/node-pg-cursor) [cases](https://github.com/brianc/node-pg-query-stream) which are difficult to do with libpq. :smile: - -To use the native bindings, first install [pg-native](https://github.com/brianc/node-pg-native.git). Once pg-native is installed, simply replace `var pg = require('pg')` with `var pg = require('pg').native`. Make sure any exported constructors from `pg` are from the native instance. Example: - -```js -var pg = require('pg').native -var Pool = require('pg').Pool // bad! this is not bound to the native client -var Client = require('pg').Client // bad! this is the pure JavaScript client - -var pg = require('pg').native -var Pool = pg.Pool // good! a pool bound to the native client -var Client = pg.Client // good! this client uses libpq bindings -``` - -#### API differences - -node-postgres abstracts over the pg-native module to provide the same interface as the pure JavaScript version. Care has been taken to keep the number of api differences between the two modules to a minimum. -However, currently some differences remain, especially : -* the error object in pg-native is different : notably, the information about the postgres error code is not present in field `code` but in the field `sqlState` , and the name of a few other fields is different (see https://github.com/brianc/node-postgres/issues/938, https://github.com/brianc/node-postgres/issues/972). -So for example, if you rely on error.code in your application, your will have to adapt your code to work with native bindings. -* the notification object has a few less properties (see https://github.com/brianc/node-postgres/issues/1045) -* column objects have less properties (see https://github.com/brianc/node-postgres/issues/988) -* the modules https://github.com/brianc/node-pg-copy-streams and https://github.com/brianc/node-pg-query-stream do not work with native bindings (you will have to require 'pg' to use them). - -Thus, it is recommended you use either the pure JavaScript or native bindings in both development and production and don't mix & match them in the same process - it can get confusing! - -## Features +### Features * pure JavaScript client and native libpq bindings share _the same api_ * connection pooling @@ -210,47 +26,39 @@ Thus, it is recommended you use either the pure JavaScript or native bindings in * async notifications with `LISTEN/NOTIFY` * bulk import & export with `COPY TO/COPY FROM` -## Extras +### Extras node-postgres is by design pretty light on abstractions. These are some handy modules we've been using over the years to complete the picture. Entire list can be found on [wiki](https://github.com/brianc/node-postgres/wiki/Extras) +## Support + +node-postgres is free software. If you encounter a bug with the library please open an issue on the [github repo](https://github.com/brianc/node-postgres). If you have questions unanswered by the documentation please open an issue pointing out how the documentation was unclear & I will do my best to make it better! + +When you open an issue please provide: +- version of node +- version of postgres +- smallest possible snippet of code to reproduce the problem + +You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on twitter. + +### Professional Support + +I offer professional support for node-postgres. I provide implementation, training, and many years of expertise on how to build applications with node, express, PostgreSQL, and react/redux. Please contact me at [brian.m.carlson@gmail.com](mailto:brian.m.carlson@gmail.com) to discuss how I can help your company be more successful! + ## Contributing __:heart: contributions!__ -If you need help getting the tests running locally or have any questions about the code when working on a patch please feel free to email me or gchat me. - I will __happily__ accept your pull request if it: - __has tests__ - looks reasonable - does not break backwards compatibility -Information about the testing processes is in the [wiki](https://github.com/brianc/node-postgres/wiki/Testing). - -Open source belongs to all of us, and we're all invited to participate! - ## Troubleshooting and FAQ The causes and solutions to common errors can be found among the [Frequently Asked Questions(FAQ)](https://github.com/brianc/node-postgres/wiki/FAQ) -## Support - -If at all possible when you open an issue please provide -- version of node -- version of postgres -- smallest possible snippet of code to reproduce the problem - -Usually I'll pop the code into the repo as a test. Hopefully the test fails. Then I make the test pass. Then everyone's happy! - -If you need help or run into _any_ issues getting node-postgres to work on your system please report a bug or contact me directly. I am usually available via google-talk at my github account public email address. Remember this is a labor of love, and though I try to get back to everything sometimes life takes priority, and I might take a while. It helps if you use nice code formatting in your issue, search for existing answers before posting, and come back and close out the issue if you figure out a solution. The easier you can make it for me, the quicker I'll try and respond to you! - -If you need deeper support, have application specific questions, would like to sponsor development, or want consulting around node & postgres please send me an email, I'm always happy to discuss! - -I usually tweet about any important status updates or changes to node-postgres on twitter. -Follow me [@briancarlson](https://twitter.com/briancarlson) to keep up to date. - - ## License Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) From 14153f274f3bea1063c3d74fd160e238b39b0702 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 17 Jul 2017 22:27:12 -0500 Subject: [PATCH 0276/1037] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index aad42ce70..be50cc2ab 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,9 @@ Non-blocking PostgreSQL client for node.js. Pure JavaScript and optional native $ npm install pg ``` -## [Documentation](https://node-postgres.com) +--- +## :star: [Documentation](https://node-postgres.com) :star: + ### Features From 482c06bfc83f5b1f882d360aa0f1f2db0eab0693 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 18 Jul 2017 13:38:13 -0700 Subject: [PATCH 0277/1037] Update minimum Node version to 4.5.0 `Buffer.alloc` and `Buffer.from` were only backported then. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5a1405038..727c90323 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,6 @@ }, "license": "MIT", "engines": { - "node": ">= 4.0.0" + "node": ">= 4.5.0" } } From 0921daa7f4ab8f71a973c4e1d8bc1046eca7cd9b Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 18 Jul 2017 15:41:31 -0500 Subject: [PATCH 0278/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 727c90323..6763a8e14 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.0.0", + "version": "7.0.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 5062f275a7eb09771b476fc412c676d32a3e515f Mon Sep 17 00:00:00 2001 From: Billouboq Date: Wed, 19 Jul 2017 00:35:11 +0200 Subject: [PATCH 0279/1037] remove unused variable test --- lib/native/query.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/native/query.js b/lib/native/query.js index dbcd56041..7602d161b 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -50,21 +50,20 @@ var errorFieldMap = { } NativeQuery.prototype.handleError = function (err) { - var self = this // copy pq error fields into the error object - var fields = self.native.pq.resultErrorFields() + var fields = this.native.pq.resultErrorFields() if (fields) { for (var key in fields) { var normalizedFieldName = errorFieldMap[key] || key err[normalizedFieldName] = fields[key] } } - if (self.callback) { - self.callback(err) + if (this.callback) { + this.callback(err) } else { - self.emit('error', err) + this.emit('error', err) } - self.state = 'error' + this.state = 'error' } NativeQuery.prototype.then = function (onSuccess, onFailure) { From 66c6776f6eaf3b31d010caf41538bc7e02ee2785 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 21 Jul 2017 14:51:34 -0700 Subject: [PATCH 0280/1037] Make client.end return promise with active query --- lib/client.js | 2 +- test/integration/gh-issues/1382-tests.js | 34 ++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 test/integration/gh-issues/1382-tests.js diff --git a/lib/client.js b/lib/client.js index 107377c7b..72edd699b 100644 --- a/lib/client.js +++ b/lib/client.js @@ -400,7 +400,7 @@ Client.prototype.end = function (cb) { // if we have an active query we need to force a disconnect // on the socket - otherwise a hung query could block end forever this.connection.stream.destroy(new Error('Connection terminated by user')) - return + return cb ? cb() : Promise.resolve() } if (cb) { this.connection.end() diff --git a/test/integration/gh-issues/1382-tests.js b/test/integration/gh-issues/1382-tests.js new file mode 100644 index 000000000..3cbc31cf1 --- /dev/null +++ b/test/integration/gh-issues/1382-tests.js @@ -0,0 +1,34 @@ +"use strict" +var helper = require('./../test-helper') + +const suite = new helper.Suite() + +suite.test('calling end during active query should return a promise', (done) => { + const client = new helper.pg.Client() + let callCount = 0 + // ensure both the query rejects and the end promise resolves + const after = () => { + if (++callCount > 1) { + done() + } + } + client.connect().then(() => { + client.query('SELECT NOW()').catch(after) + client.end().then(after) + }) +}) + +suite.test('calling end during an active query should call end callback', (done) => { + const client = new helper.pg.Client() + let callCount = 0 + // ensure both the query rejects and the end callback fires + const after = () => { + if (++callCount > 1) { + done() + } + } + client.connect().then(() => { + client.query('SELECT NOW()').catch(after) + client.end(after) + }) +}) From 40cc6aa111d48cff9d1664c831de4f6e3ae49c6d Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Thu, 20 Jul 2017 11:31:41 +0100 Subject: [PATCH 0281/1037] Update utils.js fixing invalid custom type check --- lib/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils.js b/lib/utils.js index 166cbddc6..352a02fbc 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -70,7 +70,7 @@ var prepareValue = function (val, seen) { } function prepareObject (val, seen) { - if (val.toPostgres && typeof val.toPostgres === 'function') { + if (val && typeof val.toPostgres === 'function') { seen = seen || [] if (seen.indexOf(val) !== -1) { throw new Error('circular reference detected while preparing "' + val + '" for query') From c6ee20081fcd383ceef2580cb62aeb13ddf2b29c Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 21 Jul 2017 15:03:10 -0700 Subject: [PATCH 0282/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6763a8e14..788b8a67d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.0.1", + "version": "7.0.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 6517207690e1ab449395a320f691b77f952af3a1 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 3 Aug 2017 23:51:44 -0500 Subject: [PATCH 0283/1037] Create SPONSORS.md --- SPONSORS.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 SPONSORS.md diff --git a/SPONSORS.md b/SPONSORS.md new file mode 100644 index 000000000..81c1db64a --- /dev/null +++ b/SPONSORS.md @@ -0,0 +1,3 @@ +# Leaders + +# Supporters From 3a6b8416c2ade5e9b4e4f57571b978f718f7c712 Mon Sep 17 00:00:00 2001 From: caub Date: Thu, 13 Jul 2017 18:37:28 +0200 Subject: [PATCH 0284/1037] allow both connectionString and additional options --- lib/connection-parameters.js | 11 +++++----- lib/index.js | 5 +---- .../connection-parameters/creation-tests.js | 22 +++++++++++++++++++ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index f999d1801..37658c12a 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -11,6 +11,8 @@ var dns = require('dns') var defaults = require('./defaults') +var parse = require('pg-connection-string').parse // parses a connection string + var val = function (key, config, envVar) { if (envVar === undefined) { envVar = process.env[ 'PG' + key.toUpperCase() ] @@ -25,9 +27,6 @@ var val = function (key, config, envVar) { defaults[key] } -// parses a connection string -var parse = require('pg-connection-string').parse - var useSsl = function () { switch (process.env.PGSSLMODE) { case 'disable': @@ -43,12 +42,14 @@ var useSsl = function () { var ConnectionParameters = function (config) { // if a string is passed, it is a raw connection string so we parse it into a config - config = typeof config === 'string' ? parse(config) : (config || {}) + config = typeof config === 'string' ? parse(config) : config || {} + // if the config has a connectionString defined, parse IT into the config we use // this will override other default values with what is stored in connectionString if (config.connectionString) { - config = parse(config.connectionString) + config = Object.assign({}, config, parse(config.connectionString)) } + this.user = val('user', config) this.database = val('database', config) this.port = parseInt(val('port', config), 10) diff --git a/lib/index.js b/lib/index.js index 14434ff77..00e3ceed4 100644 --- a/lib/index.js +++ b/lib/index.js @@ -15,10 +15,7 @@ var Pool = require('pg-pool') const poolFactory = (Client) => { var BoundPool = function (options) { - var config = { Client: Client } - for (var key in options) { - config[key] = options[key] - } + var config = Object.assign({ Client: Client }, options) return new Pool(config) } diff --git a/test/unit/connection-parameters/creation-tests.js b/test/unit/connection-parameters/creation-tests.js index aa39a038b..9e02e56d0 100644 --- a/test/unit/connection-parameters/creation-tests.js +++ b/test/unit/connection-parameters/creation-tests.js @@ -67,6 +67,28 @@ test('ConnectionParameters initializing from config', function () { assert.ok(subject.isDomainSocket === false) }) +test('ConnectionParameters initializing from config and config.connectionString', function() { + var subject1 = new ConnectionParameters({ + connectionString: 'postgres://test@host/db' + }) + var subject2 = new ConnectionParameters({ + connectionString: 'postgres://test@host/db?ssl=1' + }) + var subject3 = new ConnectionParameters({ + connectionString: 'postgres://test@host/db', + ssl: true + }) + var subject4 = new ConnectionParameters({ + connectionString: 'postgres://test@host/db?ssl=1', + ssl: false + }) + + assert.equal(subject1.ssl, false) + assert.equal(subject2.ssl, true) + assert.equal(subject3.ssl, true) + assert.equal(subject4.ssl, true) +}); + test('escape spaces if present', function () { var subject = new ConnectionParameters('postgres://localhost/post gres') assert.equal(subject.database, 'post gres') From 03e8f7128c7936d8499ceb18c1c42f2a54f33934 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 3 Aug 2017 23:55:01 -0500 Subject: [PATCH 0285/1037] Update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bb1cf726..848246275 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.1.0 + +#### Enhancements + +- [You can now supply both a connection string and additional config options to clients.](https://github.com/brianc/node-postgres/pull/1363) + ### 7.0.0 #### Breaking Changes From 56d262fdfa92b9b0acd4a3660fd480d083a7cb3a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 3 Aug 2017 23:55:07 -0500 Subject: [PATCH 0286/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 788b8a67d..dfa0324d4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.0.2", + "version": "7.1.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 9ab62ff9f3050bc8d1096cd6f1258cd288be75fd Mon Sep 17 00:00:00 2001 From: caub Date: Sat, 1 Jul 2017 11:32:37 +0200 Subject: [PATCH 0287/1037] allow min/max params for pg-pool --- .gitignore | 1 + .travis.yml | 2 ++ index.js | 36 +++++++++++++----------------------- package.json | 2 +- test/parse.js | 18 +++++++++++++++++- 5 files changed, 34 insertions(+), 25 deletions(-) diff --git a/.gitignore b/.gitignore index da23d0d4b..f28f01f78 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ build/Release # Deployed apps should consider commenting this line out: # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git node_modules +package-lock.json \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 244b7e88e..202c30781 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,5 @@ language: node_js node_js: - '0.10' + - '6.9' + - '8' diff --git a/index.js b/index.js index b2863ddef..0042faec0 100644 --- a/index.js +++ b/index.js @@ -8,18 +8,20 @@ var url = require('url'); //parses a connection string function parse(str) { - var config; //unix socket if(str.charAt(0) === '/') { - config = str.split(' '); + var config = str.split(' '); return { host: config[0], database: config[1] }; } + // url parse expects spaces encoded as %20 - if(/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) { - str = encodeURI(str).replace(/\%25(\d\d)/g, "%$1"); + var result = url.parse(/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str) ? encodeURI(str).replace(/\%25(\d\d)/g, "%$1") : str, true); + var config = result.query; + for (var k in config) { + if (Array.isArray(config[k])) { + config[k] = config[k][config[k].length-1]; + } } - var result = url.parse(str, true); - config = {}; config.port = result.port; if(result.protocol == 'socket:') { @@ -42,26 +44,14 @@ function parse(str) { config.user = auth[0]; config.password = auth.splice(1).join(':'); - var ssl = result.query.ssl; - if (ssl === 'true' || ssl === '1') { + if (config.ssl === 'true' || config.ssl === '1') { config.ssl = true; } - ['db', 'database', 'encoding', 'client_encoding', 'host', 'port', 'user', 'password', 'ssl'] - .forEach(function(key) { - delete result.query[key]; - }); - - Object.getOwnPropertyNames(result.query).forEach(function(key) { - var value = result.query[key]; - if (Array.isArray(value)) - value = value[value.length-1]; - config[key] = value; - }); - return config; } -module.exports = { - parse: parse -}; + +module.exports = parse; + +parse.parse = parse; diff --git a/package.json b/package.json index f3b14c907..9b0e62ec4 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,6 @@ "homepage": "https://github.com/iceddev/pg-connection-string", "dependencies": {}, "devDependencies": { - "tap": "^0.4.11" + "tap": "^10.3.3" } } diff --git a/test/parse.js b/test/parse.js index bd1171ba7..8f4bcb43a 100644 --- a/test/parse.js +++ b/test/parse.js @@ -160,6 +160,20 @@ test('configuration parameter ssl=1', function(t){ t.end(); }); +test('set ssl', function (t) { + var subject = parse('pg://myhost/db?ssl=1'); + t.equal(subject.ssl, true); + t.end(); + }); + + test('allow other params like max, ...', function (t) { + var subject = parse('pg://myhost/db?max=18&min=4'); + t.equal(subject.max, '18'); + t.equal(subject.min, '4'); + t.end(); + }); + + test('configuration parameter keepalives', function(t){ var connectionString = 'pg:///?keepalives=1'; var subject = parse(connectionString); @@ -182,9 +196,11 @@ test('do not override a config field with value from query string', function(t){ t.end(); }); + test('return last value of repeated parameter', function(t){ var connectionString = 'pg:///?keepalives=1&keepalives=0'; var subject = parse(connectionString); t.equal(subject.keepalives, '0'); t.end(); -}); \ No newline at end of file +}); + From d0c18b088d0dac9fbb9b01cb23bf5dd33d9ceea8 Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 4 Aug 2017 15:42:51 -0500 Subject: [PATCH 0288/1037] Update README.md Add Patreon page link --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index be50cc2ab..3058bc19e 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,10 @@ You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that I offer professional support for node-postgres. I provide implementation, training, and many years of expertise on how to build applications with node, express, PostgreSQL, and react/redux. Please contact me at [brian.m.carlson@gmail.com](mailto:brian.m.carlson@gmail.com) to discuss how I can help your company be more successful! +### Sponsorship :heart: + +If you are benifiting from node-postgres and would like to help keep the project financially sustainable please visit Brian Carlson's [Patreon page](https://www.patreon.com/node_postgres). + ## Contributing __:heart: contributions!__ From a8304f8bac8e386af35f5733b8940415495ac1b7 Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 4 Aug 2017 15:47:45 -0500 Subject: [PATCH 0289/1037] Update README.md Spelling... --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3058bc19e..8e479769d 100644 --- a/README.md +++ b/README.md @@ -48,9 +48,9 @@ You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that I offer professional support for node-postgres. I provide implementation, training, and many years of expertise on how to build applications with node, express, PostgreSQL, and react/redux. Please contact me at [brian.m.carlson@gmail.com](mailto:brian.m.carlson@gmail.com) to discuss how I can help your company be more successful! -### Sponsorship :heart: +### Sponsorship :star: -If you are benifiting from node-postgres and would like to help keep the project financially sustainable please visit Brian Carlson's [Patreon page](https://www.patreon.com/node_postgres). +If you are benefiting from node-postgres and would like to help keep the project financially sustainable please visit Brian Carlson's [Patreon page](https://www.patreon.com/node_postgres). ## Contributing From 9c7d2c853e70dbdcb9d5ad36d34525eebb174b6f Mon Sep 17 00:00:00 2001 From: Rick Bergfalk Date: Fri, 4 Aug 2017 16:58:32 -0400 Subject: [PATCH 0290/1037] Test cursor with pg-pool --- test/pool.js | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 test/pool.js diff --git a/test/pool.js b/test/pool.js new file mode 100644 index 000000000..c3f755bfd --- /dev/null +++ b/test/pool.js @@ -0,0 +1,85 @@ +const assert = require('assert') +const Cursor = require('../') +const pg = require('pg') + +const text = 'SELECT generate_series as num FROM generate_series(0, 50)' + +function poolQueryPromise(pool, readRowCount) { + return new Promise((resolve, reject) => { + pool.connect((err, client, done) => { + if (err) { + done(err) + return reject(err) + } + const cursor = client.query(new Cursor(text)) + cursor.read(readRowCount, (err, res) => { + if (err) { + done(err) + return reject(err) + } + cursor.close(err => { + if (err) { + done(err) + return reject(err) + } + done() + resolve() + }) + }) + }) + }) +} + +describe('pool', function() { + beforeEach(function() { + this.pool = new pg.Pool({max: 1}) + }) + + afterEach(function() { + this.pool.end() + }) + + it('closes cursor early, single pool query', function(done) { + poolQueryPromise(this.pool, 25) + .then(() => done()) + .catch(err => { + assert.ifError(err) + done() + }) + }) + + it('closes cursor early, saturated pool', function(done) { + const promises = [] + for (let i = 0; i < 10; i++) { + promises.push(poolQueryPromise(this.pool, 25)) + } + Promise.all(promises) + .then(() => done()) + .catch(err => { + assert.ifError(err) + done() + }) + }) + + it('closes exhausted cursor, single pool query', function(done) { + poolQueryPromise(this.pool, 100) + .then(() => done()) + .catch(err => { + assert.ifError(err) + done() + }) + }) + + it('closes exhausted cursor, saturated pool', function(done) { + const promises = [] + for (let i = 0; i < 10; i++) { + promises.push(poolQueryPromise(this.pool, 100)) + } + Promise.all(promises) + .then(() => done()) + .catch(err => { + assert.ifError(err) + done() + }) + }) +}) \ No newline at end of file From 620ddc0dede4e5ed1d7e9702c86b6273cfe9d3be Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 4 Aug 2017 17:40:52 -0500 Subject: [PATCH 0291/1037] Do not send close after readyForQuery Close is used to release a named portal (which isn't used by pg-cursor) or when you're early-terminating a cursor on the unnamed portal. Sending 'close' on an connection which has already sent 'readyForQuery' results in the connection responding with a _second_ 'readyForQuery' which causes a lot of issues within node-postgres as 'readyForQuery' is the signal to indicate the client has gone back into the idle state. --- index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/index.js b/index.js index 0827043e5..84236fc6e 100644 --- a/index.js +++ b/index.js @@ -145,6 +145,9 @@ Cursor.prototype.end = function(cb) { } Cursor.prototype.close = function(cb) { + if (this.state == 'done') { + return setImmediate(cb) + } this.connection.close({type: 'P'}) this.connection.sync() this.state = 'done' From 5a0af8cdd13850a179ad4e9019d5a7a30f005942 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 5 Aug 2017 15:56:56 -0500 Subject: [PATCH 0292/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f3a0d6429..f37edf9df 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "1.2.0", + "version": "1.2.1", "description": "", "main": "index.js", "directories": { From a720dc774b33b8eabc70acf8c8d1d1894c16bf10 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Sat, 5 Aug 2017 16:59:20 -0500 Subject: [PATCH 0293/1037] Some cleanup --- .travis.yml | 4 +++- index.js | 13 +++++------ package.json | 6 ++--- test/error-handling.js | 50 ++++++++++++++++++++++++++++++++++++++---- test/index.js | 1 + test/mocha.opts | 1 - 6 files changed, 59 insertions(+), 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index 267b07b57..54d66546e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,9 @@ language: node_js dist: trusty sudo: false node_js: + - "4.2" - "6" + - "8" env: - PGUSER=postgres services: @@ -10,4 +12,4 @@ services: addons: postgresql: "9.6" before_script: - - psql -c 'create database travis;' -U postgres | true \ No newline at end of file + - psql -c 'create database travis;' -U postgres | true diff --git a/index.js b/index.js index 84236fc6e..6b8103813 100644 --- a/index.js +++ b/index.js @@ -98,10 +98,8 @@ Cursor.prototype.handleReadyForQuery = function() { this.state = 'done' } -Cursor.prototype.handleEmptyQuery = function(con) { - if (con.sync) { - con.sync() - } +Cursor.prototype.handleEmptyQuery = function() { + this.connection.sync() }; Cursor.prototype.handleError = function(msg) { @@ -140,8 +138,9 @@ Cursor.prototype.end = function(cb) { if(this.state != 'initialized') { this.connection.sync() } - this.connection.end() this.connection.stream.once('end', cb) + console.log('calling end on connection') + this.connection.end() } Cursor.prototype.close = function(cb) { @@ -167,10 +166,10 @@ Cursor.prototype.read = function(rows, cb) { return this._queue.push([rows, cb]) } if(this.state == 'error') { - return cb(this._error) + return setImmediate(() => cb(this._error)) } if(this.state == 'done') { - return cb(null, []) + return setImmediate(() => cb(null, [])) } else { throw new Error("Unknown state: " + this.state) diff --git a/package.json b/package.json index f37edf9df..bfd060b90 100644 --- a/package.json +++ b/package.json @@ -7,13 +7,13 @@ "test": "test" }, "scripts": { - "test": "mocha test/" + "test": "mocha test" }, "author": "Brian M. Carlson", "license": "MIT", "devDependencies": { - "pg": "~6.0.0", - "mocha": "~1.17.1" + "mocha": "^3.5.0", + "pg": "~6.0.0" }, "dependencies": {} } diff --git a/test/error-handling.js b/test/error-handling.js index fedee4b13..45c7f3639 100644 --- a/test/error-handling.js +++ b/test/error-handling.js @@ -20,16 +20,58 @@ describe('error handling', function() { }) }) -describe('proper cleanup', function() { - it('can issue multiple cursors on one client', function(done) { +describe('read callback does not fire sync', () => { + it('does not fire error callback sync', (done) => { + var client = new pg.Client() + client.connect() + var cursor = client.query(new Cursor('asdfdffsdf')) + let after = false + cursor.read(1, function(err) { + assert(err, 'error should be returned') + assert.equal(after, true, 'should not call read sync') + after = false + cursor.read(1, function (err) { + assert(err, 'error should be returned') + assert.equal(after, true, 'should not call read sync') + client.end() + done() + }) + after = true + }) + after = true + }) + + it('does not fire result sync after finished', (done) => { + var client = new pg.Client() + client.connect() + var cursor = client.query(new Cursor('SELECT NOW()')) + let after = false + cursor.read(1, function(err) { + assert.equal(after, true, 'should not call read sync') + cursor.read(1, function (err) { + after = false + cursor.read(1, function (err) { + assert.equal(after, true, 'should not call read sync') + client.end() + done() + }) + after = true + }) + }) + after = true + }) +}) + +describe('proper cleanup', function () { + it('can issue multiple cursors on one client', function (done) { var client = new pg.Client() client.connect() var cursor1 = client.query(new Cursor(text)) - cursor1.read(8, function(err, rows) { + cursor1.read(8, function (err, rows) { assert.ifError(err) assert.equal(rows.length, 5) cursor2 = client.query(new Cursor(text)) - cursor2.read(8, function(err, rows) { + cursor2.read(8, function (err, rows) { assert.ifError(err) assert.equal(rows.length, 5) client.end() diff --git a/test/index.js b/test/index.js index cc97960e5..fd8c73d2a 100644 --- a/test/index.js +++ b/test/index.js @@ -30,6 +30,7 @@ describe('cursor', function() { }) }) + for (var i = 0; i < 100; i++) it('end before reading to end', function(done) { var cursor = this.pgCursor(text) cursor.read(3, function(err, res) { diff --git a/test/mocha.opts b/test/mocha.opts index 8fd0f04e3..46e8e69d9 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1,3 +1,2 @@ --no-exit --bail ---reporter=spec From 3675d2b041cb95aaa5d4c1dbe4ddbc39b18ab478 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 5 Aug 2017 17:17:24 -0500 Subject: [PATCH 0294/1037] Fix to support node@4 LTS --- index.js | 2 +- package.json | 2 +- test/error-handling.js | 3 ++- test/index.js | 1 - test/mocha.opts | 1 + test/pool.js | 3 ++- test/result-config.js | 9 +++++++++ 7 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 test/result-config.js diff --git a/index.js b/index.js index 6b8103813..bda2b4863 100644 --- a/index.js +++ b/index.js @@ -114,7 +114,7 @@ Cursor.prototype.handleError = function(msg) { this._queue.pop()[1](msg) } - if (this.eventNames().indexOf('error') >= 0) { + if (this.listenerCount('error') > 0) { //only dispatch error events if we have a listener this.emit('error', msg) } diff --git a/package.json b/package.json index bfd060b90..d6238ec61 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "test": "test" }, "scripts": { - "test": "mocha test" + "test": "mocha" }, "author": "Brian M. Carlson", "license": "MIT", diff --git a/test/error-handling.js b/test/error-handling.js index 45c7f3639..014762009 100644 --- a/test/error-handling.js +++ b/test/error-handling.js @@ -1,3 +1,4 @@ +'use strict' var assert = require('assert') var Cursor = require('../') var pg = require('pg') @@ -70,7 +71,7 @@ describe('proper cleanup', function () { cursor1.read(8, function (err, rows) { assert.ifError(err) assert.equal(rows.length, 5) - cursor2 = client.query(new Cursor(text)) + var cursor2 = client.query(new Cursor(text)) cursor2.read(8, function (err, rows) { assert.ifError(err) assert.equal(rows.length, 5) diff --git a/test/index.js b/test/index.js index fd8c73d2a..cc97960e5 100644 --- a/test/index.js +++ b/test/index.js @@ -30,7 +30,6 @@ describe('cursor', function() { }) }) - for (var i = 0; i < 100; i++) it('end before reading to end', function(done) { var cursor = this.pgCursor(text) cursor.read(3, function(err, res) { diff --git a/test/mocha.opts b/test/mocha.opts index 46e8e69d9..eb60d626e 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1,2 +1,3 @@ +--reporter spec --no-exit --bail diff --git a/test/pool.js b/test/pool.js index c3f755bfd..2817f881b 100644 --- a/test/pool.js +++ b/test/pool.js @@ -1,3 +1,4 @@ +'use strict' const assert = require('assert') const Cursor = require('../') const pg = require('pg') @@ -82,4 +83,4 @@ describe('pool', function() { done() }) }) -}) \ No newline at end of file +}) diff --git a/test/result-config.js b/test/result-config.js new file mode 100644 index 000000000..f8db484ca --- /dev/null +++ b/test/result-config.js @@ -0,0 +1,9 @@ +var assert = require('assert') +var Cursor = require('../') +var pg = require('pg') + +describe('Custom query config', () => { + it('supports row mode array', () => { + + }) +}) From 2ced8f1f2b3f4f221a7cba4a58a37a8ee7eda81a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 5 Aug 2017 17:24:49 -0500 Subject: [PATCH 0295/1037] Integrate eslint --- .eslintrc | 9 ++++ index.js | 114 +++++++++++++++++++-------------------- package.json | 8 ++- pg.js | 8 +-- test/close.js | 14 ++--- test/error-handling.js | 15 +++--- test/index.js | 92 ++++++++++++++++--------------- test/no-data-handling.js | 14 +++-- test/pool.js | 16 +++--- 9 files changed, 154 insertions(+), 136 deletions(-) create mode 100644 .eslintrc diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 000000000..95f4d0c65 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,9 @@ +{ + "extends": "standard", + "env": { + "mocha": true + }, + "rules": { + "no-new-func": "off" + } +} diff --git a/index.js b/index.js index bda2b4863..b01d43fde 100644 --- a/index.js +++ b/index.js @@ -1,10 +1,11 @@ -var Result = require('./pg').Result -var prepare = require('./pg').prepareValue -var EventEmitter = require('events').EventEmitter; -var util = require('util'); +'use strict' +const Result = require('./pg').Result +const prepare = require('./pg').prepareValue +const EventEmitter = require('events').EventEmitter +const util = require('util') function Cursor (text, values) { - EventEmitter.call(this); + EventEmitter.call(this) this.text = text this.values = values ? values.map(prepare) : null @@ -18,11 +19,10 @@ function Cursor (text, values) { util.inherits(Cursor, EventEmitter) -Cursor.prototype.submit = function(connection) { +Cursor.prototype.submit = function (connection) { this.connection = connection - var con = connection - var self = this + const con = connection con.parse({ text: this.text @@ -34,99 +34,99 @@ Cursor.prototype.submit = function(connection) { con.describe({ type: 'P', - name: '' //use unamed portal + name: '' // use unamed portal }, true) con.flush() + const ifNoData = () => { + this.state = 'idle' + this._shiftQueue() + } + con.once('noData', ifNoData) con.once('rowDescription', function () { - con.removeListener('noData', ifNoData); - }); - - function ifNoData () { - self.state = 'idle' - self._shiftQueue(); - } + con.removeListener('noData', ifNoData) + }) } Cursor.prototype._shiftQueue = function () { - if(this._queue.length) { + if (this._queue.length) { this._getRows.apply(this, this._queue.shift()) } } -Cursor.prototype.handleRowDescription = function(msg) { +Cursor.prototype.handleRowDescription = function (msg) { this._result.addFields(msg.fields) this.state = 'idle' - this._shiftQueue(); + this._shiftQueue() } -Cursor.prototype.handleDataRow = function(msg) { - var row = this._result.parseRow(msg.fields) +Cursor.prototype.handleDataRow = function (msg) { + const row = this._result.parseRow(msg.fields) this.emit('row', row, this._result) this._rows.push(row) } -Cursor.prototype._sendRows = function() { +Cursor.prototype._sendRows = function () { this.state = 'idle' - setImmediate(function() { - var cb = this._cb - //remove callback before calling it - //because likely a new one will be added - //within the call to this callback + setImmediate(() => { + const cb = this._cb + // remove callback before calling it + // because likely a new one will be added + // within the call to this callback this._cb = null - if(cb) { + if (cb) { this._result.rows = this._rows cb(null, this._rows, this._result) } this._rows = [] - }.bind(this)) + }) } -Cursor.prototype.handleCommandComplete = function() { +Cursor.prototype.handleCommandComplete = function () { this.connection.sync() } -Cursor.prototype.handlePortalSuspended = function() { +Cursor.prototype.handlePortalSuspended = function () { this._sendRows() } -Cursor.prototype.handleReadyForQuery = function() { +Cursor.prototype.handleReadyForQuery = function () { this._sendRows() this.emit('end', this._result) this.state = 'done' } -Cursor.prototype.handleEmptyQuery = function() { +Cursor.prototype.handleEmptyQuery = function () { this.connection.sync() -}; +} -Cursor.prototype.handleError = function(msg) { +Cursor.prototype.handleError = function (msg) { this.state = 'error' this._error = msg - //satisfy any waiting callback - if(this._cb) { + // satisfy any waiting callback + if (this._cb) { this._cb(msg) } - //dispatch error to all waiting callbacks - for(var i = 0; i < this._queue.length; i++) { + // dispatch error to all waiting callbacks + for (var i = 0; i < this._queue.length; i++) { this._queue.pop()[1](msg) } if (this.listenerCount('error') > 0) { - //only dispatch error events if we have a listener + // only dispatch error events if we have a listener this.emit('error', msg) } - //call sync to keep this connection from hanging + // call sync to keep this connection from hanging this.connection.sync() } -Cursor.prototype._getRows = function(rows, cb) { +Cursor.prototype._getRows = function (rows, cb) { this.state = 'busy' this._cb = cb this._rows = [] - var msg = { + const msg = { portal: '', rows: rows } @@ -134,8 +134,8 @@ Cursor.prototype._getRows = function(rows, cb) { this.connection.flush() } -Cursor.prototype.end = function(cb) { - if(this.state != 'initialized') { +Cursor.prototype.end = function (cb) { + if (this.state !== 'initialized') { this.connection.sync() } this.connection.stream.once('end', cb) @@ -143,36 +143,34 @@ Cursor.prototype.end = function(cb) { this.connection.end() } -Cursor.prototype.close = function(cb) { - if (this.state == 'done') { +Cursor.prototype.close = function (cb) { + if (this.state === 'done') { return setImmediate(cb) } this.connection.close({type: 'P'}) this.connection.sync() this.state = 'done' - if(cb) { - this.connection.once('closeComplete', function() { + if (cb) { + this.connection.once('closeComplete', function () { cb() }) } } -Cursor.prototype.read = function(rows, cb) { - var self = this - if(this.state == 'idle') { +Cursor.prototype.read = function (rows, cb) { + if (this.state === 'idle') { return this._getRows(rows, cb) } - if(this.state == 'busy' || this.state == 'initialized') { + if (this.state === 'busy' || this.state === 'initialized') { return this._queue.push([rows, cb]) } - if(this.state == 'error') { + if (this.state === 'error') { return setImmediate(() => cb(this._error)) } - if(this.state == 'done') { + if (this.state === 'done') { return setImmediate(() => cb(null, [])) - } - else { - throw new Error("Unknown state: " + this.state) + } else { + throw new Error('Unknown state: ' + this.state) } } diff --git a/package.json b/package.json index d6238ec61..8050798e3 100644 --- a/package.json +++ b/package.json @@ -7,11 +7,17 @@ "test": "test" }, "scripts": { - "test": "mocha" + "test": " mocha && eslint ." }, "author": "Brian M. Carlson", "license": "MIT", "devDependencies": { + "eslint": "^4.4.0", + "eslint-config-standard": "^10.2.1", + "eslint-plugin-import": "^2.7.0", + "eslint-plugin-node": "^5.1.1", + "eslint-plugin-promise": "^3.5.0", + "eslint-plugin-standard": "^3.0.1", "mocha": "^3.5.0", "pg": "~6.0.0" }, diff --git a/pg.js b/pg.js index c6be9ba61..42d89a9b1 100644 --- a/pg.js +++ b/pg.js @@ -1,10 +1,10 @@ -//support both pg & pg.js -//this will eventually go away when i break native bindings -//out into their own module +// support both pg & pg.js +// this will eventually go away when i break native bindings +// out into their own module try { module.exports.Result = require('pg/lib/result.js') module.exports.prepareValue = require('pg/lib/utils.js').prepareValue -} catch(e) { +} catch (e) { module.exports.Result = require('pg.js/lib/result.js') module.exports.prepareValue = require('pg.js/lib/utils.js').prepareValue } diff --git a/test/close.js b/test/close.js index df61319e3..59ea3c71a 100644 --- a/test/close.js +++ b/test/close.js @@ -3,30 +3,30 @@ var Cursor = require('../') var pg = require('pg') var text = 'SELECT generate_series as num FROM generate_series(0, 50)' -describe('close', function() { - beforeEach(function(done) { +describe('close', function () { + beforeEach(function (done) { var client = this.client = new pg.Client() client.connect(done) client.on('drain', client.end.bind(client)) }) - it('closes cursor early', function(done) { + it('closes cursor early', function (done) { var cursor = new Cursor(text) this.client.query(cursor) this.client.query('SELECT NOW()', done) - cursor.read(25, function(err, res) { + cursor.read(25, function (err, res) { assert.ifError(err) cursor.close() }) }) - it('works with callback style', function(done) { + it('works with callback style', function (done) { var cursor = new Cursor(text) var client = this.client client.query(cursor) - cursor.read(25, function(err, res) { + cursor.read(25, function (err, res) { assert.ifError(err) - cursor.close(function(err) { + cursor.close(function (err) { assert.ifError(err) client.query('SELECT NOW()', done) }) diff --git a/test/error-handling.js b/test/error-handling.js index 014762009..bfcbf71f1 100644 --- a/test/error-handling.js +++ b/test/error-handling.js @@ -5,14 +5,14 @@ var pg = require('pg') var text = 'SELECT generate_series as num FROM generate_series(0, 4)' -describe('error handling', function() { - it('can continue after error', function(done) { +describe('error handling', function () { + it('can continue after error', function (done) { var client = new pg.Client() client.connect() var cursor = client.query(new Cursor('asdfdffsdf')) - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(err) - client.query('SELECT NOW()', function(err, res) { + client.query('SELECT NOW()', function (err, res) { assert.ifError(err) client.end() done() @@ -27,7 +27,7 @@ describe('read callback does not fire sync', () => { client.connect() var cursor = client.query(new Cursor('asdfdffsdf')) let after = false - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(err, 'error should be returned') assert.equal(after, true, 'should not call read sync') after = false @@ -47,11 +47,14 @@ describe('read callback does not fire sync', () => { client.connect() var cursor = client.query(new Cursor('SELECT NOW()')) let after = false - cursor.read(1, function(err) { + cursor.read(1, function (err) { + assert(!err) assert.equal(after, true, 'should not call read sync') cursor.read(1, function (err) { + assert(!err) after = false cursor.read(1, function (err) { + assert(!err) assert.equal(after, true, 'should not call read sync') client.end() done() diff --git a/test/index.js b/test/index.js index cc97960e5..a5b3636fc 100644 --- a/test/index.js +++ b/test/index.js @@ -4,60 +4,60 @@ var pg = require('pg') var text = 'SELECT generate_series as num FROM generate_series(0, 5)' -describe('cursor', function() { - - beforeEach(function(done) { +describe('cursor', function () { + beforeEach(function (done) { var client = this.client = new pg.Client() client.connect(done) - this.pgCursor = function(text, values) { + this.pgCursor = function (text, values) { client.on('drain', client.end.bind(client)) return client.query(new Cursor(text, values || [])) } }) - - afterEach(function() { + afterEach(function () { this.client.end() }) - it('fetch 6 when asking for 10', function(done) { + it('fetch 6 when asking for 10', function (done) { var cursor = this.pgCursor(text) - cursor.read(10, function(err, res) { + cursor.read(10, function (err, res) { assert.ifError(err) assert.equal(res.length, 6) done() }) }) - it('end before reading to end', function(done) { + it('end before reading to end', function (done) { var cursor = this.pgCursor(text) - cursor.read(3, function(err, res) { + cursor.read(3, function (err, res) { assert.ifError(err) assert.equal(res.length, 3) cursor.end(done) }) }) - it('callback with error', function(done) { + it('callback with error', function (done) { var cursor = this.pgCursor('select asdfasdf') - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(err) done() }) }) - - it('read a partial chunk of data', function(done) { + it('read a partial chunk of data', function (done) { var cursor = this.pgCursor(text) - cursor.read(2, function(err, res) { + cursor.read(2, function (err, res) { assert.ifError(err) assert.equal(res.length, 2) - cursor.read(3, function(err, res) { + cursor.read(3, function (err, res) { + assert(!err) assert.equal(res.length, 3) - cursor.read(1, function(err, res) { + cursor.read(1, function (err, res) { + assert(!err) assert.equal(res.length, 1) - cursor.read(1, function(err, res) { + cursor.read(1, function (err, res) { + assert(!err) assert.ifError(err) assert.strictEqual(res.length, 0) done() @@ -67,12 +67,15 @@ describe('cursor', function() { }) }) - it('read return length 0 past the end', function(done) { + it('read return length 0 past the end', function (done) { var cursor = this.pgCursor(text) - cursor.read(2, function(err, res) { - cursor.read(100, function(err, res) { + cursor.read(2, function (err, res) { + assert(!err) + cursor.read(100, function (err, res) { + assert(!err) assert.equal(res.length, 4) - cursor.read(100, function(err, res) { + cursor.read(100, function (err, res) { + assert(!err) assert.equal(res.length, 0) done() }) @@ -80,22 +83,22 @@ describe('cursor', function() { }) }) - it('read huge result', function(done) { + it('read huge result', function (done) { this.timeout(10000) var text = 'SELECT generate_series as num FROM generate_series(0, 100000)' var values = [] - var cursor = this.pgCursor(text, values); - var count = 0; - var read = function() { - cursor.read(100, function(err, rows) { - if(err) return done(err); - if(!rows.length) { + var cursor = this.pgCursor(text, values) + var count = 0 + var read = function () { + cursor.read(100, function (err, rows) { + if (err) return done(err) + if (!rows.length) { assert.equal(count, 100001) return done() } - count += rows.length; - if(count%10000 == 0) { - //console.log(count) + count += rows.length + if (count % 10000 === 0) { + // console.log(count) } setImmediate(read) }) @@ -103,23 +106,24 @@ describe('cursor', function() { read() }) - it('normalizes parameter values', function(done) { + it('normalizes parameter values', function (done) { var text = 'SELECT $1::json me' - var values = [{name: 'brian'}] - var cursor = this.pgCursor(text, values); - cursor.read(1, function(err, rows) { - if(err) return done(err); + var values = [{ name: 'brian' }] + var cursor = this.pgCursor(text, values) + cursor.read(1, function (err, rows) { + if (err) return done(err) assert.equal(rows[0].me.name, 'brian') - cursor.read(1, function(err, rows) { + cursor.read(1, function (err, rows) { + assert(!err) assert.equal(rows.length, 0) done() }) }) }) - it('returns result along with rows', function(done) { + it('returns result along with rows', function (done) { var cursor = this.pgCursor(text) - cursor.read(1, function(err, rows, result) { + cursor.read(1, function (err, rows, result) { assert.ifError(err) assert.equal(rows.length, 1) assert.strictEqual(rows, result.rows) @@ -128,7 +132,7 @@ describe('cursor', function() { }) }) - it('emits row events', function(done) { + it('emits row events', function (done) { var cursor = this.pgCursor(text) cursor.read(10) cursor.on('row', (row, result) => result.addRow(row)) @@ -138,7 +142,7 @@ describe('cursor', function() { }) }) - it('emits row events when cursor is closed manually', function(done) { + it('emits row events when cursor is closed manually', function (done) { var cursor = this.pgCursor(text) cursor.on('row', (row, result) => result.addRow(row)) cursor.on('end', (result) => { @@ -149,9 +153,9 @@ describe('cursor', function() { cursor.read(3, () => cursor.close()) }) - it('emits error events', function(done) { + it('emits error events', function (done) { var cursor = this.pgCursor('select asdfasdf') - cursor.on('error', function(err) { + cursor.on('error', function (err) { assert(err) done() }) diff --git a/test/no-data-handling.js b/test/no-data-handling.js index 969df2d4b..2218b41de 100644 --- a/test/no-data-handling.js +++ b/test/no-data-handling.js @@ -1,15 +1,14 @@ var assert = require('assert') -var pg = require('pg'); -var Cursor = require('../'); +var pg = require('pg') +var Cursor = require('../') describe('queries with no data', function () { - beforeEach(function(done) { + beforeEach(function (done) { var client = this.client = new pg.Client() client.connect(done) }) - - afterEach(function() { + afterEach(function () { this.client.end() }) @@ -21,7 +20,7 @@ describe('queries with no data', function () { assert.equal(rows.length, 0) done() }) - }); + }) it('handles empty query', function (done) { var cursor = new Cursor('-- this is a comment') @@ -32,5 +31,4 @@ describe('queries with no data', function () { done() }) }) - -}); +}) diff --git a/test/pool.js b/test/pool.js index 2817f881b..e3d3bc1d9 100644 --- a/test/pool.js +++ b/test/pool.js @@ -5,7 +5,7 @@ const pg = require('pg') const text = 'SELECT generate_series as num FROM generate_series(0, 50)' -function poolQueryPromise(pool, readRowCount) { +function poolQueryPromise (pool, readRowCount) { return new Promise((resolve, reject) => { pool.connect((err, client, done) => { if (err) { @@ -31,16 +31,16 @@ function poolQueryPromise(pool, readRowCount) { }) } -describe('pool', function() { - beforeEach(function() { +describe('pool', function () { + beforeEach(function () { this.pool = new pg.Pool({max: 1}) }) - afterEach(function() { + afterEach(function () { this.pool.end() }) - it('closes cursor early, single pool query', function(done) { + it('closes cursor early, single pool query', function (done) { poolQueryPromise(this.pool, 25) .then(() => done()) .catch(err => { @@ -49,7 +49,7 @@ describe('pool', function() { }) }) - it('closes cursor early, saturated pool', function(done) { + it('closes cursor early, saturated pool', function (done) { const promises = [] for (let i = 0; i < 10; i++) { promises.push(poolQueryPromise(this.pool, 25)) @@ -62,7 +62,7 @@ describe('pool', function() { }) }) - it('closes exhausted cursor, single pool query', function(done) { + it('closes exhausted cursor, single pool query', function (done) { poolQueryPromise(this.pool, 100) .then(() => done()) .catch(err => { @@ -71,7 +71,7 @@ describe('pool', function() { }) }) - it('closes exhausted cursor, saturated pool', function(done) { + it('closes exhausted cursor, saturated pool', function (done) { const promises = [] for (let i = 0; i < 10; i++) { promises.push(poolQueryPromise(this.pool, 100)) From bbefeb8670e7c2d052cff37500b14776d76f0ebc Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 5 Aug 2017 17:25:13 -0500 Subject: [PATCH 0296/1037] Remove unused file --- test/result-config.js | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 test/result-config.js diff --git a/test/result-config.js b/test/result-config.js deleted file mode 100644 index f8db484ca..000000000 --- a/test/result-config.js +++ /dev/null @@ -1,9 +0,0 @@ -var assert = require('assert') -var Cursor = require('../') -var pg = require('pg') - -describe('Custom query config', () => { - it('supports row mode array', () => { - - }) -}) From 5b4bb7b6156235517ec2f0fd699c4c136c054964 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 5 Aug 2017 17:29:58 -0500 Subject: [PATCH 0297/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8050798e3..885aec1f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "1.2.1", + "version": "1.2.2", "description": "", "main": "index.js", "directories": { From 4ff97f54bf456460657a2a81d8f0b48a2e5f61ce Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 5 Aug 2017 18:22:54 -0500 Subject: [PATCH 0298/1037] Add support for rowMode & custom types --- index.js | 12 ++++++++---- package.json | 2 +- test/query-config.js | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 5 deletions(-) create mode 100644 test/query-config.js diff --git a/index.js b/index.js index b01d43fde..2c33a230c 100644 --- a/index.js +++ b/index.js @@ -4,15 +4,16 @@ const prepare = require('./pg').prepareValue const EventEmitter = require('events').EventEmitter const util = require('util') -function Cursor (text, values) { +function Cursor (text, values, config) { EventEmitter.call(this) + this._conf = config || { } this.text = text this.values = values ? values.map(prepare) : null this.connection = null this._queue = [] this.state = 'initialized' - this._result = new Result() + this._result = new Result(this._conf.rowMode) this._cb = null this._rows = null } @@ -44,8 +45,12 @@ Cursor.prototype.submit = function (connection) { this._shiftQueue() } + if (this._conf.types) { + this._result._getTypeParser = this._conf.types.getTypeParser + } + con.once('noData', ifNoData) - con.once('rowDescription', function () { + con.once('rowDescription', () => { con.removeListener('noData', ifNoData) }) } @@ -139,7 +144,6 @@ Cursor.prototype.end = function (cb) { this.connection.sync() } this.connection.stream.once('end', cb) - console.log('calling end on connection') this.connection.end() } diff --git a/package.json b/package.json index 885aec1f6..ea99f0f8e 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "eslint-plugin-promise": "^3.5.0", "eslint-plugin-standard": "^3.0.1", "mocha": "^3.5.0", - "pg": "~6.0.0" + "pg": "6.x" }, "dependencies": {} } diff --git a/test/query-config.js b/test/query-config.js new file mode 100644 index 000000000..3321f94e8 --- /dev/null +++ b/test/query-config.js @@ -0,0 +1,36 @@ +'use strict' +const assert = require('assert') +const Cursor = require('../') +const pg = require('pg') + +describe('query config passed to result', () => { + it('passes rowMode to result', (done) => { + const client = new pg.Client() + client.connect() + const text = 'SELECT generate_series as num FROM generate_series(0, 5)' + const cursor = client.query(new Cursor(text, null, { rowMode: 'array' })) + cursor.read(10, (err, rows) => { + assert(!err) + assert.deepEqual(rows, [[0], [1], [2], [3], [4], [5]]) + client.end() + done() + }) + }) + + it('passes types to result', (done) => { + const client = new pg.Client() + client.connect() + const text = 'SELECT generate_series as num FROM generate_series(0, 2)' + const types = { + getTypeParser: () => () => 'foo' + } + const cursor = client.query(new Cursor(text, null, { types })) + cursor.read(10, (err, rows) => { + assert(!err) + assert.deepEqual(rows, [{ num: 'foo' }, { num: 'foo' }, { num: 'foo' }]) + client.end() + done() + }) + + }) +}) From e0b2e41e57eb5e5c6e46746957a71ccdbc196f7e Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 5 Aug 2017 18:25:09 -0500 Subject: [PATCH 0299/1037] Fix lint --- test/query-config.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/query-config.js b/test/query-config.js index 3321f94e8..596adb9c2 100644 --- a/test/query-config.js +++ b/test/query-config.js @@ -31,6 +31,5 @@ describe('query config passed to result', () => { client.end() done() }) - }) }) From e517b8ce143ef62800cfaf9720f0120b217d7914 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Sat, 5 Aug 2017 18:27:29 -0500 Subject: [PATCH 0300/1037] WIP --- .travis.yml | 4 +- index.js | 110 +++++++++++++++----------------- package.json | 17 +++-- test/close.js | 46 ------------- test/helper.js | 2 +- test/issue-3.js | 2 +- test/mocha.opts | 1 + test/stream-tester-timestamp.js | 18 +++--- 8 files changed, 73 insertions(+), 127 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0e1916fb4..9c09f74bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,7 @@ language: node_js node_js: - - "0.10" - - "0.12" - "4.2" - "6" - - "7" + - "8" env: - PGUSER=postgres PGDATABASE=postgres diff --git a/index.js b/index.js index e19650925..6665b6b04 100644 --- a/index.js +++ b/index.js @@ -1,69 +1,63 @@ +'use strict'; var util = require('util') var Cursor = require('pg-cursor') -var Readable = require('readable-stream').Readable +var Readable = require('stream').Readable -var QueryStream = module.exports = function(text, values, options) { - var self = this - this._reading = false - this._closing = false - options = options || { } - Cursor.call(this, text, values) - Readable.call(this, { - objectMode: true, - highWaterMark: options.highWaterMark || 1000 - }) - this.batchSize = options.batchSize || 100 - this.once('end', function() { - process.nextTick(function() { - self.emit('close') - }) - }) -} +class PgQueryStream extends Readable { + constructor(text, values, options) { + super(Object.assign({ objectMode: true }, options)) + this.cursor = new Cursor(text, values) + this._reading = false + this._closed = false + this.batchSize = (options || { }).batchSize || 100 -util.inherits(QueryStream, Readable) + // delegate Submittable callbacks to cursor + this.handleRowDescription = this.cursor.handleRowDescription.bind(this.cursor) + this.handleDataRow = this.cursor.handleDataRow.bind(this.cursor) + this.handlePortalSuspended = this.cursor.handlePortalSuspended.bind(this.cursor) + this.handleCommandComplete = this.cursor.handleCommandComplete.bind(this.cursor) + this.handleReadyForQuery = this.cursor.handleReadyForQuery.bind(this.cursor) + this.handleError = this.cursor.handleError.bind(this.cursor) + } -//copy cursor prototype to QueryStream -//so we can handle all the events emitted by the connection -for(var key in Cursor.prototype) { - if(key == 'read') { - QueryStream.prototype._fetch = Cursor.prototype.read - } else { - QueryStream.prototype[key] = Cursor.prototype[key] + submit(connection) { + this.cursor.submit(connection) + return this } -} -QueryStream.prototype.close = function(cb) { - this._closing = true - var self = this - Cursor.prototype.close.call(this, function(err) { - if (cb) { cb(err); } - if(err) return self.emit('error', err) - process.nextTick(function() { - self.push(null) - }) - }) -} + close(callback) { + this._closed = true + const cb = callback || (() => this.emit('close')) + this.cursor.close(cb) + } -QueryStream.prototype._read = function(n) { - if(this._reading || this._closing) return false - this._reading = true - var self = this - this._fetch(this.batchSize, function(err, rows) { - if(err) { - return self.emit('error', err) + _read(size) { + if (this._reading || this._closed) { + return false } + this._reading = true + const readAmount = Math.max(size, this.batchSize) + this.cursor.read(readAmount, (err, rows) => { + if (this._closed) { + return + } + if (err) { + return this.emit('error', err) + } + // if we get a 0 length array we've read to the end of the cursor + if (!rows.length) { + this._closed = true + setImmediate(() => this.emit('close')) + return this.push(null) + } - if (self._closing) { return; } - - if(!rows.length) { - process.nextTick(function() { - self.push(null) - }) - return - } - self._reading = false - for(var i = 0; i < rows.length; i++) { - self.push(rows[i]) - } - }) + // push each row into the stream + this._reading = false + for(var i = 0; i < rows.length; i++) { + this.push(rows[i]) + } + }) + } } + +module.exports = PgQueryStream diff --git a/package.json b/package.json index 02f78231e..5f0e0a3fc 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { - "test": "mocha test/*.js -R spec" + "test": "mocha" }, "repository": { "type": "git", @@ -17,21 +17,20 @@ "stream" ], "author": "Brian M. Carlson", - "license": "BSD-2-Clause", + "license": "MIT", "bugs": { "url": "https://github.com/brianc/node-pg-query-stream/issues" }, "devDependencies": { - "pg.js": "*", + "JSONStream": "~0.7.1", "concat-stream": "~1.0.1", - "through": "~2.3.4", - "stream-tester": "0.0.5", + "mocha": "^3.5.0", + "pg": "6.x", "stream-spec": "~0.3.5", - "JSONStream": "~0.7.1", - "mocha": "~1.17.1" + "stream-tester": "0.0.5", + "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "1.0.0", - "readable-stream": "^2.0.4" + "pg-cursor": "1.2.1" } } diff --git a/test/close.js b/test/close.js index c0a300961..a8820c13e 100644 --- a/test/close.js +++ b/test/close.js @@ -34,52 +34,6 @@ helper('early close', function(client) { }) }) -helper('should not throw errors after early close', function(client) { - it('can be closed early without error', function(done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 2000) num'); - var query = client.query(stream); - var fetchCount = 0; - var errorCount = 0; - - - function waitForErrors() { - - setTimeout(function () { - assert(errorCount === 0, 'should not throw a ton of errors'); - done(); - }, 10); - } - - // hack internal _fetch function to force query.close immediately after _fetch is called (simulating the race condition) - // race condition: if close is called immediately after _fetch is called, but before results are returned, errors are thrown - // when the fetch results are pushed to the readable stream after its already closed. - query._fetch = (function (_fetch) { - return function () { - - // wait for the second fetch. closing immediately after the first fetch throws an entirely different error :( - if (fetchCount++ === 0) { - return _fetch.apply(this, arguments); - } - - var results = _fetch.apply(this, arguments); - - query.close(); - waitForErrors(); - - query._fetch = _fetch; // we're done with our hack, so restore the original _fetch function. - - return results; - } - }(query._fetch)); - - query.on('error', function () { errorCount++; }); - - query.on('readable', function () { - query.read(); - }); - }); -}); - helper('close callback', function (client) { it('notifies an optional callback when the conneciton is closed', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [10], {batchSize: 2, highWaterMark: 2}); diff --git a/test/helper.js b/test/helper.js index ce04d1271..f4e427203 100644 --- a/test/helper.js +++ b/test/helper.js @@ -1,4 +1,4 @@ -var pg = require('pg.js') +var pg = require('pg') module.exports = function(name, cb) { describe(name, function() { var client = new pg.Client() diff --git a/test/issue-3.js b/test/issue-3.js index 0c822c973..302927d2f 100644 --- a/test/issue-3.js +++ b/test/issue-3.js @@ -1,4 +1,4 @@ -var pg = require('pg.js') +var pg = require('pg') var QueryStream = require('../') describe('end semantics race condition', function() { before(function(done) { diff --git a/test/mocha.opts b/test/mocha.opts index 8dcb4d8d9..46e8e69d9 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1 +1,2 @@ --no-exit +--bail diff --git a/test/stream-tester-timestamp.js b/test/stream-tester-timestamp.js index d62dd5669..c9c2b212e 100644 --- a/test/stream-tester-timestamp.js +++ b/test/stream-tester-timestamp.js @@ -1,4 +1,4 @@ -var pg = require('pg.js') +var pg = require('pg') var QueryStream = require('../') var spec = require('stream-spec') var assert = require('assert') @@ -10,20 +10,20 @@ require('./helper')('stream tester timestamp', function(client) { var stream = new QueryStream(sql, []) var ended = false var query = client.query(stream) - query. - on('end', function() { ended = true }) + query.on('end', function() { ended = true }) spec(query) .readable() - .pausable({strict: true}) - .validateOnExit() - ; + .pausable({ strict: true }) + .validateOnExit(); var checkListeners = function() { assert(stream.listeners('end').length < 10) - if (!ended) + if (!ended) { setImmediate(checkListeners) - else + } + else { done() + } } checkListeners() }) -}) \ No newline at end of file +}) From 796d1413866a59b635c4375e703c4a2dd9709ecb Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 6 Aug 2017 11:28:37 -0500 Subject: [PATCH 0301/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ea99f0f8e..c5e7f32a1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "1.2.2", + "version": "1.3.0", "description": "", "main": "index.js", "directories": { From b1f8f8d60df7794a6f05409b5ce6c0315a87c47b Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 6 Aug 2017 11:59:47 -0500 Subject: [PATCH 0302/1037] Eslint --- .eslintrc | 9 + index.js | 13 +- package.json | 8 +- test/close.js | 44 +- test/concat.js | 10 +- test/error.js | 10 +- test/fast-reader.js | 17 +- test/helper.js | 8 +- test/instant.js | 6 +- test/issue-3.js | 12 +- test/pauses.js | 8 +- test/slow-reader.js | 21 +- test/stream-tester-timestamp.js | 15 +- test/stream-tester.js | 11 +- yarn.lock | 1315 +++++++++++++++++++++++++++++++ 15 files changed, 1413 insertions(+), 94 deletions(-) create mode 100644 .eslintrc create mode 100644 yarn.lock diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 000000000..95f4d0c65 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,9 @@ +{ + "extends": "standard", + "env": { + "mocha": true + }, + "rules": { + "no-new-func": "off" + } +} diff --git a/index.js b/index.js index 6665b6b04..9b0d16172 100644 --- a/index.js +++ b/index.js @@ -1,10 +1,9 @@ -'use strict'; -var util = require('util') +'use strict' var Cursor = require('pg-cursor') var Readable = require('stream').Readable class PgQueryStream extends Readable { - constructor(text, values, options) { + constructor (text, values, options) { super(Object.assign({ objectMode: true }, options)) this.cursor = new Cursor(text, values) this._reading = false @@ -20,18 +19,18 @@ class PgQueryStream extends Readable { this.handleError = this.cursor.handleError.bind(this.cursor) } - submit(connection) { + submit (connection) { this.cursor.submit(connection) return this } - close(callback) { + close (callback) { this._closed = true const cb = callback || (() => this.emit('close')) this.cursor.close(cb) } - _read(size) { + _read (size) { if (this._reading || this._closed) { return false } @@ -53,7 +52,7 @@ class PgQueryStream extends Readable { // push each row into the stream this._reading = false - for(var i = 0; i < rows.length; i++) { + for (var i = 0; i < rows.length; i++) { this.push(rows[i]) } }) diff --git a/package.json b/package.json index 5f0e0a3fc..976f9e579 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,8 @@ "devDependencies": { "JSONStream": "~0.7.1", "concat-stream": "~1.0.1", + "eslint": "^4.4.0", + "eslint-config-standard": "^10.2.1", "mocha": "^3.5.0", "pg": "6.x", "stream-spec": "~0.3.5", @@ -31,6 +33,10 @@ "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "1.2.1" + "eslint-plugin-import": "^2.7.0", + "eslint-plugin-node": "^5.1.1", + "eslint-plugin-promise": "^3.5.0", + "eslint-plugin-standard": "^3.0.1", + "pg-cursor": "1.3.0" } } diff --git a/test/close.js b/test/close.js index a8820c13e..be103c7f6 100644 --- a/test/close.js +++ b/test/close.js @@ -1,33 +1,31 @@ var assert = require('assert') var concat = require('concat-stream') -var tester = require('stream-tester') -var JSONStream = require('JSONStream') var QueryStream = require('../') var helper = require('./helper') -helper('close', function(client) { - it('emits close', function(done) { +helper('close', function (client) { + it('emits close', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], {batchSize: 2, highWaterMark: 2}) var query = client.query(stream) - query.pipe(concat(function() {})) + query.pipe(concat(function () {})) query.on('close', done) }) }) -helper('early close', function(client) { - it('can be closed early', function(done) { +helper('early close', function (client) { + it('can be closed early', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [20000], {batchSize: 2, highWaterMark: 2}) var query = client.query(stream) var readCount = 0 - query.on('readable', function() { + query.on('readable', function () { readCount++ query.read() }) - query.once('readable', function() { + query.once('readable', function () { query.close() }) - query.on('close', function() { + query.on('close', function () { assert(readCount < 10, 'should not have read more than 10 rows') done() }) @@ -36,19 +34,19 @@ helper('early close', function(client) { helper('close callback', function (client) { it('notifies an optional callback when the conneciton is closed', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [10], {batchSize: 2, highWaterMark: 2}); - var query = client.query(stream); - query.once('readable', function() { // only reading once - query.read(); - }); - query.once('readable', function() { + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [10], {batchSize: 2, highWaterMark: 2}) + var query = client.query(stream) + query.once('readable', function () { // only reading once + query.read() + }) + query.once('readable', function () { query.close(function () { // nothing to assert. This test will time out if the callback does not work. - done(); - }); - }); + done() + }) + }) query.on('close', function () { - assert(false, "close event should not fire"); // no close event because we did not read to the end of the stream. - }); - }); -}); + assert(false, 'close event should not fire') // no close event because we did not read to the end of the stream. + }) + }) +}) diff --git a/test/concat.js b/test/concat.js index 8e6bf5d97..78a633be2 100644 --- a/test/concat.js +++ b/test/concat.js @@ -5,14 +5,14 @@ var helper = require('./helper') var QueryStream = require('../') -helper('concat', function(client) { - it('concats correctly', function(done) { +helper('concat', function (client) { + it('concats correctly', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) - query.pipe(through(function(row) { + query.pipe(through(function (row) { this.push(row.num) - })).pipe(concat(function(result) { - var total = result.reduce(function(prev, cur) { + })).pipe(concat(function (result) { + var total = result.reduce(function (prev, cur) { return prev + cur }) assert.equal(total, 20100) diff --git a/test/error.js b/test/error.js index b3ef8f1eb..1e6030d5d 100644 --- a/test/error.js +++ b/test/error.js @@ -3,20 +3,20 @@ var helper = require('./helper') var QueryStream = require('../') -helper('error', function(client) { - it('receives error on stream', function(done) { +helper('error', function (client) { + it('receives error on stream', function (done) { var stream = new QueryStream('SELECT * FROM asdf num', []) var query = client.query(stream) - query.on('error', function(err) { + query.on('error', function (err) { assert(err) assert.equal(err.code, '42P01') done() }).on('data', function () { - //noop to kick of reading + // noop to kick of reading }) }) - it('continues to function after stream', function(done) { + it('continues to function after stream', function (done) { client.query('SELECT NOW()', done) }) }) diff --git a/test/fast-reader.js b/test/fast-reader.js index a99326d73..5190f10d2 100644 --- a/test/fast-reader.js +++ b/test/fast-reader.js @@ -2,27 +2,26 @@ var assert = require('assert') var helper = require('./helper') var QueryStream = require('../') -helper('fast reader', function(client) { - it('works', function(done) { +helper('fast reader', function (client) { + it('works', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) var result = [] - var count = 0 - stream.on('readable', function() { + stream.on('readable', function () { var res = stream.read() if (result.length !== 201) { assert(res, 'should not return null on evented reader') } else { - //a readable stream will emit a null datum when it finishes being readable - //https://nodejs.org/api/stream.html#stream_event_readable + // a readable stream will emit a null datum when it finishes being readable + // https://nodejs.org/api/stream.html#stream_event_readable assert.equal(res, null) } - if(res) { + if (res) { result.push(res.num) } }) - stream.on('end', function() { - var total = result.reduce(function(prev, cur) { + stream.on('end', function () { + var total = result.reduce(function (prev, cur) { return prev + cur }) assert.equal(total, 20100) diff --git a/test/helper.js b/test/helper.js index f4e427203..ad21d6ea2 100644 --- a/test/helper.js +++ b/test/helper.js @@ -1,15 +1,15 @@ var pg = require('pg') -module.exports = function(name, cb) { - describe(name, function() { +module.exports = function (name, cb) { + describe(name, function () { var client = new pg.Client() - before(function(done) { + before(function (done) { client.connect(done) }) cb(client) - after(function(done) { + after(function (done) { client.end() client.on('end', done) }) diff --git a/test/instant.js b/test/instant.js index dd36fbca8..49ab0b07d 100644 --- a/test/instant.js +++ b/test/instant.js @@ -3,11 +3,11 @@ var concat = require('concat-stream') var QueryStream = require('../') -require('./helper')('instant', function(client) { - it('instant', function(done) { +require('./helper')('instant', function (client) { + it('instant', function (done) { var query = new QueryStream('SELECT pg_sleep(1)', []) var stream = client.query(query) - stream.pipe(concat(function(res) { + stream.pipe(concat(function (res) { assert.equal(res.length, 1) done() })) diff --git a/test/issue-3.js b/test/issue-3.js index 302927d2f..7b467a3b3 100644 --- a/test/issue-3.js +++ b/test/issue-3.js @@ -1,7 +1,7 @@ var pg = require('pg') var QueryStream = require('../') -describe('end semantics race condition', function() { - before(function(done) { +describe('end semantics race condition', function () { + before(function (done) { var client = new pg.Client() client.connect() client.on('drain', client.end.bind(client)) @@ -9,20 +9,20 @@ describe('end semantics race condition', function() { client.query('create table IF NOT EXISTS p(id serial primary key)') client.query('create table IF NOT EXISTS c(id int primary key references p)') }) - it('works', function(done) { + it('works', function (done) { var client1 = new pg.Client() client1.connect() var client2 = new pg.Client() client2.connect() - var qr = new QueryStream("INSERT INTO p DEFAULT VALUES RETURNING id") + var qr = new QueryStream('INSERT INTO p DEFAULT VALUES RETURNING id') client1.query(qr) var id = null - qr.on('data', function(row) { + qr.on('data', function (row) { id = row.id }) qr.on('end', function () { - client2.query("INSERT INTO c(id) VALUES ($1)", [id], function (err, rows) { + client2.query('INSERT INTO c(id) VALUES ($1)', [id], function (err, rows) { client1.end() client2.end() done(err) diff --git a/test/pauses.js b/test/pauses.js index 181f3c29f..8d9beb02c 100644 --- a/test/pauses.js +++ b/test/pauses.js @@ -1,16 +1,16 @@ -var assert = require('assert') var concat = require('concat-stream') var tester = require('stream-tester') var JSONStream = require('JSONStream') var QueryStream = require('../') -require('./helper')('pauses', function(client) { - it('pauses', function(done) { +require('./helper')('pauses', function (client) { + it('pauses', function (done) { + this.timeout(5000) var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], {batchSize: 2, highWaterMark: 2}) var query = client.query(stream) var pauser = tester.createPauseStream(0.1, 100) - query.pipe(JSONStream.stringify()).pipe(concat(function(json) { + query.pipe(JSONStream.stringify()).pipe(pauser).pipe(concat(function (json) { JSON.parse(json) done() })) diff --git a/test/slow-reader.js b/test/slow-reader.js index b9675a368..c95574a7a 100644 --- a/test/slow-reader.js +++ b/test/slow-reader.js @@ -1,4 +1,3 @@ -var assert = require('assert') var helper = require('./helper') var QueryStream = require('../') var concat = require('concat-stream') @@ -7,22 +6,20 @@ var Transform = require('stream').Transform var mapper = new Transform({objectMode: true}) -mapper._transform = function(obj, enc, cb) { - this.push(obj) - setTimeout(cb, 5) +mapper._transform = function (obj, enc, cb) { + this.push(obj) + setTimeout(cb, 5) } -helper('slow reader', function(client) { - it('works', function(done) { +helper('slow reader', function (client) { + it('works', function (done) { this.timeout(50000) var stream = new QueryStream('SELECT * FROM generate_series(0, 201) num', [], {highWaterMark: 100, batchSize: 50}) - stream.on('end', function() { - //console.log('stream end') + stream.on('end', function () { + // console.log('stream end') }) - var query = client.query(stream) - var result = [] - var count = 0 - stream.pipe(mapper).pipe(concat(function(res) { + client.query(stream) + stream.pipe(mapper).pipe(concat(function (res) { done() })) }) diff --git a/test/stream-tester-timestamp.js b/test/stream-tester-timestamp.js index c9c2b212e..7a31b4ecc 100644 --- a/test/stream-tester-timestamp.js +++ b/test/stream-tester-timestamp.js @@ -1,26 +1,23 @@ -var pg = require('pg') var QueryStream = require('../') var spec = require('stream-spec') var assert = require('assert') -require('./helper')('stream tester timestamp', function(client) { - it('should not warn about max listeners', function(done) { +require('./helper')('stream tester timestamp', function (client) { + it('should not warn about max listeners', function (done) { var sql = 'SELECT * FROM generate_series(\'1983-12-30 00:00\'::timestamp, \'2013-12-30 00:00\', \'1 years\')' - var result = [] var stream = new QueryStream(sql, []) var ended = false var query = client.query(stream) - query.on('end', function() { ended = true }) + query.on('end', function () { ended = true }) spec(query) .readable() .pausable({ strict: true }) - .validateOnExit(); - var checkListeners = function() { + .validateOnExit() + var checkListeners = function () { assert(stream.listeners('end').length < 10) if (!ended) { setImmediate(checkListeners) - } - else { + } else { done() } } diff --git a/test/stream-tester.js b/test/stream-tester.js index a00125f25..826565813 100644 --- a/test/stream-tester.js +++ b/test/stream-tester.js @@ -1,16 +1,15 @@ -var tester = require('stream-tester') var spec = require('stream-spec') var QueryStream = require('../') -require('./helper')('stream tester', function(client) { - it('passes stream spec', function(done) { +require('./helper')('stream tester', function (client) { + it('passes stream spec', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) spec(query) - .readable() - .pausable({strict: true}) - .validateOnExit() + .readable() + .pausable({strict: true}) + .validateOnExit() stream.on('end', done) }) }) diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..938fda8ee --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1315 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +JSONStream@~0.7.1: + version "0.7.4" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-0.7.4.tgz#734290e41511eea7c2cfe151fbf9a563a97b9786" + dependencies: + jsonparse "0.0.5" + through ">=2.2.7 <3" + +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + dependencies: + acorn "^3.0.4" + +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + +acorn@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.1.tgz#53fe161111f912ab999ee887a90a0bc52822fd75" + +ajv-keywords@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + +ajv@^4.7.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +ajv@^5.2.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.2.tgz#47c68d69e86f5d953103b0074a9430dc63da5e39" + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + json-schema-traverse "^0.3.0" + json-stable-stringify "^1.0.1" + +ansi-escapes@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + +ansi-styles@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + dependencies: + color-convert "^1.9.0" + +ap@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" + +argparse@^1.0.7: + version "1.0.9" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + dependencies: + sprintf-js "~1.0.2" + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + +arrify@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + +assertions@~2.3.0: + version "2.3.4" + resolved "https://registry.yarnpkg.com/assertions/-/assertions-2.3.4.tgz#a9433ced1fce57cc999af0965d1008e96c2796e6" + dependencies: + fomatto "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6" + render "0.1" + traverser "1" + +babel-code-frame@^6.22.0: + version "6.22.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" + dependencies: + chalk "^1.1.0" + esutils "^2.0.2" + js-tokens "^3.0.0" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + +base64-js@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.2.tgz#024f0f72afa25b75f9c0ee73cd4f55ec1bed9784" + +bops@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/bops/-/bops-0.0.6.tgz#082d1d55fa01e60dbdc2ebc2dba37f659554cf3a" + dependencies: + base64-js "0.0.2" + to-utf8 "0.0.1" + +brace-expansion@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + +buffer-writer@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-1.0.1.tgz#22a936901e3029afcd7547eb4487ceb697a3bf08" + +builtin-modules@^1.0.0, builtin-modules@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + +chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.0.1.tgz#dbec49436d2ae15f536114e76d14656cdbc0f44d" + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + dependencies: + restore-cursor "^2.0.0" + +cli-width@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" + +co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + +color-convert@^1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" + dependencies: + color-name "^1.1.1" + +color-name@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + +commander@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + dependencies: + graceful-readlink ">= 1.0.0" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + +concat-stream@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" + dependencies: + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +concat-stream@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.0.1.tgz#018b18bc1c7d073a2dc82aa48442341a2c4dd79f" + dependencies: + bops "0.0.6" + +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +curry@0.0.x: + version "0.0.4" + resolved "https://registry.yarnpkg.com/curry/-/curry-0.0.4.tgz#1750d518d919c44f3d37ff44edc693de1f0d5fcb" + +debug@2.6.8, debug@^2.6.8: + version "2.6.8" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" + dependencies: + ms "2.0.0" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + +del@^2.0.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" + dependencies: + globby "^5.0.0" + is-path-cwd "^1.0.0" + is-path-in-cwd "^1.0.0" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + rimraf "^2.2.8" + +diff@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" + +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +doctrine@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +error-ex@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" + dependencies: + is-arrayish "^0.2.1" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + +eslint-config-standard@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591" + +eslint-import-resolver-node@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz#4422574cde66a9a7b099938ee4d508a199e0e3cc" + dependencies: + debug "^2.6.8" + resolve "^1.2.0" + +eslint-module-utils@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449" + dependencies: + debug "^2.6.8" + pkg-dir "^1.0.0" + +eslint-plugin-import@^2.7.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.7.0.tgz#21de33380b9efb55f5ef6d2e210ec0e07e7fa69f" + dependencies: + builtin-modules "^1.1.1" + contains-path "^0.1.0" + debug "^2.6.8" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.1" + eslint-module-utils "^2.1.1" + has "^1.0.1" + lodash.cond "^4.3.0" + minimatch "^3.0.3" + read-pkg-up "^2.0.0" + +eslint-plugin-node@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.1.1.tgz#a7ed956e780c22aef6afd1116005acd82f26eac6" + dependencies: + ignore "^3.3.3" + minimatch "^3.0.4" + resolve "^1.3.3" + semver "5.3.0" + +eslint-plugin-promise@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca" + +eslint-plugin-standard@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2" + +eslint-scope@^3.7.1: + version "3.7.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.4.0.tgz#a3e153e704b64f78290ef03592494eaba228d3bc" + dependencies: + ajv "^5.2.0" + babel-code-frame "^6.22.0" + chalk "^1.1.3" + concat-stream "^1.6.0" + cross-spawn "^5.1.0" + debug "^2.6.8" + doctrine "^2.0.0" + eslint-scope "^3.7.1" + espree "^3.5.0" + esquery "^1.0.0" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^9.17.0" + ignore "^3.3.3" + imurmurhash "^0.1.4" + inquirer "^3.0.6" + is-resolvable "^1.0.0" + js-yaml "^3.9.1" + json-stable-stringify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.4" + minimatch "^3.0.2" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + pluralize "^4.0.0" + progress "^2.0.0" + require-uncached "^1.0.3" + semver "^5.3.0" + strip-json-comments "~2.0.1" + table "^4.0.1" + text-table "~0.2.0" + +espree@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.0.tgz#98358625bdd055861ea27e2867ea729faf463d8d" + dependencies: + acorn "^5.1.1" + acorn-jsx "^3.0.0" + +esprima@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + +esquery@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" + dependencies: + estraverse "^4.1.0" + object-assign "^4.0.1" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" + +esutils@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + +external-editor@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972" + dependencies: + iconv-lite "^0.4.17" + jschardet "^1.4.2" + tmp "^0.0.31" + +fast-deep-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + dependencies: + locate-path "^2.0.0" + +flat-cache@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" + dependencies: + circular-json "^0.3.1" + del "^2.0.2" + graceful-fs "^4.1.2" + write "^0.2.1" + +"fomatto@git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6": + version "0.6.0" + resolved "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6" + +from@~0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/from/-/from-0.0.2.tgz#7fffac647a2f99b20d57b8e28379455cbb4189d0" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + +function-bind@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + +generic-pool@2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.4.3.tgz#780c36f69dfad05a5a045dd37be7adca11a4f6ff" + +glob@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^9.17.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + +globby@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" + dependencies: + array-union "^1.0.1" + arrify "^1.0.0" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +graceful-fs@^4.1.2: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" + +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + +growl@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + dependencies: + ansi-regex "^2.0.0" + +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + +has@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" + dependencies: + function-bind "^1.0.2" + +hosted-git-info@^2.1.4: + version "2.5.0" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" + +iconv-lite@^0.4.17: + version "0.4.18" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" + +ignore@^3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + +inquirer@^3.0.6: + version "3.2.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.2.1.tgz#06ceb0f540f45ca548c17d6840959878265fa175" + dependencies: + ansi-escapes "^2.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.4" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + +is-builtin-module@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" + dependencies: + builtin-modules "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +is-path-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" + +is-path-in-cwd@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" + dependencies: + is-path-inside "^1.0.0" + +is-path-inside@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" + dependencies: + path-is-inside "^1.0.1" + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + +is-resolvable@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" + dependencies: + tryit "^1.0.1" + +isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +js-tokens@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + +js-yaml@^3.9.1: + version "3.9.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0" + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jschardet@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.5.0.tgz#a61f310306a5a71188e1b1acd08add3cfbb08b1e" + +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + +json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + dependencies: + jsonify "~0.0.0" + +json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + +jsonparse@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-0.0.5.tgz#330542ad3f0a654665b778f3eb2d9a9fa507ac64" + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +lodash._baseassign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" + dependencies: + lodash._basecopy "^3.0.0" + lodash.keys "^3.0.0" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + +lodash._basecreate@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + +lodash.cond@^4.3.0: + version "4.5.2" + resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" + +lodash.create@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" + dependencies: + lodash._baseassign "^3.0.0" + lodash._basecreate "^3.0.0" + lodash._isiterateecall "^3.0.0" + +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + +lodash@^4.0.0, lodash@^4.17.4, lodash@^4.3.0: + version "4.17.4" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" + +lru-cache@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +macgyver@~1.10: + version "1.10.1" + resolved "https://registry.yarnpkg.com/macgyver/-/macgyver-1.10.1.tgz#b09d1599d8b36ed5b16f59589515d9d14bc2fd88" + +mimic-fn@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" + +minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + +mkdirp@0.5.1, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + dependencies: + minimist "0.0.8" + +mocha@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.0.tgz#1328567d2717f997030f8006234bce9b8cd72465" + dependencies: + browser-stdout "1.3.0" + commander "2.9.0" + debug "2.6.8" + diff "3.2.0" + escape-string-regexp "1.0.5" + glob "7.1.1" + growl "1.9.2" + json3 "3.3.2" + lodash.create "3.1.1" + mkdirp "0.5.1" + supports-color "3.1.2" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + +normalize-package-data@^2.3.2: + version "2.4.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" + dependencies: + hosted-git-info "^2.1.4" + is-builtin-module "^1.0.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +object-assign@4.1.0, object-assign@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + dependencies: + mimic-fn "^1.0.0" + +optionator@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +os-tmpdir@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + +p-limit@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + dependencies: + p-limit "^1.1.0" + +packet-reader@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.3.1.tgz#cd62e60af8d7fea8a705ec4ff990871c46871f27" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + dependencies: + error-ex "^1.2.0" + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + +path-is-inside@^1.0.1, path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + +path-parse@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + dependencies: + pify "^2.0.0" + +pg-connection-string@0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" + +pg-cursor@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/pg-cursor/-/pg-cursor-1.3.0.tgz#b220f1908976b7b40daa373c7ada5fca823ab0d9" + +pg-pool@1.*: + version "1.8.0" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-1.8.0.tgz#f7ec73824c37a03f076f51bfdf70e340147c4f37" + dependencies: + generic-pool "2.4.3" + object-assign "4.1.0" + +pg-types@1.*: + version "1.12.0" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-1.12.0.tgz#8ad3b7b897e3fd463e62de241ad5fc640b4a66f0" + dependencies: + ap "~0.2.0" + postgres-array "~1.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.0" + postgres-interval "^1.1.0" + +pg@6.x: + version "6.4.1" + resolved "https://registry.yarnpkg.com/pg/-/pg-6.4.1.tgz#3eabd8ca056814437c769f17ff7a0c36ac7023c5" + dependencies: + buffer-writer "1.0.1" + packet-reader "0.3.1" + pg-connection-string "0.1.3" + pg-pool "1.*" + pg-types "1.*" + pgpass "1.*" + semver "4.3.2" + +pgpass@1.*: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" + dependencies: + split "^1.0.0" + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + +pkg-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" + dependencies: + find-up "^1.0.0" + +pluralize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762" + +postgres-array@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-1.0.2.tgz#8e0b32eb03bf77a5c0a7851e0441c169a256a238" + +postgres-bytea@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + +postgres-date@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.3.tgz#e2d89702efdb258ff9d9cee0fe91bd06975257a8" + +postgres-interval@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.1.1.tgz#acdb0f897b4b1c6e496d9d4e0a853e1c428f06f0" + dependencies: + xtend "^4.0.0" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + +process-nextick-args@~1.0.6: + version "1.0.7" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + +progress@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +readable-stream@^2.2.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + safe-buffer "~5.1.1" + string_decoder "~1.0.3" + util-deprecate "~1.0.1" + +render@0.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/render/-/render-0.1.4.tgz#cfb33a34e26068591d418469e23d8cc5ce1ceff5" + dependencies: + traverser "0.0.x" + +require-uncached@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + +resolve@^1.2.0, resolve@^1.3.3: + version "1.4.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" + dependencies: + path-parse "^1.0.5" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +rimraf@^2.2.8: + version "2.6.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" + dependencies: + glob "^7.0.5" + +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + dependencies: + is-promise "^2.1.0" + +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" + +"semver@2 || 3 || 4 || 5", semver@5.3.0, semver@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + +semver@4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + +signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + +spdx-correct@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" + dependencies: + spdx-license-ids "^1.0.2" + +spdx-expression-parse@~1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" + +spdx-license-ids@^1.0.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" + +split@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" + dependencies: + through "2" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + +stream-spec@~0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/stream-spec/-/stream-spec-0.3.6.tgz#2fddac4a07bf3e9f8963c677a6b5a6cc2115255e" + dependencies: + macgyver "~1.10" + +stream-tester@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stream-tester/-/stream-tester-0.0.5.tgz#4f86f2531149adaf6dd4b3ff262edf64ae9a171a" + dependencies: + assertions "~2.3.0" + from "~0.0.2" + through "~0.0.3" + +string-width@^2.0.0, string-width@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +supports-color@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" + dependencies: + has-flag "^1.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + +supports-color@^4.0.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.1.tgz#65a4bb2631e90e02420dba5554c375a4754bb836" + dependencies: + has-flag "^2.0.0" + +table@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.1.tgz#a8116c133fac2c61f4a420ab6cdf5c4d61f0e435" + dependencies: + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.0.0" + +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + +through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3.4: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + +through@~0.0.3: + version "0.0.4" + resolved "https://registry.yarnpkg.com/through/-/through-0.0.4.tgz#0bf2f0fffafaac4bacbc533667e98aad00b588c8" + +tmp@^0.0.31: + version "0.0.31" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" + dependencies: + os-tmpdir "~1.0.1" + +to-utf8@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/to-utf8/-/to-utf8-0.0.1.tgz#d17aea72ff2fba39b9e43601be7b3ff72e089852" + +traverser@0.0.x: + version "0.0.5" + resolved "https://registry.yarnpkg.com/traverser/-/traverser-0.0.5.tgz#c66f38c456a0c21a88014b1223580c7ebe0631eb" + dependencies: + curry "0.0.x" + +traverser@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/traverser/-/traverser-1.0.0.tgz#6f59e5813759aeeab3646b8f4513fd4a62e4fe20" + dependencies: + curry "0.0.x" + +tryit@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + dependencies: + prelude-ls "~1.1.2" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +validate-npm-package-license@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" + dependencies: + spdx-correct "~1.0.0" + spdx-expression-parse "~1.0.0" + +which@^1.2.9: + version "1.3.0" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" + dependencies: + isexe "^2.0.0" + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + dependencies: + mkdirp "^0.5.1" + +xtend@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" From 465ac5caf3e27e56e0673139429d3c55a2fb5a08 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 6 Aug 2017 12:42:19 -0500 Subject: [PATCH 0303/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 976f9e579..96dd723d2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "1.0.0", + "version": "1.1.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From fb495866642a707979a2b791f9f0e90081de2dea Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 7 Aug 2017 10:08:25 -0500 Subject: [PATCH 0304/1037] Update SPONSORS.md Add John Fawcett as a supporter --- SPONSORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SPONSORS.md b/SPONSORS.md index 81c1db64a..80e978941 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -1,3 +1,4 @@ # Leaders # Supporters +- John Fawcett From 8a2ba46ec153073b613375d41a608b7fac8214dc Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 7 Aug 2017 10:53:14 -0500 Subject: [PATCH 0305/1037] Update SPONSORS.md --- SPONSORS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SPONSORS.md b/SPONSORS.md index 80e978941..aeb1acf99 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -1,3 +1,5 @@ +node-postgres is made possible by the helpful contributors from the community well as the following generous supporters on [Patreon](https://www.patreon.com/node_postgres). + # Leaders # Supporters From c0f55183418cd97570960345e8e7c69233426c9b Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 8 Aug 2017 11:24:06 -0500 Subject: [PATCH 0306/1037] Update README.md Add link to updated documentation --- README.md | 70 ++----------------------------------------------------- 1 file changed, 2 insertions(+), 68 deletions(-) diff --git a/README.md b/README.md index fe79bf74b..1b01b3d83 100644 --- a/README.md +++ b/README.md @@ -3,74 +3,6 @@ node-pg-cursor Use a PostgreSQL result cursor from node with an easy to use API. -### why? - -Sometimes you need to iterate through a table in chunks. It's extremely inefficient to use hand-crafted `LIMIT` and `OFFSET` queries to do this. -PostgreSQL provides built-in functionality to fetch a "cursor" to your results and page through the cursor efficiently fetching chunks of the results with full MVCC compliance. - -This actually ends up pairing very nicely with node's _asyncness_ and handling a lot of data. PostgreSQL is rad. - -### example - -```js -var Cursor = require('pg-cursor') -var pg = require('pg') - -pg.connect(function(err, client, done) { - - //imagine some_table has 30,000,000 results where prop > 100 - //lets create a query cursor to efficiently deal with the huge result set - var cursor = client.query(new Cursor('SELECT * FROM some_table WHERE prop > $1', [100])) - - //read the first 100 rows from this cursor - cursor.read(100, function(err, rows) { - if(err) { - //cursor error - release the client - //normally you'd do app-specific error handling here - return done(err) - } - - //when the cursor is exhausted and all rows have been returned - //all future calls to `cursor#read` will return an empty row array - //so if we received no rows, release the client and be done - if(!rows.length) return done() - - //do something with your rows - //when you're ready, read another chunk from - //your result - - - cursor.read(2000, function(err, rows) { - //I think you get the picture, yeah? - //if you dont...open an issue - I'd love to help you out! - - //Also - you probably want to use some sort of async or promise library to deal with paging - //through your cursor results. node-pg-cursor makes no asumptions for you on that front. - }) - }) -}); -``` - -### api - -#### var Cursor = require('pg-cursor') - -#### constructor Cursor(string queryText, array queryParameters) - -Creates an instance of a query cursor. Pass this instance to node-postgres [`client#query`](https://github.com/brianc/node-postgres/wiki/Client#wiki-method-query-parameterized) - -#### cursor#read(int rowCount, function callback(Error err, Array rows, Result result) - -Read `rowCount` rows from the cursor instance. The `callback` will be called when the rows are available, loaded into memory, parsed, and converted to JavaScript types. - -If the cursor has read to the end of the result sets all subsequent calls to `cursor#read` will return a 0 length array of rows. I'm open to other ways to signal the end of a cursor, but this has worked out well for me so far. - -`result` is a special [https://github.com/brianc/node-postgres/wiki/Query#result-object](Result) object that can be used to accumulate rows. - -#### cursor#close(function callback(Error err)) - -Closes the backend portal before itterating through the entire result set. Useful when you want to 'abort' out of a read early but continue to use the same client for other queries after the cursor is finished. - ### install ```sh @@ -78,6 +10,8 @@ $ npm install pg-cursor ``` ___note___: this depends on _either_ `npm install pg` or `npm install pg.js`, but you __must__ be using the pure JavaScript client. This will __not work__ with the native bindings. +### :star: [Documentation](https://node-postgres.com/api/cursor) :star: + ### license The MIT License (MIT) From b518617562779f6900688aeeeeaebd92d69066cd Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 8 Aug 2017 11:26:19 -0500 Subject: [PATCH 0307/1037] Update SPONSORS.md --- SPONSORS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SPONSORS.md b/SPONSORS.md index aeb1acf99..b82d856dc 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -4,3 +4,5 @@ node-postgres is made possible by the helpful contributors from the community we # Supporters - John Fawcett +- Lalit Kapoor [@lalitkapoor](https://twitter.com/lalitkapoor) +- Paul Frazee [@pfrazee](https://twitter.com/pfrazee) From 17e19e55a0c0f622af329e520096ad57d3e7f551 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 9 Aug 2017 09:53:42 -0500 Subject: [PATCH 0308/1037] Move eslint to dev dependencies --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 96dd723d2..6f45bf7fa 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,10 @@ "concat-stream": "~1.0.1", "eslint": "^4.4.0", "eslint-config-standard": "^10.2.1", + "eslint-plugin-import": "^2.7.0", + "eslint-plugin-node": "^5.1.1", + "eslint-plugin-promise": "^3.5.0", + "eslint-plugin-standard": "^3.0.1", "mocha": "^3.5.0", "pg": "6.x", "stream-spec": "~0.3.5", @@ -33,10 +37,6 @@ "through": "~2.3.4" }, "dependencies": { - "eslint-plugin-import": "^2.7.0", - "eslint-plugin-node": "^5.1.1", - "eslint-plugin-promise": "^3.5.0", - "eslint-plugin-standard": "^3.0.1", "pg-cursor": "1.3.0" } } From e762b48e484866e79181d95fdc93561f1cede0f8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 9 Aug 2017 10:35:22 -0500 Subject: [PATCH 0309/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6f45bf7fa..06915ad9f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "1.1.0", + "version": "1.1.1", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From 53584b704ac63466876ecec4a4bb9dead3835d6e Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 10 Aug 2017 00:20:56 -0500 Subject: [PATCH 0310/1037] Add connection & query timeout if all clients are checked out (#70) * Add connection & query timeout if all clients are checked out This addresses [pg#1390](https://github.com/brianc/node-postgres/issues/1390). Ensure connection timeout applies both for new connections and on an exhuasted pool. I also made the library return an error when passing a function as the first param to `pool.query` - previosuly this threw a sync type error. * Add pg-cursor to dev deps --- index.js | 32 +++++++++++++++++++++++++- package.json | 3 ++- test/connection-timeout.js | 47 +++++++++++++++++++++++++++++++++++++- test/error-handling.js | 11 +++++++++ test/submittable.js | 19 +++++++++++++++ 5 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 test/submittable.js diff --git a/index.js b/index.js index 49d797be2..46c399f9c 100644 --- a/index.js +++ b/index.js @@ -128,14 +128,34 @@ class Pool extends EventEmitter { 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 - this._pendingQueue.push(response.callback) + // 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 } @@ -199,6 +219,16 @@ class Pool extends EventEmitter { } 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 diff --git a/package.json b/package.json index a0ebd92bb..192a64ed9 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "test": "test" }, "scripts": { - "test": "node_modules/.bin/standard && node_modules/.bin/mocha" + "test": " node_modules/.bin/mocha && node_modules/.bin/standard" }, "repository": { "type": "git", @@ -32,6 +32,7 @@ "lodash": "4.13.1", "mocha": "^2.3.3", "pg": "*", + "pg-cursor": "^1.3.0", "standard": "7.1.2", "standard-format": "2.2.1" }, diff --git a/test/connection-timeout.js b/test/connection-timeout.js index 0671b1120..8f3239b30 100644 --- a/test/connection-timeout.js +++ b/test/connection-timeout.js @@ -58,5 +58,50 @@ describe('connection timeout', () => { } 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) + }) + }) + }) + }) +}) diff --git a/test/error-handling.js b/test/error-handling.js index de68fad32..9435dd7fc 100644 --- a/test/error-handling.js +++ b/test/error-handling.js @@ -112,6 +112,17 @@ describe('pool error handling', function () { })) }) + 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 }) diff --git a/test/submittable.js b/test/submittable.js new file mode 100644 index 000000000..7a1574d46 --- /dev/null +++ b/test/submittable.js @@ -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) + }) + }) +}) From c3417e95ebf669bd8617a1382f2eb5f09e0239c4 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Thu, 10 Aug 2017 00:21:10 -0500 Subject: [PATCH 0311/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 192a64ed9..9711973e5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "2.0.1", + "version": "2.0.2", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From 4e3522634034ed954b8521b528088e4610101421 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Thu, 10 Aug 2017 14:00:49 +0000 Subject: [PATCH 0312/1037] Fix client remove clearing unrelated idle timers (#71) * Add failing test for idle timer continuation after removal * Clear idle timeout only for removed client * Copy list of idle clients for modification during iteration --- index.js | 23 ++++++++++++++++++----- test/idle-timeout.js | 25 +++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index 46c399f9c..af86134b4 100644 --- a/index.js +++ b/index.js @@ -3,6 +3,14 @@ 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 @@ -80,7 +88,7 @@ class Pool extends EventEmitter { if (this.ending) { this.log('pulse queue on ending') if (this._idle.length) { - this._idle.map(item => { + this._idle.slice().map(item => { this._remove(item.client) }) } @@ -114,10 +122,15 @@ class Pool extends EventEmitter { } _remove (client) { - this._idle = this._idle.filter(item => { - clearTimeout(item.timeoutId) - return item.client !== 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) diff --git a/test/idle-timeout.js b/test/idle-timeout.js index 68a2b78a0..a24ab7b06 100644 --- a/test/idle-timeout.js +++ b/test/idle-timeout.js @@ -20,6 +20,31 @@ describe('idle timeout', () => { }) }) + 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 = [] From 4d7734a71122cbbe1bb81bb466430e96f3405394 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Thu, 10 Aug 2017 09:01:31 -0500 Subject: [PATCH 0313/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9711973e5..17740db2d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "2.0.2", + "version": "2.0.3", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From 48543bfad08d8be9e1fadacafdaf4405556ee556 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 12 Aug 2017 16:04:29 -0500 Subject: [PATCH 0314/1037] Fix vulnerability --- lib/result.js | 3 ++- package.json | 1 + test/integration/client/field-name-escape-tests.js | 10 ++++++++++ 3 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 test/integration/client/field-name-escape-tests.js diff --git a/lib/result.js b/lib/result.js index da999158a..aea4d3746 100644 --- a/lib/result.js +++ b/lib/result.js @@ -8,6 +8,7 @@ */ var types = require('pg-types') +var escape = require('js-string-escape') // result object returned from query // in the 'end' event and also @@ -82,7 +83,7 @@ var inlineParser = function (fieldName, i) { // Addendum: However, we need to make sure to replace all // occurences of apostrophes, not just the first one. // See https://github.com/brianc/node-postgres/issues/934 - fieldName.replace(/'/g, "\\'") + + escape(fieldName) + "'] = " + 'rowData[' + i + '] == null ? null : parsers[' + i + '](rowData[' + i + ']);' } diff --git a/package.json b/package.json index dfa0324d4..f4f21d7bd 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "dependencies": { "buffer-writer": "1.0.1", "packet-reader": "0.3.1", + "js-string-escape": "1.0.1", "pg-connection-string": "0.1.3", "pg-pool": "2.*", "pg-types": "1.*", diff --git a/test/integration/client/field-name-escape-tests.js b/test/integration/client/field-name-escape-tests.js new file mode 100644 index 000000000..146ad1b68 --- /dev/null +++ b/test/integration/client/field-name-escape-tests.js @@ -0,0 +1,10 @@ +var pg = require('./test-helper').pg + +var sql = 'SELECT 1 AS "\\\'/*", 2 AS "\\\'*/\n + process.exit(-1)] = null;\n//"' + +var client = new pg.Client() +client.connect() +client.query(sql, function (err, res) { + if (err) throw err + client.end() +}) From 7e7ff7f581b0f52cb6c266a882bf69c1fb385a7c Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 12 Aug 2017 16:34:35 -0500 Subject: [PATCH 0315/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f4f21d7bd..5f3680fcd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.1.0", + "version": "7.1.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 1769cff39797898af142849e689855f8b374eb13 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 12 Aug 2017 22:10:58 -0500 Subject: [PATCH 0316/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5f3680fcd..3acb225d0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.1.1", + "version": "7.1.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From cfb1fbcc18697c0e2dfe816c75f2794f77d9d76a Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 14 Aug 2017 11:11:10 -0700 Subject: [PATCH 0317/1037] Update SPONSORS.md --- SPONSORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SPONSORS.md b/SPONSORS.md index b82d856dc..c30860126 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -1,6 +1,7 @@ node-postgres is made possible by the helpful contributors from the community well as the following generous supporters on [Patreon](https://www.patreon.com/node_postgres). # Leaders +- Paul Cothenet # Supporters - John Fawcett From 8a0731fcfb8d70de2c0d142ccf07414171a953a1 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 14 Aug 2017 16:02:20 -0700 Subject: [PATCH 0318/1037] Update SPONSORS.md --- SPONSORS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SPONSORS.md b/SPONSORS.md index c30860126..eb9137a7e 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -1,7 +1,7 @@ node-postgres is made possible by the helpful contributors from the community well as the following generous supporters on [Patreon](https://www.patreon.com/node_postgres). # Leaders -- Paul Cothenet +- [MadKudu](https://www.madkudu.com) - [@madkudu](https://twitter.com/madkudu) # Supporters - John Fawcett From 6e2c1e9b98f4aead193dcc84b76019e7468164b4 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Sat, 12 Aug 2017 07:54:11 -0400 Subject: [PATCH 0319/1037] Removes extra 'use strict' --- test/integration/client/promise-api-tests.js | 1 - test/suite.js | 1 - 2 files changed, 2 deletions(-) diff --git a/test/integration/client/promise-api-tests.js b/test/integration/client/promise-api-tests.js index d06132601..80337c4ae 100644 --- a/test/integration/client/promise-api-tests.js +++ b/test/integration/client/promise-api-tests.js @@ -1,5 +1,4 @@ 'use strict' -'use strict' const helper = require('./test-helper') const pg = helper.pg diff --git a/test/suite.js b/test/suite.js index 5de9b281f..72a4fdcb0 100644 --- a/test/suite.js +++ b/test/suite.js @@ -1,5 +1,4 @@ 'use strict' -'use strict' const async = require('async') From 07dfebf3863bdb02af6bc9b8ee1e4e3259411724 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Sat, 19 Aug 2017 08:54:47 -0400 Subject: [PATCH 0320/1037] Sort .gitignore --- .gitignore | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 44602419d..3d2f139a5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ +*~ +build/ +.lock-wscript +*.log node_modules/ *.swp -*.log -.lock-wscript -build/ -*~ From c7937a55308d168acb233096b8eff979bde37f8e Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Sat, 19 Aug 2017 08:55:18 -0400 Subject: [PATCH 0321/1037] Add package-lock.json to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 3d2f139a5..88b672dd3 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ build/ .lock-wscript *.log node_modules/ +package-lock.json *.swp From 78dcd708bb1af59bf77d105be7b56cafb13126ad Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Sat, 19 Aug 2017 08:57:26 -0400 Subject: [PATCH 0322/1037] Sort .npmignore --- .npmignore | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.npmignore b/.npmignore index b0d737dc3..4e5fcac5d 100644 --- a/.npmignore +++ b/.npmignore @@ -1,8 +1,8 @@ +*~ +build/ +.lock-wscript +*.log node_modules/ +script/ *.swp -*.log -.lock-wscript -build/ -*~ test/ -script/ \ No newline at end of file From c2158f7607eb0f0708c7dabf63b4e7e24350b0e8 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 21 Aug 2017 15:34:01 -0500 Subject: [PATCH 0323/1037] Update SPONSORS.md --- SPONSORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SPONSORS.md b/SPONSORS.md index eb9137a7e..8068bd19e 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -7,3 +7,4 @@ node-postgres is made possible by the helpful contributors from the community we - John Fawcett - Lalit Kapoor [@lalitkapoor](https://twitter.com/lalitkapoor) - Paul Frazee [@pfrazee](https://twitter.com/pfrazee) +- Rein Petersen From abe7583512a30b9818eef3088db93613061fd75e Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 21 Aug 2017 11:25:08 -0500 Subject: [PATCH 0324/1037] Pin child modules to tighter semver ranges --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 3acb225d0..ae5c18f26 100644 --- a/package.json +++ b/package.json @@ -22,8 +22,8 @@ "packet-reader": "0.3.1", "js-string-escape": "1.0.1", "pg-connection-string": "0.1.3", - "pg-pool": "2.*", - "pg-types": "1.*", + "pg-pool": "~2.0.3", + "pg-types": "~1.12.1", "pgpass": "1.x", "semver": "4.3.2" }, From 3ddf9c84dfb0619b78fe29bc1064e279dc62006e Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 22 Aug 2017 15:06:30 -0500 Subject: [PATCH 0325/1037] Update SPONSORS.md --- SPONSORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SPONSORS.md b/SPONSORS.md index 8068bd19e..4b96a3407 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -8,3 +8,4 @@ node-postgres is made possible by the helpful contributors from the community we - Lalit Kapoor [@lalitkapoor](https://twitter.com/lalitkapoor) - Paul Frazee [@pfrazee](https://twitter.com/pfrazee) - Rein Petersen +- Arnaud Benhamdine From 95a703596c6dcfe80c5f1ec151d5bd716150621c Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 22 Aug 2017 15:08:52 -0500 Subject: [PATCH 0326/1037] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 848246275..cea334d47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.2.0 + +- Pinned pg-pool and pg-types to a tighter semver range. This is likely not a noticable change for you unless you were specifically installing older versions of those libraries for some reason, but making it a minor bump here just in case it could cause any confusion. + ### 7.1.0 #### Enhancements From 8022fa6b440ae61c1cae728d4b57c28df6b711c7 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 22 Aug 2017 15:08:59 -0500 Subject: [PATCH 0327/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ae5c18f26..fe251ab10 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.1.2", + "version": "7.2.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From 884e21e1ca58b7045c94d8cef4941eb97ac50ed5 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Sat, 19 Aug 2017 09:29:36 -0400 Subject: [PATCH 0328/1037] Refactor addCommandComplete Refactors addCommandComplete to tighten parsing regex start anchor and handle edge case where no row count is specified (pre 8.2 COPY). --- lib/result.js | 10 +++++----- test/unit/client/result-metadata-tests.js | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/result.js b/lib/result.js index aea4d3746..7dfd116f0 100644 --- a/lib/result.js +++ b/lib/result.js @@ -27,7 +27,7 @@ var Result = function (rowMode) { } } -var matchRegexp = /([A-Za-z]+) ?(\d+ )?(\d+)?/ +var matchRegexp = /^([A-Za-z]+)(?: (\d+))?(?: (\d+))?/ // adds a command complete message Result.prototype.addCommandComplete = function (msg) { @@ -41,12 +41,12 @@ Result.prototype.addCommandComplete = function (msg) { } if (match) { this.command = match[1] - // match 3 will only be existing on insert commands if (match[3]) { - // msg.value is from native bindings - this.rowCount = parseInt(match[3] || msg.value, 10) + // COMMMAND OID ROWS this.oid = parseInt(match[2], 10) - } else { + this.rowCount = parseInt(match[3], 10) + } else if (match[2]) { + // COMMAND ROWS this.rowCount = parseInt(match[2], 10) } } diff --git a/test/unit/client/result-metadata-tests.js b/test/unit/client/result-metadata-tests.js index 59b83443e..276892e92 100644 --- a/test/unit/client/result-metadata-tests.js +++ b/test/unit/client/result-metadata-tests.js @@ -35,3 +35,5 @@ testForTag('INSERT 841 1', check(841, 1, 'INSERT')) testForTag('DELETE 10', check(null, 10, 'DELETE')) testForTag('UPDATE 11', check(null, 11, 'UPDATE')) testForTag('SELECT 20', check(null, 20, 'SELECT')) +testForTag('COPY', check(null, null, 'COPY')) +testForTag('COPY 12345', check(null, 12345, 'COPY')) From 03c2270d0e264ad2af4ec29439f81ce2c63ea4bd Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Tue, 11 Jul 2017 14:43:59 +0200 Subject: [PATCH 0329/1037] add missing sslrootcert for native bindings --- lib/connection-parameters.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index 37658c12a..2ba409c24 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -91,6 +91,7 @@ ConnectionParameters.prototype.getLibpqConnectionString = function (cb) { add(params, ssl, 'sslca') add(params, ssl, 'sslkey') add(params, ssl, 'sslcert') + add(params, ssl, 'sslrootcert') if (this.database) { params.push('dbname=' + quoteParamValue(this.database)) From 7d1342e03bcddeb1f1fc6211c0f4566334f7fd03 Mon Sep 17 00:00:00 2001 From: Tobias Gurtzick Date: Sat, 19 Aug 2017 14:02:23 +0200 Subject: [PATCH 0330/1037] verify that sslrootcert is added to libpqConnectionString --- .../connection-parameters/creation-tests.js | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/unit/connection-parameters/creation-tests.js b/test/unit/connection-parameters/creation-tests.js index 9e02e56d0..a3fa25135 100644 --- a/test/unit/connection-parameters/creation-tests.js +++ b/test/unit/connection-parameters/creation-tests.js @@ -269,4 +269,32 @@ test('libpq connection string building', function () { var c = new Client('postgres://user@password:host/database') assert(c.ssl, 'Client should have ssl enabled via defaults') }) + + test('ssl is set on client', function () { + var sourceConfig = { + user: 'brian', + password: 'helloe', + port: 5432, + host: 'localhost', + database: 'postgres', + ssl: { + sslmode: 'verify-ca', + sslca: '/path/ca.pem', + sslkey: '/path/cert.key', + sslcert: '/path/cert.crt', + sslrootcert: '/path/root.crt' + } + } + var Client = require('../../../lib/client') + var defaults = require('../../../lib/defaults') + defaults.ssl = true + var c = new ConnectionParameters(sourceConfig) + c.getLibpqConnectionString(assert.calls(function (err, pgCString) { + assert(!err) + assert.equal( + pgCString.indexOf('sslrootcert=\'/path/root.crt\'') !== -1, true, + 'libpqConnectionString should contain sslrootcert' + ) + })) + }) }) From 1b55c7bb7b31d5fa591212fe57eb308e4a5b5922 Mon Sep 17 00:00:00 2001 From: Jessica Evans <31384125+jessicalinux@users.noreply.github.com> Date: Sun, 27 Aug 2017 13:42:28 +0100 Subject: [PATCH 0331/1037] capital letters minor beautification --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 8e479769d..7b24ee389 100644 --- a/README.md +++ b/README.md @@ -19,14 +19,14 @@ $ npm install pg ### Features -* pure JavaScript client and native libpq bindings share _the same api_ -* connection pooling -* extensible js<->postgresql data-type coercion -* supported PostgreSQL features - * parameterized queries - * named statements with query plan caching - * async notifications with `LISTEN/NOTIFY` - * bulk import & export with `COPY TO/COPY FROM` +* Pure JavaScript client and native libpq bindings share _the same api_ +* Connection pooling +* Extensible js<->postgresql data-type coercion +* Supported PostgreSQL features + * Parameterized queries + * Named statements with query plan caching + * Async notifications with `LISTEN/NOTIFY` + * Bulk import & export with `COPY TO/COPY FROM` ### Extras From 80d22da9756e4b136d753afdc401273172599442 Mon Sep 17 00:00:00 2001 From: Ben Holden-Crowther Date: Mon, 28 Aug 2017 10:52:29 +0100 Subject: [PATCH 0332/1037] Minor improvements full stop, capitalized Twitter --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7b24ee389..ca02bfc28 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ $ npm install pg ### Extras node-postgres is by design pretty light on abstractions. These are some handy modules we've been using over the years to complete the picture. -Entire list can be found on [wiki](https://github.com/brianc/node-postgres/wiki/Extras) +The entire list can be found on our [wiki](https://github.com/brianc/node-postgres/wiki/Extras). ## Support @@ -42,7 +42,7 @@ When you open an issue please provide: - version of postgres - smallest possible snippet of code to reproduce the problem -You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on twitter. +You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on Twitter. ### Professional Support From beba66f2f13ec811986a43911185bffc366b85dc Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 28 Aug 2017 10:57:38 -0500 Subject: [PATCH 0333/1037] Update SPONSORS.md --- SPONSORS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SPONSORS.md b/SPONSORS.md index 4b96a3407..b13261b53 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -8,4 +8,4 @@ node-postgres is made possible by the helpful contributors from the community we - Lalit Kapoor [@lalitkapoor](https://twitter.com/lalitkapoor) - Paul Frazee [@pfrazee](https://twitter.com/pfrazee) - Rein Petersen -- Arnaud Benhamdine +- Arnaud Benhamdine [@abenhamdine](https://twitter.com/abenhamdine) From 3ad0680e8dd0219c03d4287d253af8a5f08bc758 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Tue, 29 Aug 2017 11:19:07 -0400 Subject: [PATCH 0334/1037] Fix reference to md5 helper in test Fixes reference to md5 helper and removes reference to js client as the md5 function is now provided by utils. --- test/integration/connection/test-helper.js | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/integration/connection/test-helper.js b/test/integration/connection/test-helper.js index 71bcfb2e0..813d60411 100644 --- a/test/integration/connection/test-helper.js +++ b/test/integration/connection/test-helper.js @@ -2,6 +2,7 @@ var net = require('net') var helper = require(__dirname + '/../test-helper') var Connection = require(__dirname + '/../../../lib/connection') +var utils = require(__dirname + '/../../../lib/utils') var connect = function (callback) { var username = helper.args.user var database = helper.args.database @@ -20,10 +21,8 @@ var connect = function (callback) { con.password(helper.args.password) }) con.once('authenticationMD5Password', function (msg) { - // need js client even if native client is included - var client = require(__dirname + '/../../../lib/client') - var inner = client.md5(helper.args.password + helper.args.user) - var outer = client.md5(inner + msg.salt.toString('binary')) + var inner = utils.md5(helper.args.password + helper.args.user) + var outer = utils.md5(Buffer.concat([Buffer.from(inner), msg.salt])) con.password('md5' + outer) }) con.once('readyForQuery', function () { From e74c13ddad6832f50d4de4d43ef7ba37ed68787b Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Tue, 29 Aug 2017 16:00:59 -0400 Subject: [PATCH 0335/1037] Centralize password md5 hashing logic Centralize logic for md5 hashing of passwords for authentication. Adds a new function postgresMd5PasswordHash(user, password, salt) to utils and updates client.js and tests to use it. --- lib/client.js | 5 +---- lib/utils.js | 8 ++++++++ test/integration/connection/test-helper.js | 4 +--- test/unit/client/md5-password-tests.js | 4 +--- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/client.js b/lib/client.js index 72edd699b..2016a6ff4 100644 --- a/lib/client.js +++ b/lib/client.js @@ -106,10 +106,7 @@ Client.prototype.connect = function (callback) { // password request handling con.on('authenticationMD5Password', checkPgPass(function (msg) { - var inner = utils.md5(self.password + self.user) - var outer = utils.md5(Buffer.concat([Buffer.from(inner), msg.salt])) - var md5password = 'md5' + outer - con.password(md5password) + con.password(utils.postgresMd5PasswordHash(self.user, self.password, msg.salt)) })) con.once('backendKeyData', function (msg) { diff --git a/lib/utils.js b/lib/utils.js index 352a02fbc..575fb056b 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -138,6 +138,13 @@ const md5 = function (string) { return crypto.createHash('md5').update(string, 'utf-8').digest('hex') } +// See AuthenticationMD5Password at https://www.postgresql.org/docs/current/static/protocol-flow.html +const postgresMd5PasswordHash = function (user, password, salt) { + var inner = md5(password + user) + var outer = md5(Buffer.concat([Buffer.from(inner), salt])) + return 'md5' + outer +} + module.exports = { prepareValue: function prepareValueWrapper (value) { // this ensures that extra arguments do not get passed into prepareValue @@ -145,5 +152,6 @@ module.exports = { return prepareValue(value) }, normalizeQueryConfig: normalizeQueryConfig, + postgresMd5PasswordHash: postgresMd5PasswordHash, md5: md5 } diff --git a/test/integration/connection/test-helper.js b/test/integration/connection/test-helper.js index 813d60411..99661a469 100644 --- a/test/integration/connection/test-helper.js +++ b/test/integration/connection/test-helper.js @@ -21,9 +21,7 @@ var connect = function (callback) { con.password(helper.args.password) }) con.once('authenticationMD5Password', function (msg) { - var inner = utils.md5(helper.args.password + helper.args.user) - var outer = utils.md5(Buffer.concat([Buffer.from(inner), msg.salt])) - con.password('md5' + outer) + con.password(utils.postgresMd5PasswordHash(helper.args.user, helper.args.password, msg.salt)); }) con.once('readyForQuery', function () { con.query('create temp table ids(id integer)') diff --git a/test/unit/client/md5-password-tests.js b/test/unit/client/md5-password-tests.js index 26e233ed5..85b357ae7 100644 --- a/test/unit/client/md5-password-tests.js +++ b/test/unit/client/md5-password-tests.js @@ -11,9 +11,7 @@ test('md5 authentication', function () { test('responds', function () { assert.lengthIs(client.connection.stream.packets, 1) test('should have correct encrypted data', function () { - var encrypted = utils.md5(client.password + client.user) - encrypted = utils.md5(encrypted + salt.toString('binary')) - var password = 'md5' + encrypted + var password = utils.postgresMd5PasswordHash(client.user, client.password, salt) // how do we want to test this? assert.equalBuffers(client.connection.stream.packets[0], new BufferList() .addCString(password).join(true, 'p')) From ef3379a4800a47da4d5bcd5d68e637a47bc531a1 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Tue, 29 Aug 2017 18:46:09 -0400 Subject: [PATCH 0336/1037] Normalize export in utils to use short form --- lib/utils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 575fb056b..1167a0760 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -151,7 +151,7 @@ module.exports = { // by accident, eg: from calling values.map(utils.prepareValue) return prepareValue(value) }, - normalizeQueryConfig: normalizeQueryConfig, - postgresMd5PasswordHash: postgresMd5PasswordHash, - md5: md5 + normalizeQueryConfig, + postgresMd5PasswordHash, + md5 } From 13687353c9ecc4b2ea736ee0784a6a158a40a951 Mon Sep 17 00:00:00 2001 From: Luis Montes Date: Wed, 30 Aug 2017 13:58:52 -0700 Subject: [PATCH 0337/1037] Use mocha, istanbul, and coveralls (#16) * some tests * coveralls and mocha * coveralls post test hook * remove done calls --- .coveralls.yml | 2 + .travis.yml | 1 + README.md | 3 + package.json | 8 +- test/parse.js | 376 +++++++++++++++++++++++-------------------------- 5 files changed, 188 insertions(+), 202 deletions(-) create mode 100644 .coveralls.yml diff --git a/.coveralls.yml b/.coveralls.yml new file mode 100644 index 000000000..0709f6e03 --- /dev/null +++ b/.coveralls.yml @@ -0,0 +1,2 @@ +service_name: travis-pro +repo_token: 5F6dODinz9L9uFR6HatKmtsYDoV1A5S2N diff --git a/.travis.yml b/.travis.yml index 202c30781..daf50ba6d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,3 +3,4 @@ node_js: - '0.10' - '6.9' - '8' +after_success: 'npm run coveralls' diff --git a/README.md b/README.md index ddf9bfcb3..2228b80e1 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,10 @@ pg-connection-string ==================== +[![NPM](https://nodei.co/npm/pg-connection-string.png?compact=true)](https://nodei.co/npm/pg-connection-string/) + [![Build Status](https://travis-ci.org/iceddev/pg-connection-string.svg?branch=master)](https://travis-ci.org/iceddev/pg-connection-string) +[![Coverage Status](https://coveralls.io/repos/iceddev/pg-connection-string/badge.svg?branch=master)](https://coveralls.io/r/iceddev/pg-connection-string?branch=master) Functions for dealing with a PostgresSQL connection string diff --git a/package.json b/package.json index 9b0e62ec4..f6ff6e511 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "main": "./index.js", "types": "./index.d.ts", "scripts": { - "test": "tap ./test" + "test": "istanbul cover _mocha && npm run check-coverage", + "check-coverage": "istanbul check-coverage --statements 100 --branches 100 --lines 100 --functions 100", + "coveralls": "cat ./coverage/lcov.info | ./node_modules/.bin/coveralls" }, "repository": { "type": "git", @@ -25,6 +27,8 @@ "homepage": "https://github.com/iceddev/pg-connection-string", "dependencies": {}, "devDependencies": { - "tap": "^10.3.3" + "chai": "^4.1.1", + "istanbul": "^0.4.5", + "mocha": "^3.5.0" } } diff --git a/test/parse.js b/test/parse.js index 8f4bcb43a..8ff3ee81d 100644 --- a/test/parse.js +++ b/test/parse.js @@ -1,206 +1,182 @@ 'use strict'; -var test = require('tap').test; +var chai = require('chai'); +var expect = chai.expect; +chai.should(); var parse = require('../').parse; -test('using connection string in client constructor', function(t){ - var subject = parse('postgres://brian:pw@boom:381/lala'); - t.equal(subject.user,'brian'); - t.equal(subject.password, 'pw'); - t.equal(subject.host, 'boom'); - t.equal(subject.port, '381'); - t.equal(subject.database, 'lala'); - t.end(); +describe('parse', function(){ + + it('using connection string in client constructor', function(){ + var subject = parse('postgres://brian:pw@boom:381/lala'); + subject.user.should.equal('brian'); + subject.password.should.equal( 'pw'); + subject.host.should.equal( 'boom'); + subject.port.should.equal( '381'); + subject.database.should.equal( 'lala'); + }); + + it('escape spaces if present', function(){ + var subject = parse('postgres://localhost/post gres'); + subject.database.should.equal('post gres'); + }); + + it('do not double escape spaces', function(){ + var subject = parse('postgres://localhost/post%20gres'); + subject.database.should.equal('post gres'); + }); + + it('initializing with unix domain socket', function(){ + var subject = parse('/var/run/'); + subject.host.should.equal('/var/run/'); + }); + + it('initializing with unix domain socket and a specific database, the simple way', function(){ + var subject = parse('/var/run/ mydb'); + subject.host.should.equal('/var/run/'); + subject.database.should.equal('mydb'); + }); + + it('initializing with unix domain socket, the health way', function(){ + var subject = parse('socket:/some path/?db=my[db]&encoding=utf8'); + subject.host.should.equal('/some path/'); + subject.database.should.equal('my[db]', 'must to be escaped and unescaped trough "my%5Bdb%5D"'); + subject.client_encoding.should.equal('utf8'); + }); + + it('initializing with unix domain socket, the escaped health way', function(){ + var subject = parse('socket:/some%20path/?db=my%2Bdb&encoding=utf8'); + subject.host.should.equal('/some path/'); + subject.database.should.equal('my+db'); + subject.client_encoding.should.equal('utf8'); + }); + + it('password contains < and/or > characters', function(){ + var sourceConfig = { + user:'brian', + password: 'helloe', + port: 5432, + host: 'localhost', + database: 'postgres' + }; + var connectionString = 'postgres://' + sourceConfig.user + ':' + sourceConfig.password + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database; + var subject = parse(connectionString); + subject.password.should.equal(sourceConfig.password); + }); + + it('password contains colons', function(){ + var sourceConfig = { + user:'brian', + password: 'hello:pass:world', + port: 5432, + host: 'localhost', + database: 'postgres' + }; + var connectionString = 'postgres://' + sourceConfig.user + ':' + sourceConfig.password + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database; + var subject = parse(connectionString); + subject.password.should.equal(sourceConfig.password); + }); + + it('username or password contains weird characters', function(){ + var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000'; + var subject = parse(strang); + subject.user.should.equal('my f%irst name'); + subject.password.should.equal('is&%awesome!'); + subject.host.should.equal('localhost'); + }); + + it('url is properly encoded', function(){ + var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl'; + var subject = parse(encoded); + subject.user.should.equal('bi%na%%ry '); + subject.password.should.equal('s@f#'); + subject.host.should.equal('localhost'); + subject.database.should.equal(' u%20rl'); + }); + + it('relative url sets database', function(){ + var relative = 'different_db_on_default_host'; + var subject = parse(relative); + subject.database.should.equal('different_db_on_default_host'); + }); + + it('no pathname returns null database', function () { + var subject = parse('pg://myhost'); + (subject.database === null).should.equal(true); + }); + + it('pathname of "/" returns null database', function () { + var subject = parse('pg://myhost/'); + subject.host.should.equal('myhost'); + (subject.database === null).should.equal(true); + }); + + it('configuration parameter application_name', function(){ + var connectionString = 'pg:///?application_name=TheApp'; + var subject = parse(connectionString); + subject.application_name.should.equal('TheApp'); + }); + + it('configuration parameter fallback_application_name', function(){ + var connectionString = 'pg:///?fallback_application_name=TheAppFallback'; + var subject = parse(connectionString); + subject.fallback_application_name.should.equal('TheAppFallback'); + }); + + it('configuration parameter fallback_application_name', function(){ + var connectionString = 'pg:///?fallback_application_name=TheAppFallback'; + var subject = parse(connectionString); + subject.fallback_application_name.should.equal('TheAppFallback'); + }); + + it('configuration parameter ssl=true', function(){ + var connectionString = 'pg:///?ssl=true'; + var subject = parse(connectionString); + subject.ssl.should.equal(true); + }); + + it('configuration parameter ssl=1', function(){ + var connectionString = 'pg:///?ssl=1'; + var subject = parse(connectionString); + subject.ssl.should.equal(true); + }); + + it('set ssl', function () { + var subject = parse('pg://myhost/db?ssl=1'); + subject.ssl.should.equal(true); + }); + + it('allow other params like max, ...', function () { + var subject = parse('pg://myhost/db?max=18&min=4'); + subject.max.should.equal('18'); + subject.min.should.equal('4'); + }); + + + it('configuration parameter keepalives', function(){ + var connectionString = 'pg:///?keepalives=1'; + var subject = parse(connectionString); + subject.keepalives.should.equal('1'); + }); + + it('unknown configuration parameter is passed into client', function(){ + var connectionString = 'pg:///?ThereIsNoSuchPostgresParameter=1234'; + var subject = parse(connectionString); + subject.ThereIsNoSuchPostgresParameter.should.equal('1234'); + }); + + it('do not override a config field with value from query string', function(){ + var subject = parse('socket:/some path/?db=my[db]&encoding=utf8&client_encoding=bogus'); + subject.host.should.equal('/some path/'); + subject.database.should.equal('my[db]', 'must to be escaped and unescaped through "my%5Bdb%5D"'); + subject.client_encoding.should.equal('utf8'); + }); + + + it('return last value of repeated parameter', function(){ + var connectionString = 'pg:///?keepalives=1&keepalives=0'; + var subject = parse(connectionString); + subject.keepalives.should.equal('0'); + }); }); - -test('escape spaces if present', function(t){ - var subject = parse('postgres://localhost/post gres'); - t.equal(subject.database, 'post gres'); - t.end(); -}); - -test('do not double escape spaces', function(t){ - var subject = parse('postgres://localhost/post%20gres'); - t.equal(subject.database, 'post gres'); - t.end(); -}); - -test('initializing with unix domain socket', function(t){ - var subject = parse('/var/run/'); - t.equal(subject.host, '/var/run/'); - t.end(); -}); - -test('initializing with unix domain socket and a specific database, the simple way', function(t){ - var subject = parse('/var/run/ mydb'); - t.equal(subject.host, '/var/run/'); - t.equal(subject.database, 'mydb'); - t.end(); -}); - -test('initializing with unix domain socket, the health way', function(t){ - var subject = parse('socket:/some path/?db=my[db]&encoding=utf8'); - t.equal(subject.host, '/some path/'); - t.equal(subject.database, 'my[db]', 'must to be escaped and unescaped trough "my%5Bdb%5D"'); - t.equal(subject.client_encoding, 'utf8'); - t.end(); -}); - -test('initializing with unix domain socket, the escaped health way', function(t){ - var subject = parse('socket:/some%20path/?db=my%2Bdb&encoding=utf8'); - t.equal(subject.host, '/some path/'); - t.equal(subject.database, 'my+db'); - t.equal(subject.client_encoding, 'utf8'); - t.end(); -}); - -test('password contains < and/or > characters', function(t){ - var sourceConfig = { - user:'brian', - password: 'helloe', - port: 5432, - host: 'localhost', - database: 'postgres' - }; - var connectionString = 'postgres://' + sourceConfig.user + ':' + sourceConfig.password + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database; - var subject = parse(connectionString); - t.equal(subject.password, sourceConfig.password); - t.end(); -}); - -test('password contains colons', function(t){ - var sourceConfig = { - user:'brian', - password: 'hello:pass:world', - port: 5432, - host: 'localhost', - database: 'postgres' - }; - var connectionString = 'postgres://' + sourceConfig.user + ':' + sourceConfig.password + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database; - var subject = parse(connectionString); - t.equal(subject.password, sourceConfig.password); - t.end(); -}); - -test('username or password contains weird characters', function(t){ - var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000'; - var subject = parse(strang); - t.equal(subject.user, 'my f%irst name'); - t.equal(subject.password, 'is&%awesome!'); - t.equal(subject.host, 'localhost'); - t.end(); -}); - -test('url is properly encoded', function(t){ - var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl'; - var subject = parse(encoded); - t.equal(subject.user, 'bi%na%%ry '); - t.equal(subject.password, 's@f#'); - t.equal(subject.host, 'localhost'); - t.equal(subject.database, ' u%20rl'); - t.end(); -}); - -test('relative url sets database', function(t){ - var relative = 'different_db_on_default_host'; - var subject = parse(relative); - t.equal(subject.database, 'different_db_on_default_host'); - t.end(); -}); - -test('no pathname returns null database', function (t) { - var subject = parse('pg://myhost'); - t.equal(subject.host, 'myhost'); - t.type(subject.database, 'null'); - - t.end(); -}); - -test('pathname of "/" returns null database', function (t) { - var subject = parse('pg://myhost/'); - t.equal(subject.host, 'myhost'); - t.type(subject.database, 'null'); - - t.end(); -}); - -test('configuration parameter application_name', function(t){ - var connectionString = 'pg:///?application_name=TheApp'; - var subject = parse(connectionString); - t.equal(subject.application_name, 'TheApp'); - t.end(); -}); - -test('configuration parameter fallback_application_name', function(t){ - var connectionString = 'pg:///?fallback_application_name=TheAppFallback'; - var subject = parse(connectionString); - t.equal(subject.fallback_application_name, 'TheAppFallback'); - t.end(); -}); - -test('configuration parameter fallback_application_name', function(t){ - var connectionString = 'pg:///?fallback_application_name=TheAppFallback'; - var subject = parse(connectionString); - t.equal(subject.fallback_application_name, 'TheAppFallback'); - t.end(); -}); - -test('configuration parameter ssl=true', function(t){ - var connectionString = 'pg:///?ssl=true'; - var subject = parse(connectionString); - t.equal(subject.ssl, true); - t.end(); -}); - -test('configuration parameter ssl=1', function(t){ - var connectionString = 'pg:///?ssl=1'; - var subject = parse(connectionString); - t.equal(subject.ssl, true); - t.end(); -}); - -test('set ssl', function (t) { - var subject = parse('pg://myhost/db?ssl=1'); - t.equal(subject.ssl, true); - t.end(); - }); - - test('allow other params like max, ...', function (t) { - var subject = parse('pg://myhost/db?max=18&min=4'); - t.equal(subject.max, '18'); - t.equal(subject.min, '4'); - t.end(); - }); - - -test('configuration parameter keepalives', function(t){ - var connectionString = 'pg:///?keepalives=1'; - var subject = parse(connectionString); - t.equal(subject.keepalives, '1'); - t.end(); -}); - -test('unknown configuration parameter is passed into client', function(t){ - var connectionString = 'pg:///?ThereIsNoSuchPostgresParameter=1234'; - var subject = parse(connectionString); - t.equal(subject.ThereIsNoSuchPostgresParameter, '1234'); - t.end(); -}); - -test('do not override a config field with value from query string', function(t){ - var subject = parse('socket:/some path/?db=my[db]&encoding=utf8&client_encoding=bogus'); - t.equal(subject.host, '/some path/'); - t.equal(subject.database, 'my[db]', 'must to be escaped and unescaped trough "my%5Bdb%5D"'); - t.equal(subject.client_encoding, 'utf8'); - t.end(); -}); - - -test('return last value of repeated parameter', function(t){ - var connectionString = 'pg:///?keepalives=1&keepalives=0'; - var subject = parse(connectionString); - t.equal(subject.keepalives, '0'); - t.end(); -}); - From eafb7acd951b4ee606d41c0d1ba66b34e72119a3 Mon Sep 17 00:00:00 2001 From: Luis Montes Date: Wed, 30 Aug 2017 14:25:59 -0700 Subject: [PATCH 0338/1037] 2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f6ff6e511..5b75ea37a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "0.1.3", + "version": "2.0.0", "description": "Functions for dealing with a PostgresSQL connection string", "main": "./index.js", "types": "./index.d.ts", From ffc7653b9ebf1572620a1db16f9121e33e0995bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kau=C3=AA=20Gimenes?= Date: Thu, 31 Aug 2017 22:26:22 -0300 Subject: [PATCH 0339/1037] Update Grammatical person Update Grammatical person from First Person to Third Person. --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index ca02bfc28..3da93346c 100644 --- a/README.md +++ b/README.md @@ -35,18 +35,18 @@ The entire list can be found on our [wiki](https://github.com/brianc/node-postgr ## Support -node-postgres is free software. If you encounter a bug with the library please open an issue on the [github repo](https://github.com/brianc/node-postgres). If you have questions unanswered by the documentation please open an issue pointing out how the documentation was unclear & I will do my best to make it better! +node-postgres is free software. If you encounter a bug with the library please open an issue on the [github repo](https://github.com/brianc/node-postgres). If you have questions unanswered by the documentation please open an issue pointing out how the documentation was unclear & We will do our best to make it better! When you open an issue please provide: - version of node - version of postgres - smallest possible snippet of code to reproduce the problem -You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on Twitter. +You can also follow [@briancarlson](https://twitter.com/briancarlson) if that's your thing. He aways tries to announce noteworthy changes & developments with node-postgres on Twitter. ### Professional Support -I offer professional support for node-postgres. I provide implementation, training, and many years of expertise on how to build applications with node, express, PostgreSQL, and react/redux. Please contact me at [brian.m.carlson@gmail.com](mailto:brian.m.carlson@gmail.com) to discuss how I can help your company be more successful! +If you need professional support for node-postgres, you can contact Brian, he provides training, and has many years of expertise on how to build applications with node, express, PostgreSQL, and react/redux. Please contact Brian at [brian.m.carlson@gmail.com](mailto:brian.m.carlson@gmail.com) to discuss how your company can be more successful! ### Sponsorship :star: @@ -54,9 +54,9 @@ If you are benefiting from node-postgres and would like to help keep the project ## Contributing -__:heart: contributions!__ +We __:heart: contributions!__ -I will __happily__ accept your pull request if it: +We will __happily__ accept your pull request if it: - __has tests__ - looks reasonable - does not break backwards compatibility From c961888cebda15376f67711d5354c8d07b68e4ec Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Sun, 3 Sep 2017 17:16:38 +0000 Subject: [PATCH 0340/1037] Revert "Update Grammatical person" This reverts commit ffc7653b9ebf1572620a1db16f9121e33e0995bc. --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3da93346c..ca02bfc28 100644 --- a/README.md +++ b/README.md @@ -35,18 +35,18 @@ The entire list can be found on our [wiki](https://github.com/brianc/node-postgr ## Support -node-postgres is free software. If you encounter a bug with the library please open an issue on the [github repo](https://github.com/brianc/node-postgres). If you have questions unanswered by the documentation please open an issue pointing out how the documentation was unclear & We will do our best to make it better! +node-postgres is free software. If you encounter a bug with the library please open an issue on the [github repo](https://github.com/brianc/node-postgres). If you have questions unanswered by the documentation please open an issue pointing out how the documentation was unclear & I will do my best to make it better! When you open an issue please provide: - version of node - version of postgres - smallest possible snippet of code to reproduce the problem -You can also follow [@briancarlson](https://twitter.com/briancarlson) if that's your thing. He aways tries to announce noteworthy changes & developments with node-postgres on Twitter. +You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on Twitter. ### Professional Support -If you need professional support for node-postgres, you can contact Brian, he provides training, and has many years of expertise on how to build applications with node, express, PostgreSQL, and react/redux. Please contact Brian at [brian.m.carlson@gmail.com](mailto:brian.m.carlson@gmail.com) to discuss how your company can be more successful! +I offer professional support for node-postgres. I provide implementation, training, and many years of expertise on how to build applications with node, express, PostgreSQL, and react/redux. Please contact me at [brian.m.carlson@gmail.com](mailto:brian.m.carlson@gmail.com) to discuss how I can help your company be more successful! ### Sponsorship :star: @@ -54,9 +54,9 @@ If you are benefiting from node-postgres and would like to help keep the project ## Contributing -We __:heart: contributions!__ +__:heart: contributions!__ -We will __happily__ accept your pull request if it: +I will __happily__ accept your pull request if it: - __has tests__ - looks reasonable - does not break backwards compatibility From 27492efc11e9998ad9bc1ea8a840d36fbbeb7205 Mon Sep 17 00:00:00 2001 From: Arnaud Benhamdine Date: Wed, 30 Aug 2017 22:19:20 +0200 Subject: [PATCH 0341/1037] Remove properties no more used in node-pg-pool --- lib/defaults.js | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/lib/defaults.js b/lib/defaults.js index 62f2ad158..f0a6208f9 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -35,23 +35,15 @@ module.exports = { // binary result mode binary: false, - // Connection pool options - see https://github.com/coopernurse/node-pool + // Connection pool options - see https://github.com/brianc/node-pg-pool + // number of connections to use in connection pool // 0 will disable connection pooling poolSize: 10, // max milliseconds a client can go unused before it is removed // from the pool and destroyed - poolIdleTimeout: 30000, - - // frequency to check for idle clients within the client pool - reapIntervalMillis: 1000, - - // if true the most recently released resources will be the first to be allocated - returnToHead: false, - - // pool log function / boolean - poolLog: false, + idleTimeoutMillis: 30000, client_encoding: '', From 3b3e52cdc2501f92a65cac4a5097143b29f2cfe4 Mon Sep 17 00:00:00 2001 From: Arnaud Benhamdine Date: Wed, 30 Aug 2017 22:21:06 +0200 Subject: [PATCH 0342/1037] Prefer max over poolSize : max is the only property documented in node-pg-pool --- lib/defaults.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/defaults.js b/lib/defaults.js index f0a6208f9..e99abef42 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -39,7 +39,7 @@ module.exports = { // number of connections to use in connection pool // 0 will disable connection pooling - poolSize: 10, + max: 10, // max milliseconds a client can go unused before it is removed // from the pool and destroyed From d6e7dfee837156d34b68f47ccbc995b8c9e5aedf Mon Sep 17 00:00:00 2001 From: Arnaud Benhamdine Date: Wed, 30 Aug 2017 22:46:52 +0200 Subject: [PATCH 0343/1037] Replace poolSize by max in configuration test --- test/integration/client/configuration-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/client/configuration-tests.js b/test/integration/client/configuration-tests.js index 9d3b7f5ab..36391ab0f 100644 --- a/test/integration/client/configuration-tests.js +++ b/test/integration/client/configuration-tests.js @@ -18,7 +18,7 @@ suite.test('default values are used in new clients', function () { password: null, port: 5432, rows: 0, - poolSize: 10 + max: 10, }) var client = new pg.Client() From 4936033adfcaec54388019372dd1b955c70c0dba Mon Sep 17 00:00:00 2001 From: Arnaud Benhamdine Date: Wed, 30 Aug 2017 22:47:17 +0200 Subject: [PATCH 0344/1037] Check more default properties in configuration teset --- test/integration/client/configuration-tests.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/integration/client/configuration-tests.js b/test/integration/client/configuration-tests.js index 36391ab0f..87bb52d47 100644 --- a/test/integration/client/configuration-tests.js +++ b/test/integration/client/configuration-tests.js @@ -19,6 +19,13 @@ suite.test('default values are used in new clients', function () { port: 5432, rows: 0, max: 10, + binary: false, + idleTimeoutMillis: 30000, + client_encoding: '', + ssl: false, + application_name: undefined, + fallback_application_name: undefined, + parseInputDatesAsUTC: false }) var client = new pg.Client() From ad36063ca59fdad7b903bb95f79c867919aa15a5 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 29 Aug 2017 17:09:55 -0700 Subject: [PATCH 0345/1037] support statement_timeout --- .gitignore | 1 + lib/client.js | 3 + lib/connection-parameters.js | 1 + lib/defaults.js | 5 +- .../client/statement_timeout-tests.js | 69 +++++++++++++++++++ .../connection-parameters/creation-tests.js | 4 +- 6 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 test/integration/client/statement_timeout-tests.js diff --git a/.gitignore b/.gitignore index 88b672dd3..439db5fd6 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ build/ node_modules/ package-lock.json *.swp +/.idea diff --git a/lib/client.js b/lib/client.js index 2016a6ff4..3228571d5 100644 --- a/lib/client.js +++ b/lib/client.js @@ -269,6 +269,9 @@ Client.prototype.getStartupConf = function () { if (params.replication) { data.replication = '' + params.replication } + if (params.statement_timeout) { + data.statement_timeout = String(parseInt(params.statement_timeout, 10)) + } return data } diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index 2ba409c24..f31f28dd3 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -64,6 +64,7 @@ var ConnectionParameters = function (config) { this.application_name = val('application_name', config, 'PGAPPNAME') this.fallback_application_name = val('fallback_application_name', config, false) + this.statement_timeout = val('statement_timeout', config, false) } // Convert arg to a string, surround in single quotes, and escape single quotes and backslashes diff --git a/lib/defaults.js b/lib/defaults.js index e99abef42..30214b1d8 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -52,7 +52,10 @@ module.exports = { application_name: undefined, fallback_application_name: undefined, - parseInputDatesAsUTC: false + parseInputDatesAsUTC: false, + + // max milliseconds any query using this connection will execute for before timing out in error. false=unlimited + statement_timeout: false } var pgTypes = require('pg-types') diff --git a/test/integration/client/statement_timeout-tests.js b/test/integration/client/statement_timeout-tests.js new file mode 100644 index 000000000..5bf1e943d --- /dev/null +++ b/test/integration/client/statement_timeout-tests.js @@ -0,0 +1,69 @@ +'use strict' +var helper = require('./test-helper') +var Client = helper.Client + +var suite = new helper.Suite() + +var conInfo = helper.config + +function getConInfo (override) { + var newConInfo = {} + Object.keys(conInfo).forEach(function (k) { + newConInfo[k] = conInfo[k] + }) + Object.keys(override || {}).forEach(function (k) { + newConInfo[k] = override[k] + }) + return newConInfo +} + +function getStatementTimeout (conf, cb) { + var client = new Client(conf) + client.connect(assert.success(function () { + client.query('SHOW statement_timeout', assert.success(function (res) { + var statementTimeout = res.rows[0].statement_timeout + cb(statementTimeout) + client.end() + })) + })) +} + +if (!helper.args.native) { // statement_timeout is not supported with the native client + suite.test('No default statement_timeout ', function (done) { + getConInfo() + getStatementTimeout({}, function (res) { + assert.strictEqual(res, '0') // 0 = no timeout + done() + }) + }) + + suite.test('statement_timeout integer is used', function (done) { + var conf = getConInfo({ + 'statement_timeout': 3000 + }) + getStatementTimeout(conf, function (res) { + assert.strictEqual(res, '3s') + done() + }) + }) + + suite.test('statement_timeout float is used', function (done) { + var conf = getConInfo({ + 'statement_timeout': 3000.7 + }) + getStatementTimeout(conf, function (res) { + assert.strictEqual(res, '3s') + done() + }) + }) + + suite.test('statement_timeout string is used', function (done) { + var conf = getConInfo({ + 'statement_timeout': '3000' + }) + getStatementTimeout(conf, function (res) { + assert.strictEqual(res, '3s') + done() + }) + }) +} diff --git a/test/unit/connection-parameters/creation-tests.js b/test/unit/connection-parameters/creation-tests.js index a3fa25135..8563a404e 100644 --- a/test/unit/connection-parameters/creation-tests.js +++ b/test/unit/connection-parameters/creation-tests.js @@ -22,6 +22,7 @@ var compare = function (actual, expected, type) { assert.equal(actual.host, expected.host, type + ' host') assert.equal(actual.password, expected.password, type + ' password') assert.equal(actual.binary, expected.binary, type + ' binary') + assert.equal(actual.statement_timout, expected.statement_timout, type + ' binary') } test('ConnectionParameters initializing from defaults', function () { @@ -60,7 +61,8 @@ test('ConnectionParameters initializing from config', function () { host: 'yo', ssl: { asdf: 'blah' - } + }, + statement_timeout: 15000 } var subject = new ConnectionParameters(config) compare(subject, config, 'config') From 8839d425475cc70c55c791aeff46e5356f8322a8 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 29 Aug 2017 17:16:21 -0700 Subject: [PATCH 0346/1037] fixed test failure message --- test/unit/connection-parameters/creation-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/connection-parameters/creation-tests.js b/test/unit/connection-parameters/creation-tests.js index 8563a404e..fc9f6521f 100644 --- a/test/unit/connection-parameters/creation-tests.js +++ b/test/unit/connection-parameters/creation-tests.js @@ -22,7 +22,7 @@ var compare = function (actual, expected, type) { assert.equal(actual.host, expected.host, type + ' host') assert.equal(actual.password, expected.password, type + ' password') assert.equal(actual.binary, expected.binary, type + ' binary') - assert.equal(actual.statement_timout, expected.statement_timout, type + ' binary') + assert.equal(actual.statement_timout, expected.statement_timout, type + ' statement_timeout') } test('ConnectionParameters initializing from defaults', function () { From 78fc90366d12461faed78566a5551c38379617b6 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 29 Aug 2017 18:19:51 -0700 Subject: [PATCH 0347/1037] remove .idea from gitignore --- .gitignore | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 439db5fd6..8e3056a0e 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,4 @@ build/ *.log node_modules/ package-lock.json -*.swp -/.idea +*.swp \ No newline at end of file From 689bb25e86bcd9433b0cf4788f50ea2d3b324409 Mon Sep 17 00:00:00 2001 From: Josh Date: Tue, 29 Aug 2017 18:23:21 -0700 Subject: [PATCH 0348/1037] fixes --- package.json | 3 ++- test/integration/client/appname-tests.js | 9 +-------- test/integration/client/statement_timeout-tests.js | 9 +-------- 3 files changed, 4 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index fe251ab10..680a54d44 100644 --- a/package.json +++ b/package.json @@ -19,9 +19,10 @@ "main": "./lib", "dependencies": { "buffer-writer": "1.0.1", - "packet-reader": "0.3.1", "js-string-escape": "1.0.1", + "packet-reader": "0.3.1", "pg-connection-string": "0.1.3", + "pg-native": "^2.2.0", "pg-pool": "~2.0.3", "pg-types": "~1.12.1", "pgpass": "1.x", diff --git a/test/integration/client/appname-tests.js b/test/integration/client/appname-tests.js index 4db5297c9..e5883908d 100644 --- a/test/integration/client/appname-tests.js +++ b/test/integration/client/appname-tests.js @@ -7,14 +7,7 @@ var suite = new helper.Suite() var conInfo = helper.config function getConInfo (override) { - var newConInfo = {} - Object.keys(conInfo).forEach(function (k) { - newConInfo[k] = conInfo[k] - }) - Object.keys(override || {}).forEach(function (k) { - newConInfo[k] = override[k] - }) - return newConInfo + return Object.assign({}, conInfo, override ) } function getAppName (conf, cb) { diff --git a/test/integration/client/statement_timeout-tests.js b/test/integration/client/statement_timeout-tests.js index 5bf1e943d..5574285c6 100644 --- a/test/integration/client/statement_timeout-tests.js +++ b/test/integration/client/statement_timeout-tests.js @@ -7,14 +7,7 @@ var suite = new helper.Suite() var conInfo = helper.config function getConInfo (override) { - var newConInfo = {} - Object.keys(conInfo).forEach(function (k) { - newConInfo[k] = conInfo[k] - }) - Object.keys(override || {}).forEach(function (k) { - newConInfo[k] = override[k] - }) - return newConInfo + return Object.assign({}, conInfo, override ) } function getStatementTimeout (conf, cb) { From 175b688b90a1f930876e1344b03dd3a21ab407b7 Mon Sep 17 00:00:00 2001 From: Josh Date: Wed, 30 Aug 2017 08:07:57 -0700 Subject: [PATCH 0349/1037] remove pg-native from dependencies `npm run test` seems to be adding this --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 680a54d44..eddce4902 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "js-string-escape": "1.0.1", "packet-reader": "0.3.1", "pg-connection-string": "0.1.3", - "pg-native": "^2.2.0", "pg-pool": "~2.0.3", "pg-types": "~1.12.1", "pgpass": "1.x", From 64eb77e94c09a6b3e53b86fa98a558b3c11f6f1b Mon Sep 17 00:00:00 2001 From: Josh Date: Thu, 31 Aug 2017 08:57:02 -0700 Subject: [PATCH 0350/1037] new test for actual statement timeout --- .../integration/client/statement_timeout-tests.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/integration/client/statement_timeout-tests.js b/test/integration/client/statement_timeout-tests.js index 5574285c6..393e82a19 100644 --- a/test/integration/client/statement_timeout-tests.js +++ b/test/integration/client/statement_timeout-tests.js @@ -59,4 +59,19 @@ if (!helper.args.native) { // statement_timeout is not supported with the native done() }) }) + + suite.test('statement_timeout actually cancels long running queries', function (done) { + var conf = getConInfo({ + 'statement_timeout': '10' // 10ms to keep tests running fast + }) + var client = new Client(conf) + client.connect(assert.success(function () { + client.query('SELECT pg_sleep( 1 )', function ( error ) { + client.end() + assert.strictEqual( error.code, '57014' ) // query_cancelled + done() + }) + })) + }) + } From ecab41c3f3d07230b24253e804971367cd04fb53 Mon Sep 17 00:00:00 2001 From: Josh Date: Thu, 31 Aug 2017 09:01:15 -0700 Subject: [PATCH 0351/1037] restore newline at end of file --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 8e3056a0e..88b672dd3 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,4 @@ build/ *.log node_modules/ package-lock.json -*.swp \ No newline at end of file +*.swp From f1336fcb003812ae43ce15cc81ac27d76f971120 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Tue, 29 Aug 2017 11:03:48 -0400 Subject: [PATCH 0352/1037] Change Makefile to use local eslint Changes the Makefile lint target to use the local copy of eslint that would be installed in node_modules rather than a global copy that may not be installed. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f710d846f..05736465b 100644 --- a/Makefile +++ b/Makefile @@ -62,4 +62,4 @@ test-pool: lint: @echo "***Starting lint***" - eslint lib + node_modules/.bin/eslint lib From dfc7214d147b687553a0a0854782d14f1c001347 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 3 Sep 2017 14:41:03 -0500 Subject: [PATCH 0353/1037] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cea334d47..3c69540ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.3.0 + +- Add support for [statement timeout](https://github.com/brianc/node-postgres/pull/1436). + ### 7.2.0 - Pinned pg-pool and pg-types to a tighter semver range. This is likely not a noticable change for you unless you were specifically installing older versions of those libraries for some reason, but making it a minor bump here just in case it could cause any confusion. From f66379f5fe01d8e9c491b0b2d1f352334783858f Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 3 Sep 2017 14:41:16 -0500 Subject: [PATCH 0354/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index eddce4902..48f2fa180 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.2.0", + "version": "7.3.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "postgres", From e087305f316b364bdbd3045f5c5339b80f757174 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 6 Sep 2017 10:41:25 -0500 Subject: [PATCH 0355/1037] Update SPONSORS.md --- SPONSORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SPONSORS.md b/SPONSORS.md index b13261b53..a49e2beac 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -9,3 +9,4 @@ node-postgres is made possible by the helpful contributors from the community we - Paul Frazee [@pfrazee](https://twitter.com/pfrazee) - Rein Petersen - Arnaud Benhamdine [@abenhamdine](https://twitter.com/abenhamdine) +- Matthew Welke From 24e485e81e125dc95492591a6fc0db16a9525d7d Mon Sep 17 00:00:00 2001 From: Hetul Patel Date: Tue, 3 Oct 2017 18:13:40 -0700 Subject: [PATCH 0356/1037] Fix closing a finished cursor without supplying a callback --- index.js | 6 +++++- test/close.js | 10 ++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 2c33a230c..af95d2875 100644 --- a/index.js +++ b/index.js @@ -149,7 +149,11 @@ Cursor.prototype.end = function (cb) { Cursor.prototype.close = function (cb) { if (this.state === 'done') { - return setImmediate(cb) + if (cb) { + return setImmediate(cb) + } else { + return + } } this.connection.close({type: 'P'}) this.connection.sync() diff --git a/test/close.js b/test/close.js index 59ea3c71a..a108fa87b 100644 --- a/test/close.js +++ b/test/close.js @@ -10,6 +10,16 @@ describe('close', function () { client.on('drain', client.end.bind(client)) }) + it('can close a finished cursor without a callback', function (done) { + var cursor = new Cursor(text) + this.client.query(cursor) + this.client.query('SELECT NOW()', done) + cursor.read(100, function (err, res) { + assert.ifError(err) + cursor.close() + }) + }) + it('closes cursor early', function (done) { var cursor = new Cursor(text) this.client.query(cursor) From 74aaced74a8115216bc1c844713037e375330785 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Sun, 15 Oct 2017 18:37:36 -0700 Subject: [PATCH 0357/1037] Avoid modifying package.json or creating package-lock when running tests with npm 5 Should save some confusion in future pull requests (#1465, #1436, #1363). --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 05736465b..a5b0bc1da 100644 --- a/Makefile +++ b/Makefile @@ -42,7 +42,7 @@ test-missing-native: @rm -rf node_modules/libpq node_modules/pg-native/index.js: - @npm i pg-native + @npm i --no-save pg-native test-native: node_modules/pg-native/index.js test-connection @echo "***Testing native bindings***" From c2da0ed97842ac22d380e28e6329eb1d570dc7b3 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Wed, 6 Sep 2017 08:13:30 -0400 Subject: [PATCH 0358/1037] Sort keywords in package.json --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 48f2fa180..383022117 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,11 @@ "version": "7.3.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ - "postgres", - "pg", + "database", "libpq", + "pg", "postgre", - "database", + "postgres", "rdbms" ], "homepage": "http://github.com/brianc/node-postgres", From 19bfb2f9b8c16589a42cc1fa4c91162f390a4451 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Wed, 6 Sep 2017 08:13:56 -0400 Subject: [PATCH 0359/1037] Add postgresql to package.json keywords --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 383022117..548816c48 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "pg", "postgre", "postgres", + "postgresql", "rdbms" ], "homepage": "http://github.com/brianc/node-postgres", From 32537d534574c4b048fce1a8947920979c30911e Mon Sep 17 00:00:00 2001 From: Robert Treat Date: Mon, 30 Oct 2017 17:16:56 -0400 Subject: [PATCH 0360/1037] Fix minor type in recent changelog entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c69540ab..1116343e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ We do not include break-fix version release in this file. ### 7.2.0 -- Pinned pg-pool and pg-types to a tighter semver range. This is likely not a noticable change for you unless you were specifically installing older versions of those libraries for some reason, but making it a minor bump here just in case it could cause any confusion. +- Pinned pg-pool and pg-types to a tighter semver range. This is likely not a noticeable change for you unless you were specifically installing older versions of those libraries for some reason, but making it a minor bump here just in case it could cause any confusion. ### 7.1.0 From 894e2f2f1eddbaa672abf1e25aac15d3723db287 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Sch=C3=A4r?= Date: Thu, 7 Sep 2017 02:01:37 +0200 Subject: [PATCH 0361/1037] Support Uint8Array values --- lib/utils.js | 7 +++++++ test/unit/utils-tests.js | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/lib/utils.js b/lib/utils.js index 1167a0760..ca5ab2a0a 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -50,6 +50,13 @@ var prepareValue = function (val, seen) { if (val instanceof Buffer) { return val } + if (ArrayBuffer.isView(val)) { + var buf = Buffer.from(val.buffer, val.byteOffset, val.byteLength) + if (buf.length === val.byteLength) { + return buf + } + return buf.slice(val.byteOffset, val.byteOffset + val.byteLength) // Node.js v4 does not support those Buffer.from params + } if (val instanceof Date) { if (defaults.parseInputDatesAsUTC) { return dateToStringUTC(val) diff --git a/test/unit/utils-tests.js b/test/unit/utils-tests.js index 680b9fb50..617fe2dd5 100644 --- a/test/unit/utils-tests.js +++ b/test/unit/utils-tests.js @@ -53,6 +53,13 @@ test('prepareValues: buffer prepared properly', function () { assert.strictEqual(buf, out) }) +test('prepareValues: Uint8Array prepared properly', function () { + var buf = new Uint8Array([1, 2, 3]).subarray(1, 2) + var out = utils.prepareValue(buf) + assert.ok(Buffer.isBuffer(out)) + assert.deepEqual(out, [2]) +}) + test('prepareValues: date prepared properly', function () { helper.setTimezoneOffset(-330) From fccf8e818ca045c09d830a5b39d7c36ec7cc3849 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 4 Nov 2017 14:21:28 -0500 Subject: [PATCH 0362/1037] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1116343e3..1516e9115 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.4.0 + +- Add support for [Uint8Array](https://github.com/brianc/node-postgres/pull/1448) values. + ### 7.3.0 - Add support for [statement timeout](https://github.com/brianc/node-postgres/pull/1436). From 9da3a85cbc6fa7b71036f736ec51bb45b6d66a3c Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 4 Nov 2017 14:21:36 -0500 Subject: [PATCH 0363/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 548816c48..576b9db5c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.3.0", + "version": "7.4.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 0b80abacaf261819f31f352b0b45264f107d42de Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 15 Nov 2017 22:44:13 -0800 Subject: [PATCH 0364/1037] Specify collation when relied on in tests Fixes #189. --- test/integration/client/api-tests.js | 2 +- test/integration/client/prepared-statement-tests.js | 4 ++-- test/integration/client/simple-query-tests.js | 4 ++-- test/native/evented-api-tests.js | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/integration/client/api-tests.js b/test/integration/client/api-tests.js index 22fe96b2f..acf403a42 100644 --- a/test/integration/client/api-tests.js +++ b/test/integration/client/api-tests.js @@ -26,7 +26,7 @@ suite.test('callback API', done => { client.query(config) client.query('INSERT INTO peep(name) VALUES ($1)', ['aaron']) - client.query('SELECT * FROM peep ORDER BY name', (err, res) => { + client.query('SELECT * FROM peep ORDER BY name COLLATE "C"', (err, res) => { assert(!err) assert.equal(res.rowCount, 3) assert.deepEqual(res.rows, [ diff --git a/test/integration/client/prepared-statement-tests.js b/test/integration/client/prepared-statement-tests.js index 6fdf72f6d..188bf8266 100644 --- a/test/integration/client/prepared-statement-tests.js +++ b/test/integration/client/prepared-statement-tests.js @@ -122,7 +122,7 @@ var suite = new helper.Suite() suite.test('with small row count', function (done) { var query = client.query(new Query({ name: 'get names', - text: 'SELECT name FROM zoom ORDER BY name', + text: 'SELECT name FROM zoom ORDER BY name COLLATE "C"', rows: 1 }, done)) @@ -132,7 +132,7 @@ var suite = new helper.Suite() suite.test('with large row count', function (done) { var query = client.query(new Query({ name: 'get names', - text: 'SELECT name FROM zoom ORDER BY name', + text: 'SELECT name FROM zoom ORDER BY name COLLATE "C"', rows: 1000 }, done)) checkForResults(query) diff --git a/test/integration/client/simple-query-tests.js b/test/integration/client/simple-query-tests.js index d7f1916a5..0c4575c5b 100644 --- a/test/integration/client/simple-query-tests.js +++ b/test/integration/client/simple-query-tests.js @@ -6,7 +6,7 @@ var Query = helper.pg.Query test('simple query interface', function () { var client = helper.client() - var query = client.query(new Query('select name from person order by name')) + var query = client.query(new Query('select name from person order by name collate "C"')) client.on('drain', client.end.bind(client)) @@ -43,7 +43,7 @@ test('prepared statements do not mutate params', function () { var params = [1] - var query = client.query(new Query('select name from person where $1 = 1 order by name', params)) + var query = client.query(new Query('select name from person where $1 = 1 order by name collate "C"', params)) assert.deepEqual(params, [1]) diff --git a/test/native/evented-api-tests.js b/test/native/evented-api-tests.js index 02a00cff4..4fac0415b 100644 --- a/test/native/evented-api-tests.js +++ b/test/native/evented-api-tests.js @@ -64,7 +64,7 @@ test('parameterized queries', function () { test('multiple parameters', function () { var client = setupClient() - var q = client.query(new Query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name', ['Aaron', 'Brian'])) + var q = client.query(new Query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name COLLATE "C"', ['Aaron', 'Brian'])) assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Aaron') assert.emits(q, 'row', function (row) { From 9870c86fde2f489b7f5ad900ac1b4b9ff514e110 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 14 Nov 2017 20:50:47 -0800 Subject: [PATCH 0365/1037] Make tests compatible with PostgreSQL 10 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PostgreSQL 10 reports its version as only `major.minor`, so it can’t be parsed with semver. The `server_version_num` setting is a major version followed by a four-digit minor version since version 10, and was a three-digit major version followed by a two-digit minor version before that. --- test/integration/client/json-type-parsing-tests.js | 2 +- .../query-error-handling-prepared-statement-tests.js | 2 +- test/integration/client/query-error-handling-tests.js | 6 +++--- test/integration/client/result-metadata-tests.js | 2 +- test/integration/connection-pool/error-tests.js | 2 +- test/integration/test-helper.js | 9 ++++----- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/test/integration/client/json-type-parsing-tests.js b/test/integration/client/json-type-parsing-tests.js index 63684d96d..58cbc3f31 100644 --- a/test/integration/client/json-type-parsing-tests.js +++ b/test/integration/client/json-type-parsing-tests.js @@ -4,7 +4,7 @@ var assert = require('assert') const pool = new helper.pg.Pool() pool.connect(assert.success(function (client, done) { - helper.versionGTE(client, '9.2.0', assert.success(function (jsonSupported) { + helper.versionGTE(client, 90200, assert.success(function (jsonSupported) { if (!jsonSupported) { console.log('skip json test on older versions of postgres') done() diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/test/integration/client/query-error-handling-prepared-statement-tests.js index a29c41a0b..9ba7567e2 100644 --- a/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -44,7 +44,7 @@ function killIdleQuery (targetQuery, cb) { var pidColName = 'procpid' var queryColName = 'current_query' client2.connect(assert.success(function () { - helper.versionGTE(client2, '9.2.0', assert.success(function (isGreater) { + helper.versionGTE(client2, 90200, assert.success(function (isGreater) { if (isGreater) { pidColName = 'pid' queryColName = 'query' diff --git a/test/integration/client/query-error-handling-tests.js b/test/integration/client/query-error-handling-tests.js index 6c1b3b7cc..67ac5d699 100644 --- a/test/integration/client/query-error-handling-tests.js +++ b/test/integration/client/query-error-handling-tests.js @@ -10,7 +10,7 @@ test('error during query execution', function() { var sleepQuery = new Query(queryText); var pidColName = 'procpid' var queryColName = 'current_query'; - helper.versionGTE(client, '9.2.0', assert.success(function(isGreater) { + helper.versionGTE(client, 90200, assert.success(function(isGreater) { if(isGreater) { pidColName = 'pid'; queryColName = 'query'; @@ -48,7 +48,7 @@ if (helper.config.native) { test('9.3 column error fields', function() { var client = new Client(helper.args); client.connect(assert.success(function() { - helper.versionGTE(client, '9.3.0', assert.success(function(isGreater) { + helper.versionGTE(client, 90300, assert.success(function(isGreater) { if(!isGreater) { return client.end(); } @@ -68,7 +68,7 @@ test('9.3 column error fields', function() { test('9.3 constraint error fields', function() { var client = new Client(helper.args); client.connect(assert.success(function() { - helper.versionGTE(client, '9.3.0', assert.success(function(isGreater) { + helper.versionGTE(client, 90300, assert.success(function(isGreater) { if(!isGreater) { console.log('skip 9.3 error field on older versions of postgres'); return client.end(); diff --git a/test/integration/client/result-metadata-tests.js b/test/integration/client/result-metadata-tests.js index 0f2e7e763..074a1598d 100644 --- a/test/integration/client/result-metadata-tests.js +++ b/test/integration/client/result-metadata-tests.js @@ -7,7 +7,7 @@ new helper.Suite().test('should return insert metadata', function () { pool.connect(assert.calls(function (err, client, done) { assert(!err) - helper.versionGTE(client, '9.0.0', assert.success(function (hasRowCount) { + helper.versionGTE(client, 90000, assert.success(function (hasRowCount) { client.query('CREATE TEMP TABLE zugzug(name varchar(10))', assert.calls(function (err, result) { assert(!err) assert.equal(result.oid, null) diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index b90ab5dfb..fbc0fdedf 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -21,7 +21,7 @@ suite.test('errors emitted on pool', (cb) => { pool.connect(assert.success(function (client2, done2) { client2.id = 2 var pidColName = 'procpid' - helper.versionGTE(client2, '9.2.0', assert.success(function (isGreater) { + helper.versionGTE(client2, 90200, assert.success(function (isGreater) { var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1' var params = ['idle'] if (!isGreater) { diff --git a/test/integration/test-helper.js b/test/integration/test-helper.js index ca844de33..fb9ac6dac 100644 --- a/test/integration/test-helper.js +++ b/test/integration/test-helper.js @@ -14,12 +14,11 @@ helper.client = function (cb) { return client } -var semver = require('semver') -helper.versionGTE = function (client, versionString, callback) { - client.query('SELECT version()', assert.calls(function (err, result) { +helper.versionGTE = function (client, testVersion, callback) { + client.query('SHOW server_version_num', assert.calls(function (err, result) { if (err) return callback(err) - var version = result.rows[0].version.split(' ')[1] - return callback(null, semver.gte(version, versionString)) + var version = parseInt(result.rows[0].server_version_num, 10) + return callback(null, version >= testVersion) })) } From 279fdeae2fdd331197d74d6f31a201bba1bdf7cf Mon Sep 17 00:00:00 2001 From: Youngwook Kim Date: Wed, 22 Nov 2017 10:17:22 +0900 Subject: [PATCH 0366/1037] Add supporting username and password for socket connections This fix adds the ability to use username and password even when using a socket. --- index.js | 8 ++++---- test/parse.js | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 0042faec0..3e04f5475 100644 --- a/index.js +++ b/index.js @@ -23,6 +23,10 @@ function parse(str) { } } + var auth = (result.auth || ':').split(':'); + config.user = auth[0]; + config.password = auth.splice(1).join(':'); + config.port = result.port; if(result.protocol == 'socket:') { config.host = decodeURI(result.pathname); @@ -40,10 +44,6 @@ function parse(str) { } config.database = pathname && decodeURI(pathname); - var auth = (result.auth || ':').split(':'); - config.user = auth[0]; - config.password = auth.splice(1).join(':'); - if (config.ssl === 'true' || config.ssl === '1') { config.ssl = true; } diff --git a/test/parse.js b/test/parse.js index 8ff3ee81d..429367330 100644 --- a/test/parse.js +++ b/test/parse.js @@ -52,6 +52,14 @@ describe('parse', function(){ subject.client_encoding.should.equal('utf8'); }); + it('initializing with unix domain socket, username and password', function(){ + var subject = parse('socket://brian:pw@/var/run/?db=mydb'); + subject.user.should.equal('brian'); + subject.password.should.equal('pw'); + subject.host.should.equal('/var/run/'); + subject.database.should.equal('mydb'); + }); + it('password contains < and/or > characters', function(){ var sourceConfig = { user:'brian', From 56633a5989c014e929d6da9981e5cfd5a07e7de2 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 6 Dec 2017 10:06:13 -0600 Subject: [PATCH 0367/1037] Update SPONSORS.md --- SPONSORS.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SPONSORS.md b/SPONSORS.md index a49e2beac..38bc0fed0 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -9,4 +9,5 @@ node-postgres is made possible by the helpful contributors from the community we - Paul Frazee [@pfrazee](https://twitter.com/pfrazee) - Rein Petersen - Arnaud Benhamdine [@abenhamdine](https://twitter.com/abenhamdine) -- Matthew Welke +- Matthew Weber +- Benjie Gillam From 6c723b2f141668f27c172368fc5de19c7ab017bd Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 6 Dec 2017 10:11:49 -0600 Subject: [PATCH 0368/1037] Update SPONSORS.md --- SPONSORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SPONSORS.md b/SPONSORS.md index 38bc0fed0..707893a5f 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -9,5 +9,6 @@ node-postgres is made possible by the helpful contributors from the community we - Paul Frazee [@pfrazee](https://twitter.com/pfrazee) - Rein Petersen - Arnaud Benhamdine [@abenhamdine](https://twitter.com/abenhamdine) +- Matthew Welke - Matthew Weber - Benjie Gillam From 929fcb73c3f5128e2d1d50eb5d62a6481d098754 Mon Sep 17 00:00:00 2001 From: benny-medflyt Date: Wed, 13 Dec 2017 11:20:29 +0200 Subject: [PATCH 0369/1037] Fix typings --- index.d.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/index.d.ts b/index.d.ts index 556375110..d0fc72149 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,14 +1,14 @@ export function parse(connectionString: string): ConnectionOptions; export interface ConnectionOptions { - host: string | null; - password: string | null; - user: string | null; - port: number | null; - database: string | null; - client_encoding: string | null; - ssl: boolean | null; + host: string; + password?: string; + user?: string; + port: string | null; + database: string | null | undefined; + client_encoding?: string | undefined; + ssl?: boolean; - application_name: string | null; - fallback_application_name: string | null; + application_name?: string; + fallback_application_name?: string; } From ece764518774690ea8ee58360ae0b6ca7b248d4d Mon Sep 17 00:00:00 2001 From: benny-medflyt Date: Wed, 13 Dec 2017 11:23:28 +0200 Subject: [PATCH 0370/1037] typings: turns out "host" can actually be `null` --- index.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.d.ts b/index.d.ts index d0fc72149..2a6574600 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,7 +1,7 @@ export function parse(connectionString: string): ConnectionOptions; export interface ConnectionOptions { - host: string; + host: string | null; password?: string; user?: string; port: string | null; From 2398e992a8e6e8e437f74637b8a38f74cad0291e Mon Sep 17 00:00:00 2001 From: jakob Date: Mon, 1 Jan 2018 18:43:18 +0000 Subject: [PATCH 0371/1037] return rowCount on insert --- index.js | 3 ++- test/index.js | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 2c33a230c..f76c7d92e 100644 --- a/index.js +++ b/index.js @@ -89,7 +89,8 @@ Cursor.prototype._sendRows = function () { }) } -Cursor.prototype.handleCommandComplete = function () { +Cursor.prototype.handleCommandComplete = function (msg) { + this._result.addCommandComplete(msg) this.connection.sync() } diff --git a/test/index.js b/test/index.js index a5b3636fc..31a676e98 100644 --- a/test/index.js +++ b/test/index.js @@ -160,4 +160,18 @@ describe('cursor', function () { done() }) }) + + it('returns rowCount on insert', function (done) { + var pgCursor = this.pgCursor + this.client.query('CREATE TEMPORARY TABLE pg_cursor_test (foo VARCHAR(1), bar VARCHAR(1))') + .then(function () { + var cursor = pgCursor('insert into pg_cursor_test values($1, $2)', ['a', 'b']) + cursor.read(1, function (err, rows, result) { + assert.ifError(err) + assert.equal(rows.length, 0) + assert.equal(result.rowCount, 1) + done() + }) + }).catch(done) + }) }) From 1e48733b206fa694d0efad62a01f4c9a22ce449b Mon Sep 17 00:00:00 2001 From: Ben Holden-Crowther Date: Sun, 31 Dec 2017 15:59:23 +0000 Subject: [PATCH 0372/1037] Update license date --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index a7b546d2d..6a6bfe763 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2010 - 2017 Brian Carlson +Copyright (c) 2010 - 2018 Brian 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 From c9ca1dad69db4dd98548dc639ffde3b3352fe2df Mon Sep 17 00:00:00 2001 From: Ben Holden-Crowther Date: Wed, 3 Jan 2018 17:09:21 +0000 Subject: [PATCH 0373/1037] License date in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ca02bfc28..82ef77088 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ The causes and solutions to common errors can be found among the [Frequently Ask ## License -Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) +Copyright (c) 2010-2018 Brian Carlson (brian.m.carlson@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 4cf67b23d48c7c37a0a8a2e5701fd297a14a49cf Mon Sep 17 00:00:00 2001 From: Pasi Eronen Date: Wed, 13 Dec 2017 12:49:06 +0200 Subject: [PATCH 0374/1037] Ignore socket hangup when ending connection also with ssl (#1344). --- lib/connection.js | 8 ++++++- test/unit/connection/error-tests.js | 37 ++++++++++++++++++++++++++--- test/unit/connection/test-helper.js | 2 +- 3 files changed, 42 insertions(+), 5 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 0f98cb062..61f2562f6 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -97,11 +97,17 @@ Connection.prototype.connect = function (port, host) { NPNProtocols: self.ssl.NPNProtocols }) self.attachListeners(self.stream) - self.emit('sslconnect') self.stream.on('error', function (error) { + // don't raise ECONNRESET errors - they can & should be ignored + // during disconnect + if (self._ending && error.code === 'ECONNRESET') { + return + } self.emit('error', error) }) + + self.emit('sslconnect') }) } diff --git a/test/unit/connection/error-tests.js b/test/unit/connection/error-tests.js index 19674608c..c8b61b432 100644 --- a/test/unit/connection/error-tests.js +++ b/test/unit/connection/error-tests.js @@ -1,31 +1,62 @@ 'use strict' var helper = require(__dirname + '/test-helper') var Connection = require(__dirname + '/../../../lib/connection') -test('connection emits stream errors', function () { +var net = require('net') + +const suite = new helper.Suite() + +suite.test('connection emits stream errors', function (done) { var con = new Connection({stream: new MemoryStream()}) assert.emits(con, 'error', function (err) { assert.equal(err.message, 'OMG!') + done() }) con.connect() con.stream.emit('error', new Error('OMG!')) }) -test('connection emits ECONNRESET errors during normal operation', function () { +suite.test('connection emits ECONNRESET errors during normal operation', function (done) { var con = new Connection({stream: new MemoryStream()}) con.connect() assert.emits(con, 'error', function (err) { assert.equal(err.code, 'ECONNRESET') + done() }) var e = new Error('Connection Reset') e.code = 'ECONNRESET' con.stream.emit('error', e) }) -test('connection does not emit ECONNRESET errors during disconnect', function () { +suite.test('connection does not emit ECONNRESET errors during disconnect', function (done) { var con = new Connection({stream: new MemoryStream()}) con.connect() var e = new Error('Connection Reset') e.code = 'ECONNRESET' con.end() con.stream.emit('error', e) + done() +}) + + +suite.test('connection does not emit ECONNRESET errors during disconnect also when using SSL', function (done) { + // our fake postgres server, which just responds with 'S' to start SSL + var socket + var server = net.createServer(function (c) { + socket = c + c.once('data', function (data) { + c.write(new Buffer('S', 'utf8')) + }) + }) + + server.listen(7778, function () { + var con = new Connection({ssl: true}) + con.connect(7778, 'localhost') + assert.emits(con, 'sslconnect', function () { + con.end() + socket.destroy() + server.close() + done() + }) + con.requestSsl() + }) }) diff --git a/test/unit/connection/test-helper.js b/test/unit/connection/test-helper.js index bcb4b25ca..53c4b0c9b 100644 --- a/test/unit/connection/test-helper.js +++ b/test/unit/connection/test-helper.js @@ -1,2 +1,2 @@ 'use strict' -require(__dirname + '/../test-helper') +module.exports = require(__dirname + '/../test-helper') From 70a8ee1334214ef3e13057217522a1d5de3dbc2d Mon Sep 17 00:00:00 2001 From: Pasi Eronen Date: Wed, 13 Dec 2017 21:28:48 +0200 Subject: [PATCH 0375/1037] Don't repeat logic for reporting stream errors --- lib/connection.js | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 61f2562f6..7b7a8abf0 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -62,14 +62,15 @@ Connection.prototype.connect = function (port, host) { self.emit('connect') }) - this.stream.on('error', function (error) { + const reportStreamError = function (error) { // don't raise ECONNRESET errors - they can & should be ignored // during disconnect if (self._ending && error.code === 'ECONNRESET') { return } self.emit('error', error) - }) + } + this.stream.on('error', reportStreamError) this.stream.on('close', function () { self.emit('end') @@ -97,15 +98,7 @@ Connection.prototype.connect = function (port, host) { NPNProtocols: self.ssl.NPNProtocols }) self.attachListeners(self.stream) - - self.stream.on('error', function (error) { - // don't raise ECONNRESET errors - they can & should be ignored - // during disconnect - if (self._ending && error.code === 'ECONNRESET') { - return - } - self.emit('error', error) - }) + self.stream.on('error', reportStreamError) self.emit('sslconnect') }) From 9825e7c733771d2ab8b8707f924789e820980de1 Mon Sep 17 00:00:00 2001 From: Pasi Eronen Date: Wed, 13 Dec 2017 21:29:08 +0200 Subject: [PATCH 0376/1037] Use Buffer.from instead of deprecated Buffer constructor --- test/unit/connection/error-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/connection/error-tests.js b/test/unit/connection/error-tests.js index c8b61b432..329e1e316 100644 --- a/test/unit/connection/error-tests.js +++ b/test/unit/connection/error-tests.js @@ -44,7 +44,7 @@ suite.test('connection does not emit ECONNRESET errors during disconnect also wh var server = net.createServer(function (c) { socket = c c.once('data', function (data) { - c.write(new Buffer('S', 'utf8')) + c.write(Buffer.from('S')) }) }) From a664983cbb6317a7d7e1fdae87583658ab8920db Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 5 Jan 2018 13:41:36 -0600 Subject: [PATCH 0377/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 576b9db5c..7eeff6c43 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.4.0", + "version": "7.4.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From be57714f164d3d5c8b82f3e39b75b22cc43f4800 Mon Sep 17 00:00:00 2001 From: Ben Holden-Crowther Date: Tue, 9 Jan 2018 21:06:45 +0000 Subject: [PATCH 0378/1037] spelling corrections --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1516e9115..3a2aaf45a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -66,7 +66,7 @@ var pg = require('pg') var pool = new pg.Pool() -// your friendly neighboorhood pool interface, without the singleton +// your friendly neighborhood pool interface, without the singleton pool.connect(function(err, client, done) { // ... }) @@ -113,7 +113,7 @@ client.query('SELECT $1::text as name', ['brianc']) - Add option to parse JS date objects in query parameters as [UTC](https://github.com/brianc/node-postgres/pull/943) ### v4.4.0 -- Warn to `stderr` if a named query exceeds 63 characters which is the max lenght supported by postgres. +- Warn to `stderr` if a named query exceeds 63 characters which is the max length supported by postgres. ### v4.3.0 - Unpin `pg-types` semver. Allow it to float against `pg-types@1.x`. From 94d38f941e9039a2b09a560bdd1410676920edbd Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 9 Jan 2018 21:39:40 -0800 Subject: [PATCH 0379/1037] Capitalize some parts of the README --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 82ef77088..2aa5675f3 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ NPM version NPM downloads -Non-blocking PostgreSQL client for node.js. Pure JavaScript and optional native libpq bindings. +Non-blocking PostgreSQL client for Node.js. Pure JavaScript and optional native libpq bindings. ## Install @@ -19,9 +19,9 @@ $ npm install pg ### Features -* Pure JavaScript client and native libpq bindings share _the same api_ +* Pure JavaScript client and native libpq bindings share _the same API_ * Connection pooling -* Extensible js<->postgresql data-type coercion +* Extensible JS<->PostgreSQL data-type coercion * Supported PostgreSQL features * Parameterized queries * Named statements with query plan caching @@ -35,18 +35,18 @@ The entire list can be found on our [wiki](https://github.com/brianc/node-postgr ## Support -node-postgres is free software. If you encounter a bug with the library please open an issue on the [github repo](https://github.com/brianc/node-postgres). If you have questions unanswered by the documentation please open an issue pointing out how the documentation was unclear & I will do my best to make it better! +node-postgres is free software. If you encounter a bug with the library please open an issue on the [GitHub repo](https://github.com/brianc/node-postgres). If you have questions unanswered by the documentation please open an issue pointing out how the documentation was unclear & I will do my best to make it better! When you open an issue please provide: -- version of node -- version of postgres +- version of Node +- version of Postgres - smallest possible snippet of code to reproduce the problem You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on Twitter. ### Professional Support -I offer professional support for node-postgres. I provide implementation, training, and many years of expertise on how to build applications with node, express, PostgreSQL, and react/redux. Please contact me at [brian.m.carlson@gmail.com](mailto:brian.m.carlson@gmail.com) to discuss how I can help your company be more successful! +I offer professional support for node-postgres. I provide implementation, training, and many years of expertise on how to build applications with Node, Express, PostgreSQL, and React/Redux. Please contact me at [brian.m.carlson@gmail.com](mailto:brian.m.carlson@gmail.com) to discuss how I can help your company be more successful! ### Sponsorship :star: @@ -63,7 +63,7 @@ I will __happily__ accept your pull request if it: ## Troubleshooting and FAQ -The causes and solutions to common errors can be found among the [Frequently Asked Questions(FAQ)](https://github.com/brianc/node-postgres/wiki/FAQ) +The causes and solutions to common errors can be found among the [Frequently Asked Questions (FAQ)](https://github.com/brianc/node-postgres/wiki/FAQ) ## License From 3f1d7b9bc64d8b5c40822e1c9366e4a6fb9103fa Mon Sep 17 00:00:00 2001 From: Ruben Bridgewater Date: Sat, 10 Mar 2018 22:09:23 +0100 Subject: [PATCH 0380/1037] Remove `noAssert` argument The support for the `noAssert` argument dropped in the upcoming Node.js v.10.x. All input is then validated no matter if this is set to true or not. Just remove the argument because of that. --- lib/connection.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 7b7a8abf0..49121aedd 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -617,13 +617,13 @@ Connection.prototype.parsed = function (buffer, length) { } Connection.prototype.parseInt32 = function (buffer) { - var value = buffer.readInt32BE(this.offset, true) + var value = buffer.readInt32BE(this.offset) this.offset += 4 return value } Connection.prototype.parseInt16 = function (buffer) { - var value = buffer.readInt16BE(this.offset, true) + var value = buffer.readInt16BE(this.offset) this.offset += 2 return value } From 875236fc0bfa8d3828ee88407614ff08fb76e9ee Mon Sep 17 00:00:00 2001 From: "C. T. Lin" Date: Wed, 14 Mar 2018 22:43:52 +0800 Subject: [PATCH 0381/1037] use net.Socket instead of net.Stream `net.Stream` is a undocumented legacy naming from node 0.x https://github.com/nodejs/node/blob/4ae320f2b3c745402955019d6a57a22ee2b8d3bd/lib/net.js#L1762 --- lib/connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/connection.js b/lib/connection.js index 49121aedd..8744bbe32 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -19,7 +19,7 @@ var BINARY_MODE = 1 var Connection = function (config) { EventEmitter.call(this) config = config || {} - this.stream = config.stream || new net.Stream() + this.stream = config.stream || new net.Socket() this._keepAlive = config.keepAlive this.lastBuffer = false this.lastOffset = 0 From 8fb641ee91b0f8474559983520485e90c3a94d55 Mon Sep 17 00:00:00 2001 From: Elexy Date: Wed, 4 Apr 2018 15:46:46 +0200 Subject: [PATCH 0382/1037] upgrade testing node versions --- .travis.yml | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3abcf8a98..dbe804cef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,28 +8,31 @@ env: matrix: include: + - node_js: "lts/boron" + addons: + postgresql: "9.6" - node_js: "lts/argon" addons: postgresql: "9.6" - - node_js: "lts/boron" + - node_js: "9" + addons: + postgresql: "9.6" + - node_js: "lts/carbon" addons: postgresql: "9.1" dist: precise - - node_js: "lts/boron" + - node_js: "lts/carbon" addons: postgresql: "9.2" - - node_js: "lts/boron" + - node_js: "lts/carbon" addons: postgresql: "9.3" - - node_js: "lts/boron" + - node_js: "lts/carbon" addons: postgresql: "9.4" - - node_js: "lts/boron" + - node_js: "lts/carbon" addons: postgresql: "9.5" - - node_js: "lts/boron" - addons: - postgresql: "9.6" - - node_js: "8" + - node_js: "lts/carbon" addons: postgresql: "9.6" From 2f14cb1a0f0cc6a6d35466edd939a24ff9a0e22d Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Fri, 6 Apr 2018 16:28:03 +0000 Subject: [PATCH 0383/1037] Update CI versions (#88) * Update CI versions PostgreSQL 9.1 is no longer available on 14.04. * Add Node 9 to CI --- .travis.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.travis.yml b/.travis.yml index e1a0ce70c..cd2db492f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,13 @@ matrix: - node_js: "4" addons: postgresql: "9.1" + dist: precise - node_js: "6" addons: postgresql: "9.4" + - node_js: "8" + addons: + postgresql: "9.6" + - node_js: "9" + addons: + postgresql: "9.6" From b0c60cf288cf47c31071948a703fb7b28db9a81b Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Thu, 3 May 2018 07:29:11 -0400 Subject: [PATCH 0384/1037] Add node v10 to travis matrix --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index dbe804cef..e0fb505d9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,9 @@ matrix: - node_js: "9" addons: postgresql: "9.6" + - node_js: "10" + addons: + postgresql: "9.6" - node_js: "lts/carbon" addons: postgresql: "9.1" From 272e9a5998fc631418642aed7ec64e3a9157d089 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Thu, 3 May 2018 07:57:47 -0400 Subject: [PATCH 0385/1037] Change network partition test to use socket.destroy() --- test/integration/client/network-partition-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/client/network-partition-tests.js b/test/integration/client/network-partition-tests.js index 95eca8e73..70dcc92b7 100644 --- a/test/integration/client/network-partition-tests.js +++ b/test/integration/client/network-partition-tests.js @@ -46,7 +46,7 @@ Server.prototype.start = function (cb) { } Server.prototype.drop = function () { - this.socket.end() + this.socket.destroy() } Server.prototype.close = function (cb) { From 860928e2d56b6c8a799f90bbee2e3d517fd32c13 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Thu, 3 May 2018 08:01:43 -0400 Subject: [PATCH 0386/1037] Change test to use Buffer.from(...) --- test/integration/client/network-partition-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/client/network-partition-tests.js b/test/integration/client/network-partition-tests.js index 70dcc92b7..e7198a47d 100644 --- a/test/integration/client/network-partition-tests.js +++ b/test/integration/client/network-partition-tests.js @@ -22,7 +22,7 @@ Server.prototype.start = function (cb) { this.socket.on('data', function (data) { // deny request for SSL if (data.length == 8) { - this.socket.write(new Buffer('N', 'utf8')) + this.socket.write(Buffer.from('N', 'utf8')) // consider all authentication requests as good } else if (!data[0]) { this.socket.write(buffers.authenticationOk()) From 0902d145f4e177404e3d142857a4f68fc1aa103b Mon Sep 17 00:00:00 2001 From: Vratislav Kalenda Date: Wed, 4 Apr 2018 22:28:38 +0200 Subject: [PATCH 0387/1037] fix: end stream connection --- lib/connection.js | 4 +++- test/unit/connection/outbound-sending-tests.js | 1 + test/unit/test-helper.js | 11 +++++++++-- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 8744bbe32..d2cf69ece 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -309,7 +309,9 @@ Connection.prototype.end = function () { // 0x58 = 'X' this.writer.add(emptyBuffer) this._ending = true - return this.stream.write(END_BUFFER) + return this.stream.write(END_BUFFER, () => { + this.stream.end() + }) } Connection.prototype.close = function (msg, more) { diff --git a/test/unit/connection/outbound-sending-tests.js b/test/unit/connection/outbound-sending-tests.js index e9e148c14..b8b72a214 100644 --- a/test/unit/connection/outbound-sending-tests.js +++ b/test/unit/connection/outbound-sending-tests.js @@ -183,6 +183,7 @@ test('sends end command', function () { con.end() var expected = Buffer.from([0x58, 0, 0, 0, 4]) assert.received(stream, expected) + assert.equal(stream.closed, true) }) test('sends describe command', function () { diff --git a/test/unit/test-helper.js b/test/unit/test-helper.js index 6cd2d24e0..04b73f372 100644 --- a/test/unit/test-helper.js +++ b/test/unit/test-helper.js @@ -13,12 +13,19 @@ helper.sys.inherits(MemoryStream, EventEmitter) var p = MemoryStream.prototype -p.write = function (packet) { +p.write = function (packet, cb) { this.packets.push(packet) + if(cb){ + cb(); + } } -p.setKeepAlive = function () {} +p.end = function() { + p.closed = true; +} +p.setKeepAlive = function () {} +p.closed = false; p.writable = true const createClient = function () { From 5d32be4a907b8016622bc742ae5985ba33569750 Mon Sep 17 00:00:00 2001 From: Matthew Blewitt Date: Mon, 12 Feb 2018 21:35:21 +0000 Subject: [PATCH 0388/1037] Handle SSL negotiation errors more robustly This commit adds some finer grained detail to handling the postmaster's response to SSL negotiation packets, by accounting for the possibility of an 'E' byte being sent back, and emitting an appropriate error. In the naive case, the postmaster will respond with either 'S' (proceed with an SSL connection) or 'N' (SSL is not supported). However, the current if statement doesn't account for an 'E' byte being returned by the postmaster, where an error is encountered (perhaps unable to fork due to being out of memory). By adding this case, we can prevent confusing error messages when SSL is enforced and the postmaster returns an error after successful SSL connections. This also brings the connection handling further in line with libpq, where 'E' is handled similarly as of this commit: https://github.com/postgres/postgres/commit/a49fbaaf8d461ff91912c30b3563d54649474c80 Given that there are no longer pre-7.0 databases out in the wild, I believe this is a safe change to make, and should not break backwards compatibility (unless matching on error message content). * Replace if statement with switch, to catch 'S', 'E' and 'N' bytes returned by the postmaster * Return an Error for non 'S' or 'N' cases * Expand and restructure unit tests for SSL negotiation packets --- lib/connection.js | 9 ++++- test/unit/connection/error-tests.js | 62 ++++++++++++++++++++--------- 2 files changed, 51 insertions(+), 20 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index d2cf69ece..208f05749 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -82,8 +82,13 @@ Connection.prototype.connect = function (port, host) { this.stream.once('data', function (buffer) { var responseCode = buffer.toString('utf8') - if (responseCode !== 'S') { - return self.emit('error', new Error('The server does not support SSL connections')) + switch (responseCode) { + case 'N': + return self.emit('error', new Error('The server does not support SSL connections')) + case 'S': + break + default: + return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') self.stream = tls.connect({ diff --git a/test/unit/connection/error-tests.js b/test/unit/connection/error-tests.js index 329e1e316..f39187cf7 100644 --- a/test/unit/connection/error-tests.js +++ b/test/unit/connection/error-tests.js @@ -37,26 +37,52 @@ suite.test('connection does not emit ECONNRESET errors during disconnect', funct done() }) +var SSLNegotiationPacketTests = [ + { + testName: 'connection does not emit ECONNRESET errors during disconnect also when using SSL', + errorMessage: null, + response: 'S', + responseType: 'sslconnect' + }, + { + testName: 'connection emits an error when SSL is not supported', + errorMessage: 'The server does not support SSL connections', + response: 'N', + responseType: 'error' + }, + { + testName: 'connection emits an error when postmaster responds to SSL negotiation packet', + errorMessage: 'There was an error establishing an SSL connection', + response: 'E', + responseType: 'error' + } +] -suite.test('connection does not emit ECONNRESET errors during disconnect also when using SSL', function (done) { - // our fake postgres server, which just responds with 'S' to start SSL - var socket - var server = net.createServer(function (c) { - socket = c - c.once('data', function (data) { - c.write(Buffer.from('S')) +for (var i = 0; i < SSLNegotiationPacketTests.length; i++) { + var tc = SSLNegotiationPacketTests[i] + suite.test(tc.testName, function (done) { + // our fake postgres server + var socket + var server = net.createServer(function (c) { + socket = c + c.once('data', function (data) { + c.write(Buffer.from(tc.response)) + }) }) - }) - server.listen(7778, function () { - var con = new Connection({ssl: true}) - con.connect(7778, 'localhost') - assert.emits(con, 'sslconnect', function () { - con.end() - socket.destroy() - server.close() - done() + server.listen(7778, function () { + var con = new Connection({ssl: true}) + con.connect(7778, 'localhost') + assert.emits(con, tc.responseType, function (err) { + if (err) { + assert.equal(err.message, tc.errorMessage) + } + con.end() + socket.destroy() + server.close() + done() + }) + con.requestSsl() }) - con.requestSsl() }) -}) +} From 7dd3b50e41a540a15eba5edb4371f4f7a3656845 Mon Sep 17 00:00:00 2001 From: Matthew Blewitt Date: Wed, 14 Feb 2018 18:49:38 +0000 Subject: [PATCH 0389/1037] Add guard to test to not check errors for empty error messages --- test/unit/connection/error-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/connection/error-tests.js b/test/unit/connection/error-tests.js index f39187cf7..d714c0585 100644 --- a/test/unit/connection/error-tests.js +++ b/test/unit/connection/error-tests.js @@ -74,7 +74,7 @@ for (var i = 0; i < SSLNegotiationPacketTests.length; i++) { var con = new Connection({ssl: true}) con.connect(7778, 'localhost') assert.emits(con, tc.responseType, function (err) { - if (err) { + if (err && tc.errorMessage) { assert.equal(err.message, tc.errorMessage) } con.end() From 3eb73751f5564cd8f6618fe55862549d058f510a Mon Sep 17 00:00:00 2001 From: Matthew Blewitt Date: Thu, 15 Feb 2018 18:33:58 +0000 Subject: [PATCH 0390/1037] Expand test to check for expected and unexpected errors --- test/unit/connection/error-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/connection/error-tests.js b/test/unit/connection/error-tests.js index d714c0585..f72e9ff04 100644 --- a/test/unit/connection/error-tests.js +++ b/test/unit/connection/error-tests.js @@ -74,7 +74,7 @@ for (var i = 0; i < SSLNegotiationPacketTests.length; i++) { var con = new Connection({ssl: true}) con.connect(7778, 'localhost') assert.emits(con, tc.responseType, function (err) { - if (err && tc.errorMessage) { + if (tc.errorMessage !== null || err) { assert.equal(err.message, tc.errorMessage) } con.end() From 938952760974b6b07900e2b28dafa64382f2e3b1 Mon Sep 17 00:00:00 2001 From: Matthew Blewitt Date: Thu, 22 Feb 2018 15:49:44 +0000 Subject: [PATCH 0391/1037] Add comments to case branches, explaining code meanings --- lib/connection.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 208f05749..7acf16e26 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -83,11 +83,11 @@ Connection.prototype.connect = function (port, host) { this.stream.once('data', function (buffer) { var responseCode = buffer.toString('utf8') switch (responseCode) { - case 'N': + case 'N': // Server does not support SSL connections return self.emit('error', new Error('The server does not support SSL connections')) - case 'S': + case 'S': // Server supports SSL connections, continue with a secure connection break - default: + default: // Any other response byte, including 'E' (ErrorResponse) indicating a server error return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') From 831dfb1b4cd9acf61a7d9ca4b64345e021429765 Mon Sep 17 00:00:00 2001 From: Justin Jaffray Date: Sat, 30 Sep 2017 23:50:31 -0400 Subject: [PATCH 0392/1037] Pass through portal properly This happened to work before because `Query.portalName` was undefined, but in order to be able to set the portal explicitly it should be using `Query.portal`. --- lib/query.js | 6 +- test/unit/client/prepared-statement-tests.js | 71 +++++++++++++++++++- 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/lib/query.js b/lib/query.js index 4d483ac7a..8766e1a3a 100644 --- a/lib/query.js +++ b/lib/query.js @@ -175,7 +175,7 @@ Query.prototype.handlePortalSuspended = function (connection) { Query.prototype._getRows = function (connection, rows) { connection.execute({ - portal: this.portalName, + portal: this.portal, rows: rows }, true) connection.flush() @@ -201,7 +201,7 @@ Query.prototype.prepare = function (connection) { // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY connection.bind({ - portal: self.portalName, + portal: self.portal, statement: self.name, values: self.values, binary: self.binary @@ -209,7 +209,7 @@ Query.prototype.prepare = function (connection) { connection.describe({ type: 'P', - name: self.portalName || '' + name: self.portal || '' }, true) this._getRows(connection, this.rows) diff --git a/test/unit/client/prepared-statement-tests.js b/test/unit/client/prepared-statement-tests.js index 0dc9e80a1..08db8860b 100644 --- a/test/unit/client/prepared-statement-tests.js +++ b/test/unit/client/prepared-statement-tests.js @@ -65,7 +65,7 @@ test('bound command', function () { test('bind argument', function () { assert.equal(bindArg.statement, null) - assert.equal(bindArg.portal, null) + assert.equal(bindArg.portal, '') assert.lengthIs(bindArg.values, 1) assert.equal(bindArg.values[0], 'hi') }) @@ -76,7 +76,7 @@ test('bound command', function () { }) test('execute argument', function () { - assert.equal(executeArg.portal, null) + assert.equal(executeArg.portal, '') assert.equal(executeArg.rows, null) }) @@ -86,3 +86,70 @@ test('bound command', function () { }) }) }) + +var portalClient = helper.client() +var portalCon = portalClient.connection +var portalParseArg = null +portalCon.parse = function (arg) { + portalParseArg = arg + process.nextTick(function () { + portalCon.emit('parseComplete') + }) +} + +var portalBindArg = null +portalCon.bind = function (arg) { + portalBindArg = arg + process.nextTick(function () { + portalCon.emit('bindComplete') + }) +} + +var portalExecuteArg = null +portalCon.execute = function (arg) { + portalExecuteArg = arg + process.nextTick(function () { + portalCon.emit('rowData', { fields: [] }) + portalCon.emit('commandComplete', { text: '' }) + }) +} + +var portalDescribeArg = null +portalCon.describe = function (arg) { + portalDescribeArg = arg + process.nextTick(function () { + portalCon.emit('rowDescription', { fields: [] }) + }) +} + +portalCon.flush = function () { +} +portalCon.sync = function () { + process.nextTick(function () { + portalCon.emit('readyForQuery') + }) +} + +test('prepared statement with explicit portal', function () { + assert.ok(portalClient.connection.emit('readyForQuery')) + + var query = portalClient.query(new Query({ + text: 'select * from X where name = $1', + portal: 'myportal', + values: ['hi'] + })) + + assert.emits(query, 'end', function () { + test('bind argument', function () { + assert.equal(portalBindArg.portal, 'myportal') + }) + + test('describe argument', function () { + assert.equal(portalDescribeArg.name, 'myportal') + }) + + test('execute argument', function () { + assert.equal(portalExecuteArg.portal, 'myportal') + }) + }) +}) From 49054717b4ec0c6d477f04c2becd1f9680b2d13a Mon Sep 17 00:00:00 2001 From: Toby Brain Date: Tue, 5 Sep 2017 12:05:00 +1000 Subject: [PATCH 0393/1037] Add ability to specify checkServerIdentity callback --- lib/connection.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/connection.js b/lib/connection.js index 7acf16e26..39469a309 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -94,6 +94,7 @@ Connection.prototype.connect = function (port, host) { self.stream = tls.connect({ socket: self.stream, servername: host, + checkServerIdentity: self.ssl.checkServerIdentity, rejectUnauthorized: self.ssl.rejectUnauthorized, ca: self.ssl.ca, pfx: self.ssl.pfx, From 72db7902fa9edb5fb9d436c27379dd74d4c9452f Mon Sep 17 00:00:00 2001 From: contra Date: Mon, 2 Apr 2018 13:55:10 -0400 Subject: [PATCH 0394/1037] dont use dynamic functions to parse rows, closes #1417 --- lib/result.js | 35 +++++++++++------------------------ package.json | 1 - 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/lib/result.js b/lib/result.js index 7dfd116f0..1e6bf849d 100644 --- a/lib/result.js +++ b/lib/result.js @@ -8,7 +8,6 @@ */ var types = require('pg-types') -var escape = require('js-string-escape') // result object returned from query // in the 'end' event and also @@ -65,29 +64,24 @@ Result.prototype._parseRowAsArray = function (rowData) { return row } -// rowData is an array of text or binary values -// this turns the row into a JavaScript object Result.prototype.parseRow = function (rowData) { - return new this.RowCtor(this._parsers, rowData) + var row = {} + for (var i = 0, len = rowData.length; i < len; i++) { + var rawValue = rowData[i] + var field = this.fields[i].name + if (rawValue !== null) { + row[field] = this._parsers[i](rawValue) + } else { + row[field] = null + } + } + return row } Result.prototype.addRow = function (row) { this.rows.push(row) } -var inlineParser = function (fieldName, i) { - return "\nthis['" + - // fields containing single quotes will break - // the evaluated javascript unless they are escaped - // see https://github.com/brianc/node-postgres/issues/507 - // Addendum: However, we need to make sure to replace all - // occurences of apostrophes, not just the first one. - // See https://github.com/brianc/node-postgres/issues/934 - escape(fieldName) + - "'] = " + - 'rowData[' + i + '] == null ? null : parsers[' + i + '](rowData[' + i + ']);' -} - Result.prototype.addFields = function (fieldDescriptions) { // clears field definitions // multiple query statements in 1 action can result in multiple sets @@ -97,18 +91,11 @@ Result.prototype.addFields = function (fieldDescriptions) { this.fields = [] this._parsers = [] } - var ctorBody = '' for (var i = 0; i < fieldDescriptions.length; i++) { var desc = fieldDescriptions[i] this.fields.push(desc) var parser = this._getTypeParser(desc.dataTypeID, desc.format || 'text') this._parsers.push(parser) - // this is some craziness to compile the row result parsing - // results in ~60% speedup on large query result sets - ctorBody += inlineParser(desc.name, i) - } - if (!this.rowAsArray) { - this.RowCtor = Function('parsers', 'rowData', ctorBody) } } diff --git a/package.json b/package.json index 7eeff6c43..3aa3de865 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "main": "./lib", "dependencies": { "buffer-writer": "1.0.1", - "js-string-escape": "1.0.1", "packet-reader": "0.3.1", "pg-connection-string": "0.1.3", "pg-pool": "~2.0.3", From fabf39c6063d01fe76c61b2d80d221a7c9410604 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Fri, 4 May 2018 17:59:39 +0000 Subject: [PATCH 0395/1037] Count only test query itself (#87) * Count only test query itself This breaks more obviously in PostgreSQL 10 (https://wiki.postgresql.org/wiki/New_in_postgres_10#Significant_Expansion_of_Wait_Events_in_pg_stat_activity). * Fix query counting for PostgreSQL 9.1 --- test/sizing.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/test/sizing.js b/test/sizing.js index 9e926877d..b310b3d35 100644 --- a/test/sizing.js +++ b/test/sizing.js @@ -33,11 +33,17 @@ describe('pool size of 1', () => { 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') - }) + + // the query text column name changed in PostgreSQL 9.2 + const versionResult = yield pool.query('SHOW server_version_num') + const version = parseInt(versionResult.rows[0].server_version_num, 10) + const queryColumn = version < 90200 ? 'current_query' : 'query' + + const queryText = 'SELECT COUNT(*) as counts FROM pg_stat_activity WHERE ' + queryColumn + ' = $1' + const queries = _.times(20, () => + pool.query(queryText, [queryText])) const results = yield Promise.all(queries) - const counts = results.map(res => parseInt(res.rows[0].counts), 10) + const counts = results.map(res => parseInt(res.rows[0].counts, 10)) expect(counts).to.eql(_.times(20, i => 1)) return yield pool.end() })) From 1871d0f9e18330afe8149ff5df8b3e54ac71469a Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Fri, 4 May 2018 18:04:42 +0000 Subject: [PATCH 0396/1037] Remove timed-out checkouts from queue correctly (#86) * Add failing test for correct removal from checkout queue on timeout * Remove timed-out checkouts from queue correctly Fixes #85. --- index.js | 20 +++++++++++++++----- test/connection-timeout.js | 22 ++++++++++++++++++++++ 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/index.js b/index.js index af86134b4..85f36c96a 100644 --- a/index.js +++ b/index.js @@ -3,6 +3,14 @@ const EventEmitter = require('events').EventEmitter const NOOP = function () { } +const remove = (list, value) => { + const i = list.indexOf(value) + + if (i !== -1) { + list.splice(i, 1) + } +} + const removeWhere = (list, predicate) => { const i = list.findIndex(predicate) @@ -157,18 +165,20 @@ class Pool extends EventEmitter { return result } + const queueCallback = (err, res, done) => { + clearTimeout(tid) + response.callback(err, res, done) + } + // 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) + remove(this._pendingQueue, queueCallback) 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) - }) + this._pendingQueue.push(queueCallback) return result } diff --git a/test/connection-timeout.js b/test/connection-timeout.js index 8f3239b30..f7a2fd8ea 100644 --- a/test/connection-timeout.js +++ b/test/connection-timeout.js @@ -73,6 +73,28 @@ describe('connection timeout', () => { }) }) + it('should not break further pending checkouts on a timeout', (done) => { + const pool = new Pool({ connectionTimeoutMillis: 200, max: 1 }) + pool.connect((err, client, releaseOuter) => { + expect(err).to.be(undefined) + + pool.connect((err, client) => { + expect(err).to.be.an(Error) + expect(client).to.be(undefined) + releaseOuter() + }) + + setTimeout(() => { + pool.connect((err, client, releaseInner) => { + expect(err).to.be(undefined) + expect(client).to.not.be(undefined) + releaseInner() + pool.end(done) + }) + }, 100) + }) + }) + it('should timeout on query if all clients are busy', (done) => { const pool = new Pool({ connectionTimeoutMillis: 100, max: 1 }) pool.connect((err, client, release) => { From 6b2883d2904debeb5ece69865647fa913278f8b2 Mon Sep 17 00:00:00 2001 From: Yuval Greenfield Date: Fri, 4 May 2018 11:06:32 -0700 Subject: [PATCH 0397/1037] terminiated -> terminated (#78) --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 85f36c96a..02c66f2df 100644 --- a/index.js +++ b/index.js @@ -224,7 +224,7 @@ class Pool extends EventEmitter { // 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' + err.message = 'Connection terminated due to connection timeout' } cb(err, undefined, NOOP) } else { From 277dc508daea03a8f6c0bcc3c534cab5b2501b12 Mon Sep 17 00:00:00 2001 From: Yuval Greenfield Date: Fri, 4 May 2018 11:06:49 -0700 Subject: [PATCH 0398/1037] Clarifying pool connect logging (#73) Existing log code was outputting 'connecting new client' twice and saying 'new client connected', creating a false impression when an error (like a timeout) was present. --- index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 02c66f2df..ab74209f1 100644 --- a/index.js +++ b/index.js @@ -196,7 +196,7 @@ class Pool extends EventEmitter { this.emit('error', err, client) } - this.log('connecting new client') + this.log('checking client timeout') // connection timeout logic let tid @@ -215,12 +215,12 @@ class Pool extends EventEmitter { this.log('connecting new client') client.connect((err) => { - this.log('new client connected') if (tid) { clearTimeout(tid) } client.on('error', idleListener) if (err) { + this.log('client failed to connect', err) // remove the dead client from our list of clients this._clients = this._clients.filter(c => c !== client) if (timeoutHit) { @@ -228,6 +228,7 @@ class Pool extends EventEmitter { } cb(err, undefined, NOOP) } else { + this.log('new client connected') client.release = release.bind(this, client) this.emit('connect', client) this.emit('acquire', client) From 83ede28e181fba62c325ae18a6dcd428777e9f1c Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 4 May 2018 14:01:26 -0500 Subject: [PATCH 0399/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3aa3de865..c5274b4b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.4.1", + "version": "7.4.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 7de137f9f88611b8fcae5539aa90b6037133f1f1 Mon Sep 17 00:00:00 2001 From: Matt Keas Date: Sat, 5 May 2018 09:47:34 -0500 Subject: [PATCH 0400/1037] tls.connect({checkServerIdentity}) option cannot be a null - must be a method or not exist. Defaults to built-in `tls.checkServerIdentity` method in the event one is not passed into `pgConfig.ssl` Found breaking in v9.4.2 vs v9.4.1 a la 49054717b4ec0c6d477f04c2becd1f9680b2d13a cc @tobio @brianc --- lib/connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/connection.js b/lib/connection.js index 39469a309..799ab4ed8 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -94,7 +94,7 @@ Connection.prototype.connect = function (port, host) { self.stream = tls.connect({ socket: self.stream, servername: host, - checkServerIdentity: self.ssl.checkServerIdentity, + checkServerIdentity: self.ssl.checkServerIdentity || tls.checkServerIdentity, rejectUnauthorized: self.ssl.rejectUnauthorized, ca: self.ssl.ca, pfx: self.ssl.pfx, From 3ac356a812f473ad1f0a748b662524f9b7913583 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 7 May 2018 10:07:10 -0500 Subject: [PATCH 0401/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c5274b4b2..d3569be96 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.4.2", + "version": "7.4.3", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 2dc5c6864b4b91ab96622cc638b6932259dab6f9 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Sat, 16 Jun 2018 18:34:59 -0400 Subject: [PATCH 0402/1037] Change network partition test to wait for client socket creation prior to destroy --- test/integration/client/network-partition-tests.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/integration/client/network-partition-tests.js b/test/integration/client/network-partition-tests.js index e7198a47d..8eaf5d0d7 100644 --- a/test/integration/client/network-partition-tests.js +++ b/test/integration/client/network-partition-tests.js @@ -65,10 +65,12 @@ var testServer = function (server, cb) { server.close(cb) }) - // after 50 milliseconds, drop the client - setTimeout(function () { - server.drop() - }, 50) + server.server.on('connection', () => { + // after 50 milliseconds, drop the client + setTimeout(function () { + server.drop() + }, 50) + }) // blow up if we don't receive an error var timeoutId = setTimeout(function () { From 7eabfbe0ba0593fd04891e30b84fd0c19db18bda Mon Sep 17 00:00:00 2001 From: Savannah Mastrangelo <36178047+savvymas@users.noreply.github.com> Date: Wed, 20 Jun 2018 12:29:41 -0400 Subject: [PATCH 0403/1037] Add repo to package.json Without this pages like https://www.npmjs.com/package/pg-cursor don't link back correctly. --- package.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/package.json b/package.json index c5e7f32a1..e3b46b938 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,10 @@ "scripts": { "test": " mocha && eslint ." }, + "repository": { + "type": "git", + "url": "git://github.com/brianc/node-pg-cursor.git" + }, "author": "Brian M. Carlson", "license": "MIT", "devDependencies": { From 2ea5f91f4ac72f90c956b0e4edb658585fb42cf2 Mon Sep 17 00:00:00 2001 From: Dominic Letz Date: Mon, 9 Jul 2018 11:46:56 +0800 Subject: [PATCH 0404/1037] Replace poolSize by max in error test --- test/integration/connection-pool/error-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index fbc0fdedf..b7ab986d0 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -3,7 +3,7 @@ var helper = require('./test-helper') const pg = helper.pg // first make pool hold 2 clients -pg.defaults.poolSize = 2 +pg.defaults.max = 2 const pool = new pg.Pool() From 28e66ccd4be1f3607b4d6fe457704785b8d6d337 Mon Sep 17 00:00:00 2001 From: Dominic Letz Date: Mon, 9 Jul 2018 14:19:55 +0800 Subject: [PATCH 0405/1037] Use pool constructor to pass pool size --- test/integration/connection-pool/error-tests.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index b7ab986d0..17cdcc47f 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -2,10 +2,8 @@ var helper = require('./test-helper') const pg = helper.pg -// first make pool hold 2 clients -pg.defaults.max = 2 - -const pool = new pg.Pool() +// make pool hold 2 clients +const pool = new pg.Pool({ max: 2 }) const suite = new helper.Suite() suite.test('connecting to invalid port', (cb) => { From 9bfd4bff40e122ee09934397f1b67aaca75b55e4 Mon Sep 17 00:00:00 2001 From: Mike van Rossum Date: Tue, 17 Jul 2018 01:07:00 +0800 Subject: [PATCH 0406/1037] [test] g/provded/provided --- test/integration/client/api-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/client/api-tests.js b/test/integration/client/api-tests.js index acf403a42..e18c3749c 100644 --- a/test/integration/client/api-tests.js +++ b/test/integration/client/api-tests.js @@ -87,7 +87,7 @@ suite.test('raises error if cannot connect', function () { ) }) -suite.test('query errors are handled and do not bubble if callback is provded', function (done) { +suite.test('query errors are handled and do not bubble if callback is provided', function (done) { const pool = new pg.Pool() pool.connect( assert.calls(function (err, client, release) { From 00d749cdfa62c483a2327d68f57eac1ebdbe10c4 Mon Sep 17 00:00:00 2001 From: Gajus Kuizinas Date: Sun, 29 Jul 2018 21:29:27 +0100 Subject: [PATCH 0407/1037] refactor: simplify the escapeIdentifier logic --- lib/client.js | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/lib/client.js b/lib/client.js index 3228571d5..0d023db7c 100644 --- a/lib/client.js +++ b/lib/client.js @@ -305,20 +305,7 @@ Client.prototype.getTypeParser = function (oid, format) { // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c Client.prototype.escapeIdentifier = function (str) { - var escaped = '"' - - for (var i = 0; i < str.length; i++) { - var c = str[i] - if (c === '"') { - escaped += c + c - } else { - escaped += c - } - } - - escaped += '"' - - return escaped + return '"' + str.replace(/"/g, '""') + '"' } // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c From 11a4793452d618c53e019416cc886ad38deb1aa7 Mon Sep 17 00:00:00 2001 From: Pat Gaffney Date: Tue, 19 Jun 2018 19:17:13 -0500 Subject: [PATCH 0408/1037] Add error handling for null params to Client.prototype.query() --- lib/client.js | 5 ++++- test/unit/client/simple-query-tests.js | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/lib/client.js b/lib/client.js index 0d023db7c..feedebbd8 100644 --- a/lib/client.js +++ b/lib/client.js @@ -352,7 +352,10 @@ Client.prototype.query = function (config, values, callback) { // can take in strings, config object or query object var query var result - if (typeof config.submit === 'function') { + + if (config === null || config === undefined) { + throw new TypeError('Client was passed a null or undefined query') + } else if (typeof config.submit === 'function') { result = query = config if (typeof values === 'function') { query.callback = query.callback || values diff --git a/test/unit/client/simple-query-tests.js b/test/unit/client/simple-query-tests.js index 363c44dbe..3d1deef41 100644 --- a/test/unit/client/simple-query-tests.js +++ b/test/unit/client/simple-query-tests.js @@ -120,4 +120,24 @@ test('executing query', function () { }) }) }) + + test('handles errors', function () { + var client = helper.client() + + test('throws an error when config is null', function () { + try { + client.query(null, undefined) + } catch (error) { + assert.equal(error.message, 'Client was passed a null or undefined query', 'Should have thrown an Error for null queries') + } + }) + + test('throws an error when config is undefined', function () { + try { + client.query() + } catch (error) { + assert.equal(error.message, 'Client was passed a null or undefined query', 'Should have thrown an Error for null queries') + } + }) + }) }) From fed6375e0ae4143280dd58f29a60c36d1894f337 Mon Sep 17 00:00:00 2001 From: Thomas Hunter II Date: Thu, 20 Sep 2018 14:26:25 -0700 Subject: [PATCH 0409/1037] remove query.stream references * This hasn't been supported since 0b2344b6b5afbb68e89eff1ef2b57ecf0726d80b * `node-pg-copy-streams` relies on overriding the `handleCopyInResponse` method: * https://github.com/brianc/node-pg-copy-streams/blob/e15feb19/index.js#L53 --- lib/query.js | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/lib/query.js b/lib/query.js index 8766e1a3a..fe82061e3 100644 --- a/lib/query.js +++ b/lib/query.js @@ -25,7 +25,6 @@ var Query = function (config, values, callback) { this.types = config.types this.name = config.name this.binary = config.binary - this.stream = config.stream // use unique portal name each time this.portal = config.portal || '' this.callback = config.callback @@ -216,17 +215,10 @@ Query.prototype.prepare = function (connection) { } Query.prototype.handleCopyInResponse = function (connection) { - if (this.stream) this.stream.startStreamingToConnection(connection) - else connection.sendCopyFail('No source stream defined') + connection.sendCopyFail('No source stream defined') } Query.prototype.handleCopyData = function (msg, connection) { - var chunk = msg.chunk - if (this.stream) { - this.stream.handleChunk(chunk) - } - // if there are no stream (for example when copy to query was sent by - // query method instead of copyTo) error will be handled - // on copyOutResponse event, so silently ignore this error here + // noop } module.exports = Query From 3828aa86081491282c118884c245b4a19619f02e Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 3 Oct 2018 08:37:15 -0700 Subject: [PATCH 0410/1037] Queued query errors (#1503) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add tests for query callbacks after connection-level errors * Ensure callbacks are executed for all queued queries after connection-level errors Separates socket errors from error messages, sends socket errors to all queries in the queue, marks clients as unusable after socket errors. This is not very pleasant but should maintain backwards compatibility…? * Always call `handleError` asynchronously This doesn’t match the original behaviour of the type errors, but it’s correct. * Fix return value of `Client.prototype.query` in immediate error cases * Mark clients with closed connections as unusable consistently * Add tests for error event when connecting Client * Ensure the promise and callback versions of Client#connect always have the same behaviour * Give same error to queued queries as to active query when ending and do so in the native Client as well. * Restore original ordering between queued query callbacks and 'end' event --- lib/client.js | 125 ++++++++++++----- lib/connection.js | 3 +- lib/native/client.js | 128 +++++++++++------- lib/query.js | 11 +- .../client/error-handling-tests.js | 18 +++ .../connection-pool/error-tests.js | 59 +++++++- 6 files changed, 252 insertions(+), 92 deletions(-) diff --git a/lib/client.js b/lib/client.js index feedebbd8..432443793 100644 --- a/lib/client.js +++ b/lib/client.js @@ -36,6 +36,7 @@ var Client = function (config) { this._connecting = false this._connected = false this._connectionError = false + this._queryable = true this.connection = c.connection || new Connection({ stream: c.stream, @@ -52,16 +53,31 @@ var Client = function (config) { util.inherits(Client, EventEmitter) -Client.prototype.connect = function (callback) { +Client.prototype._errorAllQueries = function (err) { + const enqueueError = (query) => { + process.nextTick(() => { + query.handleError(err, this.connection) + }) + } + + if (this.activeQuery) { + enqueueError(this.activeQuery) + this.activeQuery = null + } + + this.queryQueue.forEach(enqueueError) + this.queryQueue.length = 0 +} + +Client.prototype._connect = function (callback) { var self = this var con = this.connection if (this._connecting || this._connected) { const err = new Error('Client has already been connected. You cannot reuse a client.') - if (callback) { + process.nextTick(() => { callback(err) - return undefined - } - return Promise.reject(err) + }) + return } this._connecting = true @@ -126,15 +142,25 @@ Client.prototype.connect = function (callback) { } const connectedErrorHandler = (err) => { - if (this.activeQuery) { - var activeQuery = self.activeQuery - this.activeQuery = null - return activeQuery.handleError(err, con) - } + this._queryable = false + this._errorAllQueries(err) this.emit('error', err) } + const connectedErrorMessageHandler = (msg) => { + const activeQuery = this.activeQuery + + if (!activeQuery) { + connectedErrorHandler(msg) + return + } + + this.activeQuery = null + activeQuery.handleError(msg, con) + } + con.on('error', connectingErrorHandler) + con.on('errorMessage', connectingErrorHandler) // hook up query handling events to connection // after the connection initially becomes ready for queries @@ -143,7 +169,9 @@ Client.prototype.connect = function (callback) { self._connected = true self._attachListeners(con) con.removeListener('error', connectingErrorHandler) + con.removeListener('errorMessage', connectingErrorHandler) con.on('error', connectedErrorHandler) + con.on('errorMessage', connectedErrorMessageHandler) // process possible callback argument to Client#connect if (callback) { @@ -166,43 +194,53 @@ Client.prototype.connect = function (callback) { }) con.once('end', () => { - if (this.activeQuery) { - var disconnectError = new Error('Connection terminated') - this.activeQuery.handleError(disconnectError, con) - this.activeQuery = null - } + const error = this._ending + ? new Error('Connection terminated') + : new Error('Connection terminated unexpectedly') + + this._errorAllQueries(error) + if (!this._ending) { // if the connection is ended without us calling .end() // on this client then we have an unexpected disconnection // treat this as an error unless we've already emitted an error // during connection. - const error = new Error('Connection terminated unexpectedly') if (this._connecting && !this._connectionError) { if (callback) { callback(error) } else { - this.emit('error', error) + connectedErrorHandler(error) } } else if (!this._connectionError) { - this.emit('error', error) + connectedErrorHandler(error) } } - this.emit('end') + + process.nextTick(() => { + this.emit('end') + }) }) con.on('notice', function (msg) { self.emit('notice', msg) }) +} - if (!callback) { - return new global.Promise((resolve, reject) => { - this.once('error', reject) - this.once('connect', () => { - this.removeListener('error', reject) +Client.prototype.connect = function (callback) { + if (callback) { + this._connect(callback) + return + } + + return new Promise((resolve, reject) => { + this._connect((error) => { + if (error) { + reject(error) + } else { resolve() - }) + } }) - } + }) } Client.prototype._attachListeners = function (con) { @@ -340,7 +378,15 @@ Client.prototype._pulseQueryQueue = function () { if (this.activeQuery) { this.readyForQuery = false this.hasExecuted = true - this.activeQuery.submit(this.connection) + + const queryError = this.activeQuery.submit(this.connection) + if (queryError) { + process.nextTick(() => { + this.activeQuery.handleError(queryError, this.connection) + this.readyForQuery = true + this._pulseQueryQueue() + }) + } } else if (this.hasExecuted) { this.activeQuery = null this.emit('drain') @@ -379,6 +425,20 @@ Client.prototype.query = function (config, values, callback) { query._result._getTypeParser = this._types.getTypeParser.bind(this._types) } + if (!this._queryable) { + process.nextTick(() => { + query.handleError(new Error('Client has encountered a connection error and is not queryable'), this.connection) + }) + return result + } + + if (this._ending) { + process.nextTick(() => { + query.handleError(new Error('Client was closed and is not queryable'), this.connection) + }) + return result + } + this.queryQueue.push(query) this._pulseQueryQueue() return result @@ -386,18 +446,19 @@ Client.prototype.query = function (config, values, callback) { Client.prototype.end = function (cb) { this._ending = true + if (this.activeQuery) { // if we have an active query we need to force a disconnect // on the socket - otherwise a hung query could block end forever - this.connection.stream.destroy(new Error('Connection terminated by user')) - return cb ? cb() : Promise.resolve() + this.connection.stream.destroy() + } else { + this.connection.end() } + if (cb) { - this.connection.end() this.connection.once('end', cb) } else { - return new global.Promise((resolve, reject) => { - this.connection.end() + return new Promise((resolve) => { this.connection.once('end', resolve) }) } diff --git a/lib/connection.js b/lib/connection.js index 799ab4ed8..177739c32 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -117,10 +117,11 @@ Connection.prototype.attachListeners = function (stream) { var packet = self._reader.read() while (packet) { var msg = self.parseMessage(packet) + var eventName = msg.name === 'error' ? 'errorMessage' : msg.name if (self._emitMessage) { self.emit('message', msg) } - self.emit(msg.name, msg) + self.emit(eventName, msg) packet = self._reader.read() } }) diff --git a/lib/native/client.js b/lib/native/client.js index bed548ad8..b18ff6ffa 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -32,8 +32,10 @@ var Client = module.exports = function (config) { }) this._queryQueue = [] - this._connected = false + this._ending = false this._connecting = false + this._connected = false + this._queryable = true // keep these on the object for legacy reasons // for the time being. TODO: deprecate all this jazz @@ -52,50 +54,48 @@ Client.Query = NativeQuery util.inherits(Client, EventEmitter) +Client.prototype._errorAllQueries = function (err) { + const enqueueError = (query) => { + process.nextTick(() => { + query.native = this.native + query.handleError(err) + }) + } + + if (this._hasActiveQuery()) { + enqueueError(this._activeQuery) + this._activeQuery = null + } + + this._queryQueue.forEach(enqueueError) + this._queryQueue.length = 0 +} + // connect to the backend // pass an optional callback to be called once connected // or with an error if there was a connection error -// if no callback is passed and there is a connection error -// the client will emit an error event. -Client.prototype.connect = function (cb) { +Client.prototype._connect = function (cb) { var self = this - var onError = function (err) { - if (cb) return cb(err) - return self.emit('error', err) - } - - var result - if (!cb) { - var resolveOut, rejectOut - cb = (err) => err ? rejectOut(err) : resolveOut() - result = new global.Promise(function (resolve, reject) { - resolveOut = resolve - rejectOut = reject - }) - } - if (this._connecting) { process.nextTick(() => cb(new Error('Client has already been connected. You cannot reuse a client.'))) - return result + return } this._connecting = true this.connectionParameters.getLibpqConnectionString(function (err, conString) { - if (err) return onError(err) + if (err) return cb(err) self.native.connect(conString, function (err) { - if (err) return onError(err) + if (err) return cb(err) // set internal states to connected self._connected = true // handle connection errors from the native layer self.native.on('error', function (err) { - // error will be handled by active query - if (self._activeQuery && self._activeQuery.state !== 'end') { - return - } + self._queryable = false + self._errorAllQueries(err) self.emit('error', err) }) @@ -110,12 +110,26 @@ Client.prototype.connect = function (cb) { self.emit('connect') self._pulseQueryQueue(true) - // possibly call the optional callback - if (cb) cb() + cb() }) }) +} - return result +Client.prototype.connect = function (callback) { + if (callback) { + this._connect(callback) + return + } + + return new Promise((resolve, reject) => { + this._connect((error) => { + if (error) { + reject(error) + } else { + resolve() + } + }) + }) } // send a query to the server @@ -129,26 +143,43 @@ Client.prototype.connect = function (cb) { // optional string rowMode = 'array' for an array of results // } Client.prototype.query = function (config, values, callback) { + var query + var result + if (typeof config.submit === 'function') { + result = query = config // accept query(new Query(...), (err, res) => { }) style if (typeof values === 'function') { config.callback = values } - this._queryQueue.push(config) - this._pulseQueryQueue() - return config + } else { + query = new NativeQuery(config, values, callback) + if (!query.callback) { + let resolveOut, rejectOut + result = new Promise((resolve, reject) => { + resolveOut = resolve + rejectOut = reject + }) + query.callback = (err, res) => err ? rejectOut(err) : resolveOut(res) + } } - var query = new NativeQuery(config, values, callback) - var result - if (!query.callback) { - let resolveOut, rejectOut - result = new Promise((resolve, reject) => { - resolveOut = resolve - rejectOut = reject + if (!this._queryable) { + query.native = this.native + process.nextTick(() => { + query.handleError(new Error('Client has encountered a connection error and is not queryable')) + }) + return result + } + + if (this._ending) { + query.native = this.native + process.nextTick(() => { + query.handleError(new Error('Client was closed and is not queryable')) }) - query.callback = (err, res) => err ? rejectOut(err) : resolveOut(res) + return result } + this._queryQueue.push(query) this._pulseQueryQueue() return result @@ -157,6 +188,9 @@ Client.prototype.query = function (config, values, callback) { // disconnect from the backend server Client.prototype.end = function (cb) { var self = this + + this._ending = true + if (!this._connected) { this.once('connect', this.end.bind(this, cb)) } @@ -170,14 +204,12 @@ Client.prototype.end = function (cb) { }) } this.native.end(function () { - // send an error to the active query - if (self._hasActiveQuery()) { - var msg = 'Connection terminated' - self._queryQueue.length = 0 - self._activeQuery.handleError(new Error(msg)) - } - self.emit('end') - if (cb) cb() + self._errorAllQueries(new Error('Connection terminated')) + + process.nextTick(() => { + self.emit('end') + if (cb) cb() + }) }) return result } diff --git a/lib/query.js b/lib/query.js index fe82061e3..94c2bc3c1 100644 --- a/lib/query.js +++ b/lib/query.js @@ -146,22 +146,17 @@ Query.prototype.handleError = function (err, connection) { Query.prototype.submit = function (connection) { if (typeof this.text !== 'string' && typeof this.name !== 'string') { - const err = new Error('A query must have either text or a name. Supplying neither is unsupported.') - connection.emit('error', err) - connection.emit('readyForQuery') - return + return new Error('A query must have either text or a name. Supplying neither is unsupported.') } if (this.values && !Array.isArray(this.values)) { - const err = new Error('Query values must be an array') - connection.emit('error', err) - connection.emit('readyForQuery') - return + return new Error('Query values must be an array') } if (this.requiresPreparation()) { this.prepare(connection) } else { connection.query(this.text) } + return null } Query.prototype.hasBeenParsed = function (connection) { diff --git a/test/integration/client/error-handling-tests.js b/test/integration/client/error-handling-tests.js index 55372d141..97b0ce83f 100644 --- a/test/integration/client/error-handling-tests.js +++ b/test/integration/client/error-handling-tests.js @@ -50,6 +50,18 @@ suite.test('re-using connections results in promise rejection', (done) => { }) }) +suite.test('using a client after closing it results in error', (done) => { + const client = new Client() + client.connect(() => { + client.end(assert.calls(() => { + client.query('SELECT 1', assert.calls((err) => { + assert.equal(err.message, 'Client was closed and is not queryable') + done() + })) + })) + }) +}) + suite.test('query receives error on client shutdown', function (done) { var client = new Client() client.connect(assert.success(function () { @@ -139,6 +151,9 @@ suite.test('when connecting to an invalid host with callback', function (done) { var client = new Client({ user: 'very invalid username' }) + client.on('error', () => { + assert.fail('unexpected error event when connecting') + }) client.connect(function (error, client) { assert(error instanceof Error) done() @@ -149,6 +164,9 @@ suite.test('when connecting to invalid host with promise', function (done) { var client = new Client({ user: 'very invalid username' }) + client.on('error', () => { + assert.fail('unexpected error event when connecting') + }) client.connect().catch((e) => done()) }) diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index 17cdcc47f..cadffe3db 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -2,9 +2,6 @@ var helper = require('./test-helper') const pg = helper.pg -// make pool hold 2 clients -const pool = new pg.Pool({ max: 2 }) - const suite = new helper.Suite() suite.test('connecting to invalid port', (cb) => { const pool = new pg.Pool({ port: 13801 }) @@ -12,6 +9,8 @@ suite.test('connecting to invalid port', (cb) => { }) suite.test('errors emitted on pool', (cb) => { + // make pool hold 2 clients + const pool = new pg.Pool({ max: 2 }) // get first client pool.connect(assert.success(function (client, done) { client.id = 1 @@ -46,3 +45,57 @@ suite.test('errors emitted on pool', (cb) => { }) })) }) + +suite.test('connection-level errors cause queued queries to fail', (cb) => { + const pool = new pg.Pool() + pool.connect(assert.success((client, done) => { + client.query('SELECT pg_terminate_backend(pg_backend_pid())', assert.calls((err) => { + if (helper.args.native) { + assert.ok(err) + } else { + assert.equal(err.code, '57P01') + } + })) + + pool.once('error', assert.calls((err, brokenClient) => { + assert.equal(client, brokenClient) + })) + + client.query('SELECT 1', assert.calls((err) => { + if (helper.args.native) { + assert.ok(err) + } else { + assert.equal(err.message, 'Connection terminated unexpectedly') + } + + done() + pool.end() + cb() + })) + })) +}) + +suite.test('connection-level errors cause future queries to fail', (cb) => { + const pool = new pg.Pool() + pool.connect(assert.success((client, done) => { + client.query('SELECT pg_terminate_backend(pg_backend_pid())', assert.calls((err) => { + if (helper.args.native) { + assert.ok(err) + } else { + assert.equal(err.code, '57P01') + } + })) + + pool.once('error', assert.calls((err, brokenClient) => { + assert.equal(client, brokenClient) + + client.query('SELECT 1', assert.calls((err) => { + assert.equal(err.message, 'Client has encountered a connection error and is not queryable') + + done() + pool.end() + cb() + })) + })) + })) +}) From 8cf5a8453974bde3d43f85e32254ef6e996a2850 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 3 Oct 2018 10:45:53 -0500 Subject: [PATCH 0411/1037] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a2aaf45a..564407403 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.5.0 + +- Better [error message](https://github.com/brianc/node-postgres/commit/11a4793452d618c53e019416cc886ad38deb1aa7) when passing `null` or `undefined` to `client.query`. +- Better [error handling](https://github.com/brianc/node-postgres/pull/1503) on queued queries. + ### 7.4.0 - Add support for [Uint8Array](https://github.com/brianc/node-postgres/pull/1448) values. From 04a0ec71b48f89e68ddaa365f0b9a8a0d9e738d8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 3 Oct 2018 10:46:12 -0500 Subject: [PATCH 0412/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d3569be96..2e7097235 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.4.3", + "version": "7.5.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 2446fdb8d0111430318a628eca62f27d7baa48ff Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 8 Oct 2018 12:50:11 -0500 Subject: [PATCH 0413/1037] Fix for pg@7.5 (#47) * Fix for pg@7.5 Don't return anything from `stream.submit` * Add node@10 to travis version * Relax version of node@4.x --- .travis.yml | 3 ++- index.js | 3 +-- package.json | 2 +- test/fast-reader.js | 21 ++++++++++++--------- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9c09f74bf..b3f8a825e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,8 @@ language: node_js node_js: - - "4.2" + - "4" - "6" - "8" + - "10" env: - PGUSER=postgres PGDATABASE=postgres diff --git a/index.js b/index.js index 9b0d16172..ddfc66f12 100644 --- a/index.js +++ b/index.js @@ -8,7 +8,7 @@ class PgQueryStream extends Readable { this.cursor = new Cursor(text, values) this._reading = false this._closed = false - this.batchSize = (options || { }).batchSize || 100 + this.batchSize = (options || {}).batchSize || 100 // delegate Submittable callbacks to cursor this.handleRowDescription = this.cursor.handleRowDescription.bind(this.cursor) @@ -21,7 +21,6 @@ class PgQueryStream extends Readable { submit (connection) { this.cursor.submit(connection) - return this } close (callback) { diff --git a/package.json b/package.json index 06915ad9f..20da9651a 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "eslint-plugin-promise": "^3.5.0", "eslint-plugin-standard": "^3.0.1", "mocha": "^3.5.0", - "pg": "6.x", + "pg": "^7.5.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" diff --git a/test/fast-reader.js b/test/fast-reader.js index 5190f10d2..4c6f31f95 100644 --- a/test/fast-reader.js +++ b/test/fast-reader.js @@ -9,15 +9,18 @@ helper('fast reader', function (client) { var result = [] stream.on('readable', function () { var res = stream.read() - if (result.length !== 201) { - assert(res, 'should not return null on evented reader') - } else { - // a readable stream will emit a null datum when it finishes being readable - // https://nodejs.org/api/stream.html#stream_event_readable - assert.equal(res, null) - } - if (res) { - result.push(res.num) + while (res) { + if (result.length !== 201) { + assert(res, 'should not return null on evented reader') + } else { + // a readable stream will emit a null datum when it finishes being readable + // https://nodejs.org/api/stream.html#stream_event_readable + assert.equal(res, null) + } + if (res) { + result.push(res.num) + } + res = stream.read() } }) stream.on('end', function () { From 6177ff95a6714f4a23b5eefa3417cdf31ed22c2a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 8 Oct 2018 12:51:13 -0500 Subject: [PATCH 0414/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 20da9651a..e106abcba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "1.1.1", + "version": "1.1.2", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From 19c68c753e53d32b3190e5e81bdb6ab8d1f676c2 Mon Sep 17 00:00:00 2001 From: John Lindal Date: Wed, 17 Oct 2018 14:30:56 -0700 Subject: [PATCH 0415/1037] fix: AWS Redshift requires a portal name to honor fetchSize --- index.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 2c33a230c..940fe7f4f 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,8 @@ const prepare = require('./pg').prepareValue const EventEmitter = require('events').EventEmitter const util = require('util') +var nextUniqueID = 1; // concept borrowed from org.postgresql.core.v3.QueryExecutorImpl + function Cursor (text, values, config) { EventEmitter.call(this) @@ -16,12 +18,14 @@ function Cursor (text, values, config) { this._result = new Result(this._conf.rowMode) this._cb = null this._rows = null + this._portal = null; } util.inherits(Cursor, EventEmitter) Cursor.prototype.submit = function (connection) { this.connection = connection + this._portal = 'C_' + (nextUniqueID++); const con = connection @@ -30,12 +34,13 @@ Cursor.prototype.submit = function (connection) { }, true) con.bind({ + portal: this._portal, values: this.values }, true) con.describe({ type: 'P', - name: '' // use unamed portal + name: this._portal // AWS Redshift requires a portal name }, true) con.flush() @@ -132,7 +137,7 @@ Cursor.prototype._getRows = function (rows, cb) { this._cb = cb this._rows = [] const msg = { - portal: '', + portal: this._portal, rows: rows } this.connection.execute(msg, true) From 37997fed7628f3cf3e6e3f18e61608f992bd9e5b Mon Sep 17 00:00:00 2001 From: John Lindal Date: Tue, 23 Oct 2018 09:59:50 -0700 Subject: [PATCH 0416/1037] fix formatting issues --- index.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 940fe7f4f..be21e57ae 100644 --- a/index.js +++ b/index.js @@ -4,7 +4,7 @@ const prepare = require('./pg').prepareValue const EventEmitter = require('events').EventEmitter const util = require('util') -var nextUniqueID = 1; // concept borrowed from org.postgresql.core.v3.QueryExecutorImpl +var nextUniqueID = 1 // concept borrowed from org.postgresql.core.v3.QueryExecutorImpl function Cursor (text, values, config) { EventEmitter.call(this) @@ -18,14 +18,14 @@ function Cursor (text, values, config) { this._result = new Result(this._conf.rowMode) this._cb = null this._rows = null - this._portal = null; + this._portal = null } util.inherits(Cursor, EventEmitter) Cursor.prototype.submit = function (connection) { this.connection = connection - this._portal = 'C_' + (nextUniqueID++); + this._portal = 'C_' + (nextUniqueID++) const con = connection @@ -40,7 +40,7 @@ Cursor.prototype.submit = function (connection) { con.describe({ type: 'P', - name: this._portal // AWS Redshift requires a portal name + name: this._portal // AWS Redshift requires a portal name }, true) con.flush() From ff6fe1e01ef67c849f37ab2fe483b82ffda999c0 Mon Sep 17 00:00:00 2001 From: Igor Savin Date: Tue, 23 Oct 2018 22:02:49 +0200 Subject: [PATCH 0417/1037] Execute tests on Node 11 in CI (#1752) --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e0fb505d9..96d28c670 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,10 +14,10 @@ matrix: - node_js: "lts/argon" addons: postgresql: "9.6" - - node_js: "9" + - node_js: "10" addons: postgresql: "9.6" - - node_js: "10" + - node_js: "11" addons: postgresql: "9.6" - node_js: "lts/carbon" From 1cf1e05ab9fe12a8f1b3637e3b8fc16a837661ec Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 24 Oct 2018 08:40:23 -0700 Subject: [PATCH 0418/1037] Allow a custom type to be used for Client promises (#1518) Matches the Pool API. --- lib/client.js | 12 ++++------ lib/native/client.js | 12 ++++------ package.json | 1 + .../client/query-as-promise-tests.js | 24 ++++++++++++++++++- 4 files changed, 34 insertions(+), 15 deletions(-) diff --git a/lib/client.js b/lib/client.js index 432443793..625aad682 100644 --- a/lib/client.js +++ b/lib/client.js @@ -31,6 +31,7 @@ var Client = function (config) { var c = config || {} + this._Promise = c.Promise || global.Promise this._types = new TypeOverrides(c.types) this._ending = false this._connecting = false @@ -232,7 +233,7 @@ Client.prototype.connect = function (callback) { return } - return new Promise((resolve, reject) => { + return new this._Promise((resolve, reject) => { this._connect((error) => { if (error) { reject(error) @@ -409,12 +410,9 @@ Client.prototype.query = function (config, values, callback) { } else { query = new Query(config, values, callback) if (!query.callback) { - let resolveOut, rejectOut - result = new Promise((resolve, reject) => { - resolveOut = resolve - rejectOut = reject + result = new this._Promise((resolve, reject) => { + query.callback = (err, res) => err ? reject(err) : resolve(res) }) - query.callback = (err, res) => err ? rejectOut(err) : resolveOut(res) } } @@ -458,7 +456,7 @@ Client.prototype.end = function (cb) { if (cb) { this.connection.once('end', cb) } else { - return new Promise((resolve) => { + return new this._Promise((resolve) => { this.connection.once('end', resolve) }) } diff --git a/lib/native/client.js b/lib/native/client.js index b18ff6ffa..c88bfb12e 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -25,6 +25,7 @@ var Client = module.exports = function (config) { EventEmitter.call(this) config = config || {} + this._Promise = config.Promise || global.Promise this._types = new TypeOverrides(config.types) this.native = new Native({ @@ -121,7 +122,7 @@ Client.prototype.connect = function (callback) { return } - return new Promise((resolve, reject) => { + return new this._Promise((resolve, reject) => { this._connect((error) => { if (error) { reject(error) @@ -156,7 +157,7 @@ Client.prototype.query = function (config, values, callback) { query = new NativeQuery(config, values, callback) if (!query.callback) { let resolveOut, rejectOut - result = new Promise((resolve, reject) => { + result = new this._Promise((resolve, reject) => { resolveOut = resolve rejectOut = reject }) @@ -196,11 +197,8 @@ Client.prototype.end = function (cb) { } var result if (!cb) { - var resolve, reject - cb = (err) => err ? reject(err) : resolve() - result = new global.Promise(function (res, rej) { - resolve = res - reject = rej + result = new this._Promise(function (resolve, reject) { + cb = (err) => err ? reject(err) : resolve() }) } this.native.end(function () { diff --git a/package.json b/package.json index 2e7097235..16fc6c7d6 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ }, "devDependencies": { "async": "0.9.0", + "bluebird": "3.5.2", "co": "4.6.0", "eslint": "4.2.0", "eslint-config-standard": "10.2.1", diff --git a/test/integration/client/query-as-promise-tests.js b/test/integration/client/query-as-promise-tests.js index 625a33392..803b89099 100644 --- a/test/integration/client/query-as-promise-tests.js +++ b/test/integration/client/query-as-promise-tests.js @@ -1,4 +1,5 @@ 'use strict' +var bluebird = require('bluebird') var helper = require(__dirname + '/../test-helper') var pg = helper.pg @@ -7,10 +8,10 @@ process.on('unhandledRejection', function (e) { process.exit(1) }) -const pool = new pg.Pool() const suite = new helper.Suite() suite.test('promise API', (cb) => { + const pool = new pg.Pool() pool.connect().then((client) => { client.query('SELECT $1::text as name', ['foo']) .then(function (result) { @@ -31,3 +32,24 @@ suite.test('promise API', (cb) => { }) }) }) + +suite.test('promise API with configurable promise type', (cb) => { + const client = new pg.Client({ Promise: bluebird }) + const connectPromise = client.connect() + assert(connectPromise instanceof bluebird, 'Client connect() returns configured promise') + + connectPromise + .then(() => { + const queryPromise = client.query('SELECT 1') + assert(queryPromise instanceof bluebird, 'Client query() returns configured promise') + + return queryPromise.then(() => { + client.end(cb) + }) + }) + .catch((error) => { + process.nextTick(() => { + throw error + }) + }) +}); From badf0a1c65bc6789cb6a406b61e9ec1ba7113d80 Mon Sep 17 00:00:00 2001 From: Igor Savin Date: Fri, 26 Oct 2018 15:55:31 +0200 Subject: [PATCH 0419/1037] Update ESLint (#1753) * Update ESLint * Downgrade ESLint version to restore Node 4 support * Downgrade more dependencies * Keep downgrading --- lib/connection-parameters.js | 2 +- package.json | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index f31f28dd3..19267058f 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -87,7 +87,7 @@ ConnectionParameters.prototype.getLibpqConnectionString = function (cb) { add(params, this, 'application_name') add(params, this, 'fallback_application_name') - var ssl = typeof this.ssl === 'object' ? this.ssl : {sslmode: this.ssl} + var ssl = typeof this.ssl === 'object' ? this.ssl : { sslmode: this.ssl } add(params, ssl, 'sslmode') add(params, ssl, 'sslca') add(params, ssl, 'sslkey') diff --git a/package.json b/package.json index 16fc6c7d6..6981254fc 100644 --- a/package.json +++ b/package.json @@ -31,12 +31,12 @@ "async": "0.9.0", "bluebird": "3.5.2", "co": "4.6.0", - "eslint": "4.2.0", - "eslint-config-standard": "10.2.1", - "eslint-plugin-import": "2.7.0", - "eslint-plugin-node": "5.1.0", - "eslint-plugin-promise": "3.5.0", - "eslint-plugin-standard": "3.0.1", + "eslint": "^4.19.1", + "eslint-config-standard": "^11.0.0", + "eslint-plugin-import": "^2.14.0", + "eslint-plugin-node": "^6.0.1", + "eslint-plugin-promise": "^4.0.1", + "eslint-plugin-standard": "^3.1.0", "pg-copy-streams": "0.3.0" }, "minNativeVersion": "2.0.0", From d468b6a1f15516eb48d8b0493c2970eeb721e695 Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 26 Oct 2018 08:59:00 -0500 Subject: [PATCH 0420/1037] Update SPONSORS.md --- SPONSORS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SPONSORS.md b/SPONSORS.md index 707893a5f..59790b660 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -11,4 +11,9 @@ node-postgres is made possible by the helpful contributors from the community we - Arnaud Benhamdine [@abenhamdine](https://twitter.com/abenhamdine) - Matthew Welke - Matthew Weber +- Andrea De Simon +- Todd Kennedy +- Alexander Robson - Benjie Gillam +- David Hanson +- Franklin Davenport From 034eb34f3c98c342d460092c72c43b74ee3f3e8f Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 26 Oct 2018 09:02:53 -0500 Subject: [PATCH 0421/1037] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 564407403..6a76ebbdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.6.0 +- Add support for ["bring your own promise"](https://github.com/brianc/node-postgres/pull/1518) + ### 7.5.0 - Better [error message](https://github.com/brianc/node-postgres/commit/11a4793452d618c53e019416cc886ad38deb1aa7) when passing `null` or `undefined` to `client.query`. From a3295b435516341560b93c8071521c1c31b74998 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 26 Oct 2018 09:03:19 -0500 Subject: [PATCH 0422/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6981254fc..5e7d310f7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.5.0", + "version": "7.6.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From daddd4ffd609f290aa4b9b97aa21899ec04ac96b Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 7 Nov 2018 09:31:59 -0600 Subject: [PATCH 0423/1037] Bump buffer-writer version (#1764) Fixes the deprecation warning for using `new Buffer`. The change is semver major in buffer-writer since we dropped support for node < 4.x, but otherwise it's a non-breaking change. Since node-postgres already requires node >= 4.x it's fine. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5e7d310f7..789457a38 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "author": "Brian Carlson ", "main": "./lib", "dependencies": { - "buffer-writer": "1.0.1", + "buffer-writer": "2.0.0", "packet-reader": "0.3.1", "pg-connection-string": "0.1.3", "pg-pool": "~2.0.3", From 3620e23899784d73d534ef51683f6a8f6067abf7 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 7 Nov 2018 09:32:45 -0600 Subject: [PATCH 0424/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 789457a38..5a43e23f8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.6.0", + "version": "7.6.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 4b9669eaa764126135f0bbf64af9be1e9d5092a9 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 12 Nov 2018 12:32:19 -0600 Subject: [PATCH 0425/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 17740db2d..b15b4a53b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "2.0.3", + "version": "2.0.4", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From eb076db5d47a29c19d3212feac26cd7b6d257a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Cruz?= Date: Thu, 29 Nov 2018 15:11:47 +0000 Subject: [PATCH 0426/1037] Add configurable query timeout (#1760) * Add read_timeout to connection settings * Fix uncaught error issue * Fix lint * Fix "queryCallback is not a function" * Added test and fixed error returning * Added query timeout to native client * Added test for timeout not reached * Ensure error is the correct one Correct test name * Removed dubious check * Added new test * Improved test --- lib/client.js | 36 ++++++++++++++++++++++++ lib/connection-parameters.js | 1 + lib/defaults.js | 5 +++- lib/native/client.js | 42 ++++++++++++++++++++++++++-- test/integration/client/api-tests.js | 41 +++++++++++++++++++++++++++ 5 files changed, 122 insertions(+), 3 deletions(-) diff --git a/lib/client.js b/lib/client.js index 625aad682..8e7d307f7 100644 --- a/lib/client.js +++ b/lib/client.js @@ -399,15 +399,20 @@ Client.prototype.query = function (config, values, callback) { // can take in strings, config object or query object var query var result + var readTimeout + var readTimeoutTimer + var queryCallback if (config === null || config === undefined) { throw new TypeError('Client was passed a null or undefined query') } else if (typeof config.submit === 'function') { + readTimeout = config.query_timeout || this.connectionParameters.query_timeout result = query = config if (typeof values === 'function') { query.callback = query.callback || values } } else { + readTimeout = this.connectionParameters.query_timeout query = new Query(config, values, callback) if (!query.callback) { result = new this._Promise((resolve, reject) => { @@ -416,6 +421,37 @@ Client.prototype.query = function (config, values, callback) { } } + if (readTimeout) { + queryCallback = query.callback + + readTimeoutTimer = setTimeout(() => { + var error = new Error('Query read timeout') + + process.nextTick(() => { + query.handleError(error, this.connection) + }) + + queryCallback(error) + + // we already returned an error, + // just do nothing if query completes + query.callback = () => {} + + // Remove from queue + var index = this.queryQueue.indexOf(query) + if (index > -1) { + this.queryQueue.splice(index, 1) + } + + this._pulseQueryQueue() + }, readTimeout) + + query.callback = (err, res) => { + clearTimeout(readTimeoutTimer) + queryCallback(err, res) + } + } + if (this.binary && !query.binary) { query.binary = true } diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index 19267058f..745311ad0 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -65,6 +65,7 @@ var ConnectionParameters = function (config) { this.application_name = val('application_name', config, 'PGAPPNAME') this.fallback_application_name = val('fallback_application_name', config, false) this.statement_timeout = val('statement_timeout', config, false) + this.query_timeout = val('query_timeout', config, false) } // Convert arg to a string, surround in single quotes, and escape single quotes and backslashes diff --git a/lib/defaults.js b/lib/defaults.js index 30214b1d8..6b0a98f1b 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -55,7 +55,10 @@ module.exports = { parseInputDatesAsUTC: false, // max milliseconds any query using this connection will execute for before timing out in error. false=unlimited - statement_timeout: false + statement_timeout: false, + + // max miliseconds to wait for query to complete (client side) + query_timeout: false } var pgTypes = require('pg-types') diff --git a/lib/native/client.js b/lib/native/client.js index c88bfb12e..5338f7f10 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -146,14 +146,21 @@ Client.prototype.connect = function (callback) { Client.prototype.query = function (config, values, callback) { var query var result - - if (typeof config.submit === 'function') { + var readTimeout + var readTimeoutTimer + var queryCallback + + if (config === null || config === undefined) { + throw new TypeError('Client was passed a null or undefined query') + } else if (typeof config.submit === 'function') { + readTimeout = config.query_timeout || this.connectionParameters.query_timeout result = query = config // accept query(new Query(...), (err, res) => { }) style if (typeof values === 'function') { config.callback = values } } else { + readTimeout = this.connectionParameters.query_timeout query = new NativeQuery(config, values, callback) if (!query.callback) { let resolveOut, rejectOut @@ -165,6 +172,37 @@ Client.prototype.query = function (config, values, callback) { } } + if (readTimeout) { + queryCallback = query.callback + + readTimeoutTimer = setTimeout(() => { + var error = new Error('Query read timeout') + + process.nextTick(() => { + query.handleError(error, this.connection) + }) + + queryCallback(error) + + // we already returned an error, + // just do nothing if query completes + query.callback = () => {} + + // Remove from queue + var index = this._queryQueue.indexOf(query) + if (index > -1) { + this._queryQueue.splice(index, 1) + } + + this._pulseQueryQueue() + }, readTimeout) + + query.callback = (err, res) => { + clearTimeout(readTimeoutTimer) + queryCallback(err, res) + } + } + if (!this._queryable) { query.native = this.native process.nextTick(() => { diff --git a/test/integration/client/api-tests.js b/test/integration/client/api-tests.js index e18c3749c..c274bbd36 100644 --- a/test/integration/client/api-tests.js +++ b/test/integration/client/api-tests.js @@ -15,6 +15,47 @@ suite.test('pool callback behavior', done => { }) }) +suite.test('query timeout', (cb) => { + const pool = new pg.Pool({query_timeout: 1000}) + pool.connect().then((client) => { + client.query('SELECT pg_sleep(2)', assert.calls(function (err, result) { + assert(err) + assert(err.message === 'Query read timeout') + client.release() + pool.end(cb) + })) + }) +}) + +suite.test('query recover from timeout', (cb) => { + const pool = new pg.Pool({query_timeout: 1000}) + pool.connect().then((client) => { + client.query('SELECT pg_sleep(20)', assert.calls(function (err, result) { + assert(err) + assert(err.message === 'Query read timeout') + client.release(err) + pool.connect().then((client) => { + client.query('SELECT 1', assert.calls(function (err, result) { + assert(!err) + client.release(err) + pool.end(cb) + })) + }) + })) + }) +}) + +suite.test('query no timeout', (cb) => { + const pool = new pg.Pool({query_timeout: 10000}) + pool.connect().then((client) => { + client.query('SELECT pg_sleep(1)', assert.calls(function (err, result) { + assert(!err) + client.release() + pool.end(cb) + })) + }) +}) + suite.test('callback API', done => { const client = new helper.Client() client.query('CREATE TEMP TABLE peep(name text)') From 77866d0264dcbaff9d1fe5aa8bb2f925e32a8aaa Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 29 Nov 2018 09:15:50 -0600 Subject: [PATCH 0427/1037] Update changelog --- CHANGELOG.md | 77 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 53 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a76ebbdc..b2f34ac2d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,12 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.7.0 + +- Add support for configurable [query timeout](https://github.com/brianc/node-postgres/pull/1760) on a client level. + ### 7.6.0 + - Add support for ["bring your own promise"](https://github.com/brianc/node-postgres/pull/1518) ### 7.5.0 @@ -56,16 +61,17 @@ We do not include break-fix version release in this file. ### v6.1.0 -- Add optional callback parameter to the pure JavaScript `client.end` method. The native client already supported this. +- Add optional callback parameter to the pure JavaScript `client.end` method. The native client already supported this. ### v6.0.0 #### Breaking Changes -- Remove `pg.pools`. There is still a reference kept to the pools created & tracked by `pg.connect` but it has been renamed, is considered private, and should not be used. Accessing this API directly was uncommon and was _supposed_ to be private but was incorrectly documented on the wiki. Therefore, it is a breaking change of an (unintentionally) public interface to remove it by renaming it & making it private. Eventually `pg.connect` itself will be deprecated in favor of instantiating pools directly via `new pg.Pool()` so this property should become completely moot at some point. In the mean time...check out the new features... + +- Remove `pg.pools`. There is still a reference kept to the pools created & tracked by `pg.connect` but it has been renamed, is considered private, and should not be used. Accessing this API directly was uncommon and was _supposed_ to be private but was incorrectly documented on the wiki. Therefore, it is a breaking change of an (unintentionally) public interface to remove it by renaming it & making it private. Eventually `pg.connect` itself will be deprecated in favor of instantiating pools directly via `new pg.Pool()` so this property should become completely moot at some point. In the mean time...check out the new features... #### New features -- Replace internal pooling code with [pg-pool](https://github.com/brianc/node-pg-pool). This is the first step in eventually deprecating and removing the singleton `pg.connect`. The pg-pool constructor is exported from node-postgres at `require('pg').Pool`. It provides a backwards compatible interface with `pg.connect` as well as a promise based interface & additional niceties. +- Replace internal pooling code with [pg-pool](https://github.com/brianc/node-pg-pool). This is the first step in eventually deprecating and removing the singleton `pg.connect`. The pg-pool constructor is exported from node-postgres at `require('pg').Pool`. It provides a backwards compatible interface with `pg.connect` as well as a promise based interface & additional niceties. You can now create an instance of a pool and don't have to rely on the `pg` singleton for anything: @@ -82,68 +88,79 @@ pool.connect(function(err, client, done) { Promise support & other goodness lives now in [pg-pool](https://github.com/brianc/node-pg-pool). -__Please__ read the readme at [pg-pool](https://github.com/brianc/node-pg-pool) for the full api. +**Please** read the readme at [pg-pool](https://github.com/brianc/node-pg-pool) for the full api. -- Included support for tcp keep alive. Enable it as follows: +- Included support for tcp keep alive. Enable it as follows: ```js -var client = new Client({ keepAlive: true }) +var client = new Client({ keepAlive: true }); ``` This should help with backends incorrectly considering idle clients to be dead and prematurely disconnecting them. - ### v5.1.0 + - Make the query object returned from `client.query` implement the promise interface. This is the first step towards promisifying more of the node-postgres api. Example: + ```js -var client = new Client() -client.connect() -client.query('SELECT $1::text as name', ['brianc']) - .then(function(res) { - console.log('hello from', res.rows[0]) - client.end() - }) +var client = new Client(); +client.connect(); +client.query("SELECT $1::text as name", ["brianc"]).then(function(res) { + console.log("hello from", res.rows[0]); + client.end(); +}); ``` ### v5.0.0 #### Breaking Changes + - `require('pg').native` now returns null if the native bindings cannot be found; previously, this threw an exception. #### New Features + - better error message when passing `undefined` as a query parameter - support for `defaults.connectionString` - support for `returnToHead` being passed to [generic pool](https://github.com/coopernurse/node-pool) ### v4.5.0 + - Add option to parse JS date objects in query parameters as [UTC](https://github.com/brianc/node-postgres/pull/943) ### v4.4.0 + - Warn to `stderr` if a named query exceeds 63 characters which is the max length supported by postgres. ### v4.3.0 + - Unpin `pg-types` semver. Allow it to float against `pg-types@1.x`. ### v4.2.0 + - Support for additional error fields in postgres >= 9.3 if available. ### v4.1.0 + - Allow type parser overrides on a [per-client basis](https://github.com/brianc/node-postgres/pull/679) ### v4.0.0 + - Make [native bindings](https://github.com/brianc/node-pg-native.git) an optional install with `npm install pg-native` - No longer surround query result callback with `try/catch` block. - Remove built in COPY IN / COPY OUT support - better implementations provided by [pg-copy-streams](https://github.com/brianc/node-pg-copy-streams.git) and [pg-native](https://github.com/brianc/node-pg-native.git) ### v3.6.0 + - Include support for (parsing JSONB)[https://github.com/brianc/node-pg-types/pull/13] (supported in postgres 9.4) ### v3.5.0 + - Include support for parsing boolean arrays ### v3.4.0 + - Include port as connection parameter to [unix sockets](https://github.com/brianc/node-postgres/pull/604) - Better support for odd [date parsing](https://github.com/brianc/node-pg-types/pull/8) @@ -153,7 +170,6 @@ client.query('SELECT $1::text as name', ['brianc']) - Expose array parsers on [pg.types](https://github.com/brianc/node-pg-types/pull/2) - Allow [pool](https://github.com/brianc/node-postgres/pull/591) to be configured - ### v3.1.0 - Add [count of the number of times a client has been checked out from the pool](https://github.com/brianc/node-postgres/pull/556) @@ -162,27 +178,29 @@ client.query('SELECT $1::text as name', ['brianc']) ### v3.0.0 #### Breaking changes + - [Parse the DATE PostgreSQL type as local time](https://github.com/brianc/node-postgres/pull/514) -After [some discussion](https://github.com/brianc/node-postgres/issues/510) it was decided node-postgres was non-compliant in how it was handling DATE results. They were being converted to UTC, but the PostgreSQL documentation specifies they should be returned in the client timezone. This is a breaking change, and if you use the `date` type you might want to examine your code and make sure nothing is impacted. +After [some discussion](https://github.com/brianc/node-postgres/issues/510) it was decided node-postgres was non-compliant in how it was handling DATE results. They were being converted to UTC, but the PostgreSQL documentation specifies they should be returned in the client timezone. This is a breaking change, and if you use the `date` type you might want to examine your code and make sure nothing is impacted. - [Fix possible numeric precision loss on numeric & int8 arrays](https://github.com/brianc/node-postgres/pull/501) -pg@v2.0 included changes to not convert large integers into their JavaScript number representation because of possibility for numeric precision loss. The same types in arrays were not taken into account. This fix applies the same type of type-coercion rules to arrays of those types, so there will be no more possible numeric loss on an array of very large int8s for example. This is a breaking change because now a return type from a query of `int8[]` will contain _string_ representations -of the integers. Use your favorite JavaScript bignum module to represent them without precision loss, or punch over the type converter to return the old style arrays again. +pg@v2.0 included changes to not convert large integers into their JavaScript number representation because of possibility for numeric precision loss. The same types in arrays were not taken into account. This fix applies the same type of type-coercion rules to arrays of those types, so there will be no more possible numeric loss on an array of very large int8s for example. This is a breaking change because now a return type from a query of `int8[]` will contain _string_ representations +of the integers. Use your favorite JavaScript bignum module to represent them without precision loss, or punch over the type converter to return the old style arrays again. - [Fix to input array of dates being improperly converted to utc](https://github.com/benesch/node-postgres/commit/c41eedc3e01e5527a3d5c242fa1896f02ef0b261#diff-7172adb1fec2457a2700ed29008a8e0aR108) -Single `date` parameters were properly sent to the PostgreSQL server properly in local time, but an input array of dates was being changed into utc dates. This is a violation of what PostgreSQL expects. Small breaking change, but none-the-less something you should check out if you are inserting an array of dates. +Single `date` parameters were properly sent to the PostgreSQL server properly in local time, but an input array of dates was being changed into utc dates. This is a violation of what PostgreSQL expects. Small breaking change, but none-the-less something you should check out if you are inserting an array of dates. - [Query no longer emits `end` event if it ends due to an error](https://github.com/brianc/node-postgres/commit/357b64d70431ec5ca721eb45a63b082c18e6ffa3) -This is a small change to bring the semantics of query more in line with other EventEmitters. The tests all passed after this change, but I suppose it could still be a breaking change in certain use cases. If you are doing clever things with the `end` and `error` events of a query object you might want to check to make sure its still behaving normally, though it is most likely not an issue. +This is a small change to bring the semantics of query more in line with other EventEmitters. The tests all passed after this change, but I suppose it could still be a breaking change in certain use cases. If you are doing clever things with the `end` and `error` events of a query object you might want to check to make sure its still behaving normally, though it is most likely not an issue. #### New features + - [Supercharge `prepareValue`](https://github.com/brianc/node-postgres/pull/555) -The long & short of it is now any object you supply in the list of query values will be inspected for a `.toPostgres` method. If the method is present it will be called and its result used as the raw text value sent to PostgreSQL for that value. This allows the same type of custom type coercion on query parameters as was previously afforded to query result values. +The long & short of it is now any object you supply in the list of query values will be inspected for a `.toPostgres` method. If the method is present it will be called and its result used as the raw text value sent to PostgreSQL for that value. This allows the same type of custom type coercion on query parameters as was previously afforded to query result values. - [Domain aware connection pool](https://github.com/brianc/node-postgres/pull/531) @@ -197,41 +215,52 @@ Avoids a scenario where your pool could fill up with disconnected & unusable cli To provide better documentation and a clearer explanation of how to override the query result parsing system we broke the type converters [into their own module](https://github.com/brianc/node-pg-types). There is still work around removing the 'global-ness' of the type converters so each query or connection can return types differently, but this is a good first step and allow a lot more obvious way to return int8 results as JavaScript numbers, for example ### v2.11.0 + - Add support for [application_name](https://github.com/brianc/node-postgres/pull/497) ### v2.10.0 + - Add support for [the password file](http://www.postgresql.org/docs/9.3/static/libpq-pgpass.html) ### v2.9.0 + - Add better support for [unix domain socket](https://github.com/brianc/node-postgres/pull/487) connections ### v2.8.0 + - Add support for parsing JSON[] and UUID[] result types ### v2.7.0 + - Use single row mode in native bindings when available [@rpedela] - reduces memory consumption when handling row values in 'row' event - Automatically bind buffer type parameters as binary [@eugeneware] ### v2.6.0 + - Respect PGSSLMODE environment variable ### v2.5.0 + - Ability to opt-in to int8 parsing via `pg.defaults.parseInt8 = true` ### v2.4.0 + - Use eval in the result set parser to increase performance ### v2.3.0 + - Remove built-in support for binary Int64 parsing. -_Due to the low usage & required compiled dependency this will be pushed into a 3rd party add-on_ + _Due to the low usage & required compiled dependency this will be pushed into a 3rd party add-on_ ### v2.2.0 + - [Add support for excapeLiteral and escapeIdentifier in both JavaScript and the native bindings](https://github.com/brianc/node-postgres/pull/396) ### v2.1.0 + - Add support for SSL connections in JavaScript driver - - this means you can connect to heroku postgres from your local machine without the native bindings! +- this means you can connect to heroku postgres from your local machine without the native bindings! - [Add field metadata to result object](https://github.com/brianc/node-postgres/blob/master/test/integration/client/row-description-on-results-tests.js) - [Add ability for rows to be returned as arrays instead of objects](https://github.com/brianc/node-postgres/blob/master/test/integration/client/results-as-array-tests.js) @@ -267,7 +296,7 @@ If you are unhappy with these changes you can always [override the built in type ### v1.0.0 - remove deprecated functionality - - Callback function passed to `pg.connect` now __requires__ 3 arguments + - Callback function passed to `pg.connect` now **requires** 3 arguments - Client#pauseDrain() / Client#resumeDrain removed - numeric, decimal, and float data types no longer parsed into float before being returned. Will be returned from query results as `String` From f52a0fe8f73262ddc91e7a1cb76db4b3d29376eb Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 29 Nov 2018 09:16:05 -0600 Subject: [PATCH 0428/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5a43e23f8..07abd62b9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.6.1", + "version": "7.7.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 93df471d98dde16744dc2ff4ff20cc9c1979a47e Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 29 Nov 2018 09:36:57 -0600 Subject: [PATCH 0429/1037] Bump min version of pg-pool --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 07abd62b9..153d0d827 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "buffer-writer": "2.0.0", "packet-reader": "0.3.1", "pg-connection-string": "0.1.3", - "pg-pool": "~2.0.3", + "pg-pool": "^2.0.4", "pg-types": "~1.12.1", "pgpass": "1.x", "semver": "4.3.2" From 060a35faeb7a5c16f1d7c801ab56f42a2ee92f5d Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 29 Nov 2018 09:37:03 -0600 Subject: [PATCH 0430/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 153d0d827..b98630c6f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.7.0", + "version": "7.7.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 6fc07b4a6301cf42c9680f2c398ad0ea52322c2b Mon Sep 17 00:00:00 2001 From: Mikkel Hoegh Date: Wed, 5 Dec 2018 00:01:39 +0100 Subject: [PATCH 0431/1037] fix: remove support for deprecated pg.js package BREAKING CHANGE: pg.js is long dead and no longer supported. Use [pg](https://www.npmjs.com/package/pg) instead. --- index.js | 4 ++-- pg.js | 10 ---------- 2 files changed, 2 insertions(+), 12 deletions(-) delete mode 100644 pg.js diff --git a/index.js b/index.js index 2c33a230c..a444fc8c9 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ 'use strict' -const Result = require('./pg').Result -const prepare = require('./pg').prepareValue +const Result = require('pg/lib/result.js') +const prepare = require('pg/lib/utils.js').prepareValue const EventEmitter = require('events').EventEmitter const util = require('util') diff --git a/pg.js b/pg.js deleted file mode 100644 index 42d89a9b1..000000000 --- a/pg.js +++ /dev/null @@ -1,10 +0,0 @@ -// support both pg & pg.js -// this will eventually go away when i break native bindings -// out into their own module -try { - module.exports.Result = require('pg/lib/result.js') - module.exports.prepareValue = require('pg/lib/utils.js').prepareValue -} catch (e) { - module.exports.Result = require('pg.js/lib/result.js') - module.exports.prepareValue = require('pg.js/lib/utils.js').prepareValue -} From 7ef3f4aa4a6404abae289c3bcab5a00a50a03199 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 11 Dec 2018 10:53:00 -0800 Subject: [PATCH 0432/1037] Fix queued checkout after a connection failure (#111) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Test queued checkout after a connection failure Co-authored-by: Johannes Würbach * Fix queued checkout after a connection failure Co-authored-by: Johannes Würbach --- index.js | 4 ++++ test/error-handling.js | 22 ++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/index.js b/index.js index ab74209f1..2ccbbe7f5 100644 --- a/index.js +++ b/index.js @@ -226,6 +226,10 @@ class Pool extends EventEmitter { if (timeoutHit) { err.message = 'Connection terminated due to connection timeout' } + + // this client won’t be released, so move on immediately + this._pulseQueue() + cb(err, undefined, NOOP) } else { this.log('new client connected') diff --git a/test/error-handling.js b/test/error-handling.js index 9435dd7fc..1c84889cf 100644 --- a/test/error-handling.js +++ b/test/error-handling.js @@ -1,4 +1,5 @@ 'use strict' +const net = require('net') const co = require('co') const expect = require('expect.js') @@ -143,4 +144,25 @@ describe('pool error handling', function () { return pool.end() })) }) + + it('should continue with queued items after a connection failure', (done) => { + const closeServer = net.createServer((socket) => { + socket.destroy() + }).unref() + + closeServer.listen(() => { + const pool = new Pool({ max: 1, port: closeServer.address().port }) + pool.connect((err) => { + expect(err).to.be.an(Error) + expect(err.message).to.be('Connection terminated unexpectedly') + }) + pool.connect((err) => { + expect(err).to.be.an(Error) + expect(err.message).to.be('Connection terminated unexpectedly') + closeServer.close(() => { + pool.end(done) + }) + }) + }) + }) }) From 140f9a1242e94c09fc780d8e4bcc82b91a787d39 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 11 Dec 2018 12:53:22 -0600 Subject: [PATCH 0433/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b15b4a53b..c9334457f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "2.0.4", + "version": "2.0.5", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From 35a285c9a7a5815b0bac9e6a2274e3a47976c11e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20W=C3=BCrbach?= Date: Fri, 14 Dec 2018 21:15:35 +0100 Subject: [PATCH 0434/1037] Fix two timeout races (#109) --- index.js | 67 +++++++++++++++++---------- test/connection-timeout.js | 92 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 24 deletions(-) diff --git a/index.js b/index.js index 2ccbbe7f5..fe921cbb2 100644 --- a/index.js +++ b/index.js @@ -3,14 +3,6 @@ const EventEmitter = require('events').EventEmitter const NOOP = function () { } -const remove = (list, value) => { - const i = list.indexOf(value) - - if (i !== -1) { - list.splice(i, 1) - } -} - const removeWhere = (list, predicate) => { const i = list.findIndex(predicate) @@ -26,6 +18,12 @@ class IdleItem { } } +class PendingItem { + constructor (callback) { + this.callback = callback + } +} + function throwOnRelease () { throw new Error('Release called on client which has already been released to the pool.') } @@ -85,6 +83,7 @@ class Pool extends EventEmitter { this._pendingQueue = [] this._endCallback = undefined this.ending = false + this.ended = false } _isFull () { @@ -93,6 +92,10 @@ class Pool extends EventEmitter { _pulseQueue () { this.log('pulse queue') + if (this.ended) { + this.log('pulse queue ended') + return + } if (this.ending) { this.log('pulse queue on ending') if (this._idle.length) { @@ -101,6 +104,7 @@ class Pool extends EventEmitter { }) } if (!this._clients.length) { + this.ended = true this._endCallback() } return @@ -121,10 +125,10 @@ class Pool extends EventEmitter { const client = idleItem.client client.release = release.bind(this, client) this.emit('acquire', client) - return waiter(undefined, client, client.release) + return waiter.callback(undefined, client, client.release) } if (!this._isFull()) { - return this.connect(waiter) + return this.newClient(waiter) } throw new Error('unexpected condition') } @@ -150,18 +154,18 @@ class Pool extends EventEmitter { return cb ? cb(err) : this.Promise.reject(err) } + const response = promisify(this.Promise, cb) + const result = response.result + // 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) + this._pendingQueue.push(new PendingItem(response.callback)) return result } @@ -170,18 +174,27 @@ class Pool extends EventEmitter { response.callback(err, res, done) } + const pendingItem = new PendingItem(queueCallback) + // 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 - remove(this._pendingQueue, queueCallback) + removeWhere(this._pendingQueue, (i) => i.callback === queueCallback) + pendingItem.timedOut = true response.callback(new Error('timeout exceeded when trying to connect')) }, this.options.connectionTimeoutMillis) - this._pendingQueue.push(queueCallback) + this._pendingQueue.push(pendingItem) return result } + this.newClient(new PendingItem(response.callback)) + + return result + } + + newClient (pendingItem) { const client = new this.Client(this.options) this._clients.push(client) const idleListener = (err) => { @@ -210,9 +223,6 @@ class Pool extends EventEmitter { }, this.options.connectionTimeoutMillis) } - const response = promisify(this.Promise, cb) - cb = response.callback - this.log('connecting new client') client.connect((err) => { if (tid) { @@ -230,20 +240,29 @@ class Pool extends EventEmitter { // this client won’t be released, so move on immediately this._pulseQueue() - cb(err, undefined, NOOP) + if (!pendingItem.timedOut) { + pendingItem.callback(err, undefined, NOOP) + } } else { this.log('new client connected') client.release = release.bind(this, client) this.emit('connect', client) this.emit('acquire', client) - if (this.options.verify) { - this.options.verify(client, cb) + if (!pendingItem.timedOut) { + if (this.options.verify) { + this.options.verify(client, pendingItem.callback) + } else { + pendingItem.callback(undefined, client, client.release) + } } else { - cb(undefined, client, client.release) + if (this.options.verify) { + this.options.verify(client, client.release) + } else { + client.release() + } } } }) - return response.result } query (text, values, cb) { diff --git a/test/connection-timeout.js b/test/connection-timeout.js index f7a2fd8ea..2c4d68f7a 100644 --- a/test/connection-timeout.js +++ b/test/connection-timeout.js @@ -11,6 +11,8 @@ const after = require('mocha').after const Pool = require('../') describe('connection timeout', () => { + const connectionFailure = new Error('Temporary connection failure') + before((done) => { this.server = net.createServer((socket) => { }) @@ -126,4 +128,94 @@ describe('connection timeout', () => { }) }) }) + + it('continues processing after a connection failure', (done) => { + const Client = require('pg').Client + const orgConnect = Client.prototype.connect + let called = false + + Client.prototype.connect = function (cb) { + // Simulate a failure on first call + if (!called) { + called = true + + return setTimeout(() => { + cb(connectionFailure) + }, 100) + } + // And pass-through the second call + orgConnect.call(this, cb) + } + + const pool = new Pool({ + Client: Client, + connectionTimeoutMillis: 1000, + max: 1 + }) + + pool.connect((err, client, release) => { + expect(err).to.be(connectionFailure) + + 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) + }) + }) + }) + + it('releases newly connected clients if the queued already timed out', (done) => { + const Client = require('pg').Client + + const orgConnect = Client.prototype.connect + + let connection = 0 + + Client.prototype.connect = function (cb) { + // Simulate a failure on first call + if (connection === 0) { + connection++ + + return setTimeout(() => { + cb(connectionFailure) + }, 300) + } + + // And second connect taking > connection timeout + if (connection === 1) { + connection++ + + return setTimeout(() => { + orgConnect.call(this, cb) + }, 1000) + } + + orgConnect.call(this, cb) + } + + const pool = new Pool({ + Client: Client, + connectionTimeoutMillis: 1000, + max: 1 + }) + + // Direct connect + pool.connect((err, client, release) => { + expect(err).to.be(connectionFailure) + }) + + // Queued + let called = 0 + pool.connect((err, client, release) => { + // Verify the callback is only called once + expect(called++).to.be(0) + expect(err).to.be.an(Error) + + 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) + }) + }) + }) }) From f91769538d8036efbf394277d95d9471b9b64d6f Mon Sep 17 00:00:00 2001 From: Bryan Clement Date: Wed, 2 Jan 2019 10:10:42 -0800 Subject: [PATCH 0435/1037] idleListener no longer grabs references to things it doesn't need (#83) --- index.js | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/index.js b/index.js index fe921cbb2..cfe377c35 100644 --- a/index.js +++ b/index.js @@ -65,6 +65,20 @@ function promisify (Promise, callback) { return { callback: cb, result: result } } +function makeIdleListener (pool, client) { + return function idleListener (err) { + err.client = client + client.removeListener('error', idleListener) + client.on('error', () => { + pool.log('additional client error after disconnection due to error', err) + }) + pool._remove(client) + // TODO - document that once the pool emits an error + // the client has already been closed & purged and is unusable + pool.emit('error', err, client) + } +} + class Pool extends EventEmitter { constructor (options, Client) { super() @@ -197,17 +211,7 @@ class Pool extends EventEmitter { newClient (pendingItem) { 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) - } + const idleListener = makeIdleListener(this, client) this.log('checking client timeout') From 4d2ad3695192279f658d08d8cd5054661140def7 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 2 Jan 2019 12:11:21 -0600 Subject: [PATCH 0436/1037] Upgrade to test on node 10 (#114) * Upgrade to test on node 10 * Use errno instead of code * Only check errno if it exists --- .travis.yml | 2 +- package-lock.json | 2106 ++++++++++++++++++++++++++++++++++++ package.json | 6 +- test/connection-timeout.js | 3 + test/error-handling.js | 8 +- test/events.js | 3 +- test/mocha.opts | 1 - 7 files changed, 2120 insertions(+), 9 deletions(-) create mode 100644 package-lock.json diff --git a/.travis.yml b/.travis.yml index cd2db492f..0deb0216c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,6 @@ matrix: - node_js: "8" addons: postgresql: "9.6" - - node_js: "9" + - node_js: "10" addons: postgresql: "9.6" diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..a05e4c50f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2106 @@ +{ + "name": "pg-pool", + "version": "2.0.5", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "acorn": { + "version": "3.3.0", + "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "^3.0.4" + } + }, + "acorn-to-esprima": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/acorn-to-esprima/-/acorn-to-esprima-2.0.8.tgz", + "integrity": "sha1-AD8MZC65ITL0F9NwjxStqCrfLrE=", + "dev": true + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + } + }, + "babel-messages": { + "version": "6.23.0", + "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", + "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", + "dev": true, + "requires": { + "babel-runtime": "^6.22.0" + } + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "dev": true, + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "babel-traverse": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", + "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "babel-messages": "^6.23.0", + "babel-runtime": "^6.26.0", + "babel-types": "^6.26.0", + "babylon": "^6.18.0", + "debug": "^2.6.8", + "globals": "^9.18.0", + "invariant": "^2.2.2", + "lodash": "^4.17.4" + } + }, + "babel-types": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", + "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", + "dev": true, + "requires": { + "babel-runtime": "^6.26.0", + "esutils": "^2.0.2", + "lodash": "^4.17.4", + "to-fast-properties": "^1.0.3" + } + }, + "babylon": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", + "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bluebird": { + "version": "3.4.1", + "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-3.4.1.tgz", + "integrity": "sha1-tzHd9I4t077awudeEhWhG8uR+gc=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "^0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "http://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "dependencies": { + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", + "dev": true + }, + "commander": { + "version": "2.15.1", + "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "dev": true, + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "core-js": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.0.tgz", + "integrity": "sha512-kLRC6ncVpuEW/1kwrOXYX6KQASCVtrh1gQr/UiaVgFlf9WE5Vp+lNe5+h3LuMr5PAucWnnEXwH0nQHRH/gpGtw==", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "d": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "dev": true, + "requires": { + "es5-ext": "^0.10.9" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "debug-log": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", + "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", + "dev": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "^1.0.2" + } + }, + "deglob": { + "version": "1.1.2", + "resolved": "http://registry.npmjs.org/deglob/-/deglob-1.1.2.tgz", + "integrity": "sha1-dtV3wl/j9zKUEqK1nq3qV6xQDj8=", + "dev": true, + "requires": { + "find-root": "^1.0.0", + "glob": "^7.0.5", + "ignore": "^3.0.9", + "pkg-config": "^1.1.0", + "run-parallel": "^1.1.2", + "uniq": "^1.0.1", + "xtend": "^4.0.0" + }, + "dependencies": { + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "diff": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", + "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "dev": true + }, + "disparity": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", + "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", + "dev": true, + "requires": { + "ansi-styles": "^2.0.1", + "diff": "^1.3.2" + }, + "dependencies": { + "diff": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", + "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", + "dev": true + } + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "http://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "editorconfig": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.13.3.tgz", + "integrity": "sha512-WkjsUNVCu+ITKDj73QDvi0trvpdDWdkDyHybDGSXPfekLCqwmpD7CP7iPbvBgosNuLcI96XTDwNa75JyFl7tEQ==", + "dev": true, + "requires": { + "bluebird": "^3.0.5", + "commander": "^2.9.0", + "lru-cache": "^3.2.0", + "semver": "^5.1.0", + "sigmund": "^1.0.1" + }, + "dependencies": { + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + } + } + }, + "es5-ext": { + "version": "0.10.46", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", + "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", + "dev": true, + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", + "dev": true + }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "dev": true, + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "esformatter": { + "version": "0.9.6", + "resolved": "https://registry.npmjs.org/esformatter/-/esformatter-0.9.6.tgz", + "integrity": "sha1-Ngiux4KN7uPNP0bhGSrrRyaKlX8=", + "dev": true, + "requires": { + "acorn-to-esprima": "^2.0.6", + "babel-traverse": "^6.4.5", + "debug": "^0.7.4", + "disparity": "^2.0.0", + "esformatter-parser": "^1.0.0", + "glob": "^5.0.3", + "minimist": "^1.1.1", + "mout": ">=0.9 <2.0", + "npm-run": "^2.0.0", + "resolve": "^1.1.5", + "rocambole": ">=0.7 <2.0", + "rocambole-indent": "^2.0.4", + "rocambole-linebreak": "^1.0.2", + "rocambole-node": "~1.0", + "rocambole-token": "^1.1.2", + "rocambole-whitespace": "^1.0.0", + "stdin": "*", + "strip-json-comments": "~0.1.1", + "supports-color": "^1.3.1", + "user-home": "^2.0.0" + }, + "dependencies": { + "debug": { + "version": "0.7.4", + "resolved": "http://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=", + "dev": true + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "strip-json-comments": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-0.1.3.tgz", + "integrity": "sha1-Fkxk43Coo8wAyeAbU55WmCPw7lQ=", + "dev": true + }, + "supports-color": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", + "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=", + "dev": true + } + } + }, + "esformatter-eol-last": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esformatter-eol-last/-/esformatter-eol-last-1.0.0.tgz", + "integrity": "sha1-RaeP9GIrHUnkT1a0mQV2amMpDAc=", + "dev": true, + "requires": { + "string.prototype.endswith": "^0.2.0" + } + }, + "esformatter-ignore": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/esformatter-ignore/-/esformatter-ignore-0.1.3.tgz", + "integrity": "sha1-BNO4db+knd4ATMWN9va7w8BWfx4=", + "dev": true + }, + "esformatter-jsx": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/esformatter-jsx/-/esformatter-jsx-7.4.1.tgz", + "integrity": "sha1-siCa4JCPQTp0exIFcny/S6QklgI=", + "dev": true, + "requires": { + "babylon": "6.14.1", + "esformatter-ignore": "^0.1.3", + "extend": "3.0.0", + "js-beautify": "1.6.4" + }, + "dependencies": { + "babylon": { + "version": "6.14.1", + "resolved": "http://registry.npmjs.org/babylon/-/babylon-6.14.1.tgz", + "integrity": "sha1-lWJ1+rcnU62bNDXXr+WPi/CimBU=", + "dev": true + } + } + }, + "esformatter-literal-notation": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esformatter-literal-notation/-/esformatter-literal-notation-1.0.1.tgz", + "integrity": "sha1-cQ57QgF1/j9+WvrVu60ykQOELi8=", + "dev": true, + "requires": { + "rocambole": "^0.3.6", + "rocambole-token": "^1.2.1" + }, + "dependencies": { + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", + "dev": true + }, + "rocambole": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/rocambole/-/rocambole-0.3.6.tgz", + "integrity": "sha1-Teu/WUMUS8e2AG2Vvo+swLdDUqc=", + "dev": true, + "requires": { + "esprima": "~1.0" + } + } + } + }, + "esformatter-parser": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esformatter-parser/-/esformatter-parser-1.0.0.tgz", + "integrity": "sha1-CFQHLQSHU57TnK442KVDLBfsEdM=", + "dev": true, + "requires": { + "acorn-to-esprima": "^2.0.8", + "babel-traverse": "^6.9.0", + "babylon": "^6.8.0", + "rocambole": "^0.7.0" + } + }, + "esformatter-quotes": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esformatter-quotes/-/esformatter-quotes-1.1.0.tgz", + "integrity": "sha1-4ixsRFx/MGBB2BybnlH8psv6yoI=", + "dev": true + }, + "esformatter-remove-trailing-commas": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esformatter-remove-trailing-commas/-/esformatter-remove-trailing-commas-1.0.1.tgz", + "integrity": "sha1-k5diTB+qmA/E7Mfl6YE+tPK1gqc=", + "dev": true, + "requires": { + "rocambole-token": "^1.2.1" + } + }, + "esformatter-semicolon-first": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/esformatter-semicolon-first/-/esformatter-semicolon-first-1.2.0.tgz", + "integrity": "sha1-47US0dTgcxDqvKv1cnfqfIpW4kI=", + "dev": true, + "requires": { + "esformatter-parser": "^1.0", + "rocambole": ">=0.6.0 <2.0", + "rocambole-linebreak": "^1.0.2", + "rocambole-token": "^1.2.1" + } + }, + "esformatter-spaced-lined-comment": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esformatter-spaced-lined-comment/-/esformatter-spaced-lined-comment-2.0.1.tgz", + "integrity": "sha1-3F80B/k8KV4eVkRr00RWDaXm3Kw=", + "dev": true + }, + "eslint": { + "version": "2.10.2", + "resolved": "http://registry.npmjs.org/eslint/-/eslint-2.10.2.tgz", + "integrity": "sha1-sjCUgv7wQ9MgM2WjIShebM4Bw9c=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "concat-stream": "^1.4.6", + "debug": "^2.1.1", + "doctrine": "^1.2.1", + "es6-map": "^0.1.3", + "escope": "^3.6.0", + "espree": "3.1.4", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^1.1.1", + "glob": "^7.0.3", + "globals": "^9.2.0", + "ignore": "^3.1.2", + "imurmurhash": "^0.1.4", + "inquirer": "^0.12.0", + "is-my-json-valid": "^2.10.0", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.5.1", + "json-stable-stringify": "^1.0.0", + "lodash": "^4.0.0", + "mkdirp": "^0.5.0", + "optionator": "^0.8.1", + "path-is-absolute": "^1.0.0", + "path-is-inside": "^1.0.1", + "pluralize": "^1.2.1", + "progress": "^1.1.8", + "require-uncached": "^1.0.2", + "shelljs": "^0.6.0", + "strip-json-comments": "~1.0.1", + "table": "^3.7.8", + "text-table": "~0.2.0", + "user-home": "^2.0.0" + }, + "dependencies": { + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "eslint-config-standard-jsx": { + "version": "1.2.1", + "resolved": "http://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-1.2.1.tgz", + "integrity": "sha1-DRmxcF8K1INj7yqLv6cd8BLZibM=", + "dev": true + }, + "eslint-plugin-promise": { + "version": "1.3.2", + "resolved": "http://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-1.3.2.tgz", + "integrity": "sha1-/OMy1vX/UjIApTdwSGPsPCQiunw=", + "dev": true + }, + "eslint-plugin-react": { + "version": "5.2.2", + "resolved": "http://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-5.2.2.tgz", + "integrity": "sha1-fbBo4fVIf2hx5N7vNqOBwwPqwWE=", + "dev": true, + "requires": { + "doctrine": "^1.2.2", + "jsx-ast-utils": "^1.2.1" + } + }, + "eslint-plugin-standard": { + "version": "1.3.3", + "resolved": "http://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-1.3.3.tgz", + "integrity": "sha1-owhUUVI0MedvQJxwy4+U4yvw7H8=", + "dev": true + }, + "espree": { + "version": "3.1.4", + "resolved": "http://registry.npmjs.org/espree/-/espree-3.1.4.tgz", + "integrity": "sha1-BybXrIOvl6fISY2ps2OjYJ0qaKE=", + "dev": true, + "requires": { + "acorn": "^3.1.0", + "acorn-jsx": "^3.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "exit-hook": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", + "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", + "dev": true + }, + "expect.js": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/expect.js/-/expect.js-0.3.1.tgz", + "integrity": "sha1-sKWaDS7/VDdUTr8M6qYBWEHQm1s=", + "dev": true + }, + "extend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", + "integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + } + } + }, + "file-entry-cache": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-1.3.1.tgz", + "integrity": "sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dev": true, + "requires": { + "is-property": "^1.0.2" + } + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "^1.0.0" + } + }, + "get-stdin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", + "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "growl": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", + "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", + "dev": true + }, + "inquirer": { + "version": "0.12.0", + "resolved": "http://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", + "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", + "dev": true, + "requires": { + "ansi-escapes": "^1.1.0", + "ansi-regex": "^2.0.0", + "chalk": "^1.0.0", + "cli-cursor": "^1.0.1", + "cli-width": "^2.0.0", + "figures": "^1.3.5", + "lodash": "^4.3.0", + "readline2": "^1.0.1", + "run-async": "^0.1.0", + "rx-lite": "^3.1.2", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.0", + "through": "^2.3.6" + } + }, + "invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dev": true, + "requires": { + "loose-envify": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-my-ip-valid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", + "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", + "dev": true + }, + "is-my-json-valid": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", + "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", + "dev": true, + "requires": { + "generate-function": "^2.0.0", + "generate-object-property": "^1.1.0", + "is-my-ip-valid": "^1.0.0", + "jsonpointer": "^4.0.0", + "xtend": "^4.0.0" + } + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-beautify": { + "version": "1.6.4", + "resolved": "http://registry.npmjs.org/js-beautify/-/js-beautify-1.6.4.tgz", + "integrity": "sha1-qa95aZdCrJobb93B/bx4vE1RX8M=", + "dev": true, + "requires": { + "config-chain": "~1.1.5", + "editorconfig": "^0.13.2", + "mkdirp": "~0.5.0", + "nopt": "~3.0.1" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "~0.0.0" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "jsx-ast-utils": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", + "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lru-cache": { + "version": "3.2.0", + "resolved": "http://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", + "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", + "dev": true, + "requires": { + "pseudomap": "^1.0.1" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", + "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "dev": true, + "requires": { + "browser-stdout": "1.3.1", + "commander": "2.15.1", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.2", + "growl": "1.10.5", + "he": "1.1.1", + "minimatch": "3.0.4", + "mkdirp": "0.5.1", + "supports-color": "5.4.0" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + } + } + }, + "mout": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mout/-/mout-1.1.0.tgz", + "integrity": "sha512-XsP0vf4As6BfqglxZqbqQ8SR6KQot2AgxvR0gG+WtUkf90vUXchMOZQtPf/Hml1rEffJupqL/tIrU6EYhsUQjw==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multiline": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/multiline/-/multiline-1.0.2.tgz", + "integrity": "sha1-abHyX/B00oKJBPJE3dBrfZbvbJM=", + "dev": true, + "requires": { + "strip-indent": "^1.0.0" + } + }, + "mute-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", + "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", + "dev": true + }, + "next-tick": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", + "dev": true + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "npm-path": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-1.1.0.tgz", + "integrity": "sha1-BHSuAEGcMn1UcBt88s0F3Ii+EUA=", + "dev": true, + "requires": { + "which": "^1.2.4" + } + }, + "npm-run": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/npm-run/-/npm-run-2.0.0.tgz", + "integrity": "sha1-KN/ArV4uRv4ISOK9WN3wAue3PBU=", + "dev": true, + "requires": { + "minimist": "^1.1.1", + "npm-path": "^1.0.1", + "npm-which": "^2.0.0", + "serializerr": "^1.0.1", + "spawn-sync": "^1.0.5", + "sync-exec": "^0.5.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "npm-which": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-2.0.0.tgz", + "integrity": "sha1-DEaYIWC3gwk2YdHQG9RJbS/qu6w=", + "dev": true, + "requires": { + "commander": "^2.2.0", + "npm-path": "^1.0.0", + "which": "^1.0.5" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "os-shim": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", + "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=", + "dev": true + }, + "packet-reader": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", + "integrity": "sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "pg": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-7.7.1.tgz", + "integrity": "sha512-p3I0mXOmUvCoVlCMFW6iYSrnguPol6q8He15NGgSIdM3sPGjFc+8JGCeKclw8ZR4ETd+Jxy2KNiaPUcocHZeMw==", + "dev": true, + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "0.3.1", + "pg-connection-string": "0.1.3", + "pg-pool": "^2.0.4", + "pg-types": "~1.12.1", + "pgpass": "1.x", + "semver": "4.3.2" + } + }, + "pg-connection-string": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", + "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=", + "dev": true + }, + "pg-cursor": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/pg-cursor/-/pg-cursor-1.3.0.tgz", + "integrity": "sha1-siDxkIl2t7QNqjc8etpfyoI6sNk=", + "dev": true + }, + "pg-pool": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.5.tgz", + "integrity": "sha512-T4W9qzP2LjItXuXbW6jgAF2AY0jHp6IoTxRhM3GB7yzfBxzDnA3GCm0sAduzmmiCybMqD0+V1HiqIG5X2YWqlQ==", + "dev": true + }, + "pg-types": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.12.1.tgz", + "integrity": "sha1-1kCH45A7WP+q0nnnWVxSIIoUw9I=", + "dev": true, + "requires": { + "postgres-array": "~1.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.0", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", + "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", + "dev": true, + "requires": { + "split": "^1.0.0" + } + }, + "pkg-config": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pkg-config/-/pkg-config-1.1.1.tgz", + "integrity": "sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q=", + "dev": true, + "requires": { + "debug-log": "^1.0.0", + "find-root": "^1.0.0", + "xtend": "^4.0.1" + } + }, + "pluralize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", + "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", + "dev": true + }, + "postgres-array": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.3.tgz", + "integrity": "sha512-5wClXrAP0+78mcsNX3/ithQ5exKvCyK5lr5NEEEeGwwM6NJdQgzIJBVxLvRW+huFpX92F2QnZ5CcokH0VhK2qQ==", + "dev": true + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", + "dev": true + }, + "postgres-date": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.3.tgz", + "integrity": "sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g=", + "dev": true + }, + "postgres-interval": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.1.2.tgz", + "integrity": "sha512-fC3xNHeTskCxL1dC8KOtxXt7YeFmlbTYtn7ul8MkVERuTmf7pI4DrkAxcw3kh1fQ9uz4wQmd03a1mRiXUZChfQ==", + "dev": true, + "requires": { + "xtend": "^4.0.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "progress": { + "version": "1.1.8", + "resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz", + "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", + "dev": true + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "dev": true + }, + "protochain": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/protochain/-/protochain-1.0.5.tgz", + "integrity": "sha1-mRxAfpneJkqt+PgVBLXn+ve/omA=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readline2": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", + "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "mute-stream": "0.0.5" + } + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + } + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "dev": true, + "requires": { + "path-parse": "^1.0.5" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "^7.0.5" + }, + "dependencies": { + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "rocambole": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/rocambole/-/rocambole-0.7.0.tgz", + "integrity": "sha1-9seVBVF9xCtvuECEK4uVOw+WhYU=", + "dev": true, + "requires": { + "esprima": "^2.1" + }, + "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + } + } + }, + "rocambole-indent": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/rocambole-indent/-/rocambole-indent-2.0.4.tgz", + "integrity": "sha1-oYokl3ygQAuGHapGMehh3LUtCFw=", + "dev": true, + "requires": { + "debug": "^2.1.3", + "mout": "^0.11.0", + "rocambole-token": "^1.2.1" + }, + "dependencies": { + "mout": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/mout/-/mout-0.11.1.tgz", + "integrity": "sha1-ujYR318OWx/7/QEWa48C0fX6K5k=", + "dev": true + } + } + }, + "rocambole-linebreak": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/rocambole-linebreak/-/rocambole-linebreak-1.0.2.tgz", + "integrity": "sha1-A2IVFbQ7RyHJflocG8paA2Y2jy8=", + "dev": true, + "requires": { + "debug": "^2.1.3", + "rocambole-token": "^1.2.1", + "semver": "^4.3.1" + } + }, + "rocambole-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rocambole-node/-/rocambole-node-1.0.0.tgz", + "integrity": "sha1-21tJ3nQHsAgN1RSHLyjjk9D3/z8=", + "dev": true + }, + "rocambole-token": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rocambole-token/-/rocambole-token-1.2.1.tgz", + "integrity": "sha1-x4XfdCjcPLJ614lwR71SOMwHDTU=", + "dev": true + }, + "rocambole-whitespace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rocambole-whitespace/-/rocambole-whitespace-1.0.0.tgz", + "integrity": "sha1-YzMJSSVrKZQfWbGQRZ+ZnGsdO/k=", + "dev": true, + "requires": { + "debug": "^2.1.3", + "repeat-string": "^1.5.0", + "rocambole-token": "^1.2.1" + } + }, + "run-async": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", + "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", + "dev": true, + "requires": { + "once": "^1.3.0" + } + }, + "run-parallel": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", + "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", + "dev": true + }, + "rx-lite": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", + "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", + "dev": true + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "semver": { + "version": "4.3.2", + "resolved": "http://registry.npmjs.org/semver/-/semver-4.3.2.tgz", + "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=", + "dev": true + }, + "serializerr": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/serializerr/-/serializerr-1.0.3.tgz", + "integrity": "sha1-EtTFqhw/+49tHcXzlaqUVVacP5E=", + "dev": true, + "requires": { + "protochain": "^1.0.5" + } + }, + "shelljs": { + "version": "0.6.1", + "resolved": "http://registry.npmjs.org/shelljs/-/shelljs-0.6.1.tgz", + "integrity": "sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "http://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "spawn-sync": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz", + "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=", + "dev": true, + "requires": { + "concat-stream": "^1.4.7", + "os-shim": "^0.1.2" + } + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "requires": { + "through": "2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "standard": { + "version": "7.1.2", + "resolved": "http://registry.npmjs.org/standard/-/standard-7.1.2.tgz", + "integrity": "sha1-QBZu7sJAUGXRpPDj8VurxuJ0YH4=", + "dev": true, + "requires": { + "eslint": "~2.10.2", + "eslint-config-standard": "5.3.1", + "eslint-config-standard-jsx": "1.2.1", + "eslint-plugin-promise": "^1.0.8", + "eslint-plugin-react": "^5.0.1", + "eslint-plugin-standard": "^1.3.1", + "standard-engine": "^4.0.0" + }, + "dependencies": { + "eslint-config-standard": { + "version": "5.3.1", + "resolved": "http://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-5.3.1.tgz", + "integrity": "sha1-WRyWkVF0QTL1YdO5FagS6kE/5JA=", + "dev": true + } + } + }, + "standard-engine": { + "version": "4.1.3", + "resolved": "http://registry.npmjs.org/standard-engine/-/standard-engine-4.1.3.tgz", + "integrity": "sha1-ejGq1U8D2fOTVfQzic4GlPQJQVU=", + "dev": true, + "requires": { + "defaults": "^1.0.2", + "deglob": "^1.0.0", + "find-root": "^1.0.0", + "get-stdin": "^5.0.1", + "minimist": "^1.1.0", + "multiline": "^1.0.2", + "pkg-config": "^1.0.1", + "xtend": "^4.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "standard-format": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/standard-format/-/standard-format-2.2.4.tgz", + "integrity": "sha1-uQ+zmmNfdJzU/RF/5HMNMRearu8=", + "dev": true, + "requires": { + "deglob": "^1.0.0", + "esformatter": "^0.9.0", + "esformatter-eol-last": "^1.0.0", + "esformatter-jsx": "^7.0.0", + "esformatter-literal-notation": "^1.0.0", + "esformatter-quotes": "^1.0.0", + "esformatter-remove-trailing-commas": "^1.0.1", + "esformatter-semicolon-first": "^1.1.0", + "esformatter-spaced-lined-comment": "^2.0.0", + "minimist": "^1.1.0", + "stdin": "0.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "stdin": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/stdin/-/stdin-0.0.1.tgz", + "integrity": "sha1-0wQZgarsPf28d6GzjWNy449ftx4=", + "dev": true + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string.prototype.endswith": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/string.prototype.endswith/-/string.prototype.endswith-0.2.0.tgz", + "integrity": "sha1-oZwg3uUamHd+mkfhDwm+OTubunU=", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "^4.0.1" + }, + "dependencies": { + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + } + } + }, + "strip-json-comments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", + "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "sync-exec": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/sync-exec/-/sync-exec-0.5.0.tgz", + "integrity": "sha1-P3JY5KW6FyRTgZCfpqb2z1BuFmE=", + "dev": true + }, + "table": { + "version": "3.8.3", + "resolved": "http://registry.npmjs.org/table/-/table-3.8.3.tgz", + "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", + "dev": true, + "requires": { + "ajv": "^4.7.0", + "ajv-keywords": "^1.0.0", + "chalk": "^1.1.1", + "lodash": "^4.0.0", + "slice-ansi": "0.0.4", + "string-width": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "to-fast-properties": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", + "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "user-home": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", + "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", + "dev": true, + "requires": { + "os-homedir": "^1.0.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + } + } +} diff --git a/package.json b/package.json index c9334457f..cf7a14a1b 100644 --- a/package.json +++ b/package.json @@ -29,12 +29,12 @@ "bluebird": "3.4.1", "co": "4.6.0", "expect.js": "0.3.1", - "lodash": "4.13.1", - "mocha": "^2.3.3", + "lodash": "^4.17.11", + "mocha": "^5.2.0", "pg": "*", "pg-cursor": "^1.3.0", "standard": "7.1.2", - "standard-format": "2.2.1" + "standard-format": "^2.2.4" }, "dependencies": {}, "peerDependencies": { diff --git a/test/connection-timeout.js b/test/connection-timeout.js index 2c4d68f7a..8151354cc 100644 --- a/test/connection-timeout.js +++ b/test/connection-timeout.js @@ -15,6 +15,9 @@ describe('connection timeout', () => { before((done) => { this.server = net.createServer((socket) => { + socket.on('data', () => { + // discard any buffered data or the server wont terminate + }) }) this.server.listen(() => { diff --git a/test/error-handling.js b/test/error-handling.js index 1c84889cf..e899c350e 100644 --- a/test/error-handling.js +++ b/test/error-handling.js @@ -154,11 +154,15 @@ describe('pool error handling', function () { const pool = new Pool({ max: 1, port: closeServer.address().port }) pool.connect((err) => { expect(err).to.be.an(Error) - expect(err.message).to.be('Connection terminated unexpectedly') + if (err.errno) { + expect(err.errno).to.be('ECONNRESET') + } }) pool.connect((err) => { expect(err).to.be.an(Error) - expect(err.message).to.be('Connection terminated unexpectedly') + if (err.errno) { + expect(err.errno).to.be('ECONNRESET') + } closeServer.close(() => { pool.end(done) }) diff --git a/test/events.js b/test/events.js index 3d4405e28..a2da48100 100644 --- a/test/events.js +++ b/test/events.js @@ -23,14 +23,13 @@ describe('events', function () { }) }) - it('emits "connect" only with a successful connection', function (done) { + it('emits "connect" only with a successful connection', function () { 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) }) } }) diff --git a/test/mocha.opts b/test/mocha.opts index 590fb8628..eb0ba600d 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1,4 +1,3 @@ --require test/setup.js ---no-exit --bail --timeout 10000 From d7f6ed0c7cb7f546211ae3c90e6f1d50b7bcd383 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 2 Jan 2019 12:14:50 -0600 Subject: [PATCH 0437/1037] Bump version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index a05e4c50f..f977e2645 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "2.0.5", + "version": "2.0.6", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index cf7a14a1b..c4583b3ba 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "2.0.5", + "version": "2.0.6", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From 1200da5c747217ea8c487dfa8a91284854e9c2e8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 8 Jan 2019 08:52:05 -0600 Subject: [PATCH 0438/1037] Fix test --- index.js | 6 +- package-lock.json | 1807 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1810 insertions(+), 3 deletions(-) create mode 100644 package-lock.json diff --git a/index.js b/index.js index 615738e92..8d8a06ab0 100644 --- a/index.js +++ b/index.js @@ -9,7 +9,7 @@ var nextUniqueID = 1 // concept borrowed from org.postgresql.core.v3.QueryExecut function Cursor (text, values, config) { EventEmitter.call(this) - this._conf = config || { } + this._conf = config || {} this.text = text this.values = values ? values.map(prepare) : null this.connection = null @@ -148,7 +148,7 @@ Cursor.prototype.end = function (cb) { if (this.state !== 'initialized') { this.connection.sync() } - this.connection.stream.once('end', cb) + this.connection.once('end', cb) this.connection.end() } @@ -156,7 +156,7 @@ Cursor.prototype.close = function (cb) { if (this.state === 'done') { return setImmediate(cb) } - this.connection.close({type: 'P'}) + this.connection.close({ type: 'P' }) this.connection.sync() this.state = 'done' if (cb) { diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..662a212ae --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1807 @@ +{ + "name": "pg-cursor", + "version": "1.3.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-writer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.1.tgz", + "integrity": "sha1-Iqk2kB4wKa/NdUfrRIfOtpejvwg=", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "^0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "dev": true + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", + "dev": true, + "requires": { + "ajv": "^5.3.0", + "babel-code-frame": "^6.22.0", + "chalk": "^2.1.0", + "concat-stream": "^1.6.0", + "cross-spawn": "^5.1.0", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.4", + "esquery": "^1.0.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.0.1", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^3.0.6", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.9.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^1.0.1", + "require-uncached": "^1.0.3", + "semver": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "~2.0.1", + "table": "4.0.2", + "text-table": "~0.2.0" + } + }, + "eslint-config-standard": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", + "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", + "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", + "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", + "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", + "dev": true, + "requires": { + "contains-path": "^0.1.0", + "debug": "^2.6.8", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.1", + "eslint-module-utils": "^2.2.0", + "has": "^1.0.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.3", + "read-pkg-up": "^2.0.0", + "resolve": "^1.6.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-node": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", + "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", + "dev": true, + "requires": { + "ignore": "^3.3.6", + "minimatch": "^3.0.4", + "resolve": "^1.3.3", + "semver": "5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz", + "integrity": "sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==", + "dev": true + }, + "eslint-plugin-standard": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz", + "integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==", + "dev": true + }, + "eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "generic-pool": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.4.3.tgz", + "integrity": "sha1-eAw29p360FpaBF3Te+etyhGk9v8=", + "dev": true + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz", + "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==", + "dev": true + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-string-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", + "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "requires": { + "lodash._baseassign": "^3.0.0", + "lodash._basecreate": "^3.0.0", + "lodash._isiterateecall": "^3.0.0" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", + "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "he": "1.1.1", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "packet-reader": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", + "integrity": "sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc=", + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pg": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/pg/-/pg-6.4.2.tgz", + "integrity": "sha1-w2QBEGDqx6UHoq4GPrhX7OkQ4n8=", + "dev": true, + "requires": { + "buffer-writer": "1.0.1", + "js-string-escape": "1.0.1", + "packet-reader": "0.3.1", + "pg-connection-string": "0.1.3", + "pg-pool": "1.*", + "pg-types": "1.*", + "pgpass": "1.*", + "semver": "4.3.2" + }, + "dependencies": { + "semver": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", + "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=", + "dev": true + } + } + }, + "pg-connection-string": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", + "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=", + "dev": true + }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "dev": true + }, + "pg-pool": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-1.8.0.tgz", + "integrity": "sha1-9+xzgkw3oD8Hb1G/33DjQBR8Tzc=", + "dev": true, + "requires": { + "generic-pool": "2.4.3", + "object-assign": "4.1.0" + }, + "dependencies": { + "object-assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", + "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=", + "dev": true + } + } + }, + "pg-types": { + "version": "1.13.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.13.0.tgz", + "integrity": "sha512-lfKli0Gkl/+za/+b6lzENajczwZHc7D5kiUCZfgm914jipD2kIOIvEkAhZ8GrW3/TUoP9w8FHjwpPObBye5KQQ==", + "dev": true, + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "~1.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.0", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", + "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", + "dev": true, + "requires": { + "split": "^1.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "^1.0.0" + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "postgres-array": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.3.tgz", + "integrity": "sha512-5wClXrAP0+78mcsNX3/ithQ5exKvCyK5lr5NEEEeGwwM6NJdQgzIJBVxLvRW+huFpX92F2QnZ5CcokH0VhK2qQ==", + "dev": true + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", + "dev": true + }, + "postgres-date": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.3.tgz", + "integrity": "sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g=", + "dev": true + }, + "postgres-interval": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.1.2.tgz", + "integrity": "sha512-fC3xNHeTskCxL1dC8KOtxXt7YeFmlbTYtn7ul8MkVERuTmf7pI4DrkAxcw3kh1fQ9uz4wQmd03a1mRiXUZChfQ==", + "dev": true, + "requires": { + "xtend": "^4.0.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + } + }, + "resolve": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", + "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "*" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + } + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", + "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", + "dev": true + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "requires": { + "through": "2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "requires": { + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } +} From 1cdad4d8d20000dc6fb9a783394249b727106b84 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 8 Jan 2019 08:53:58 -0600 Subject: [PATCH 0439/1037] Bump version. Drop support for pg.js --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 662a212ae..571f921d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "1.3.0", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index e3b46b938..2841be631 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "1.3.0", + "version": "2.0.0", "description": "", "main": "index.js", "directories": { From c999aae6af17516a2aae235c1cc511d703a16fc4 Mon Sep 17 00:00:00 2001 From: Amila Welihinda Date: Tue, 8 Jan 2019 06:55:35 -0800 Subject: [PATCH 0440/1037] Updated readme examples to es6 (#36) --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 4e49d8f24..3b0e160b4 100644 --- a/README.md +++ b/README.md @@ -18,15 +18,15 @@ _requires pg>=2.8.1_ ## use ```js -var pg = require('pg') -var QueryStream = require('pg-query-stream') -var JSONStream = require('JSONStream') +const pg = require('pg') +const QueryStream = require('pg-query-stream') +const JSONStream = require('JSONStream') //pipe 1,000,000 rows to stdout without blowing up your memory usage -pg.connect(function(err, client, done) { - if(err) throw err; - var query = new QueryStream('SELECT * FROM generate_series(0, $1) num', [1000000]) - var stream = client.query(query) +pg.connect((err, client, done) => { + if (err) throw err; + const query = new QueryStream('SELECT * FROM generate_series(0, $1) num', [1000000]) + const stream = client.query(query) //release the client when the stream is finished stream.on('end', done) stream.pipe(JSONStream.stringify()).pipe(process.stdout) From d822fc8e7a3995869d0345acd4e352d35a857789 Mon Sep 17 00:00:00 2001 From: Amila Welihinda Date: Tue, 8 Jan 2019 06:57:36 -0800 Subject: [PATCH 0441/1037] Added --save flags to installation steps (#35) --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3b0e160b4..49e03749c 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,8 @@ Receive result rows from [pg](https://github.com/brianc/node-postgres) as a read ## installation ```bash -$ npm install pg -$ npm install pg-query-stream +$ npm install pg --save +$ npm install pg-query-stream --save ``` _requires pg>=2.8.1_ From 28e43b8b73b4af3390af6a2349afbf60b89f8cf8 Mon Sep 17 00:00:00 2001 From: Amila Welihinda Date: Tue, 8 Jan 2019 06:57:47 -0800 Subject: [PATCH 0442/1037] Create LICENSE (#34) --- LICENSE | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..c3ba81745 --- /dev/null +++ b/LICENSE @@ -0,0 +1,9 @@ +The MIT License (MIT) + +Copyright (c) 2013 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. From 5b2816a6f57c010ae36bb1867080afa15122d4b8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 8 Jan 2019 09:00:04 -0600 Subject: [PATCH 0443/1037] Bump version of pg-cursor --- package-lock.json | 1920 +++++++++++++++++++++++++++++++++++++++++++++ package.json | 2 +- 2 files changed, 1921 insertions(+), 1 deletion(-) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..b3a4475d2 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1920 @@ +{ + "name": "pg-query-stream", + "version": "1.1.2", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "JSONStream": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.7.4.tgz", + "integrity": "sha1-c0KQ5BUR7qfCz+FR+/mlY6l7l4Y=", + "dev": true, + "requires": { + "jsonparse": "0.0.5", + "through": ">=2.2.7 <3" + } + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "^3.0.4" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ajv-keywords": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", + "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", + "dev": true + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "assertions": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/assertions/-/assertions-2.3.4.tgz", + "integrity": "sha1-qUM87R/OV8yZmvCWXRAI6WwnluY=", + "dev": true, + "requires": { + "fomatto": "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6", + "render": "0.1", + "traverser": "1" + } + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "esutils": "^2.0.2", + "js-tokens": "^3.0.2" + }, + "dependencies": { + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "base64-js": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.2.tgz", + "integrity": "sha1-Ak8Pcq+iW3X5wO5zzU9V7Bvtl4Q=", + "dev": true + }, + "bops": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/bops/-/bops-0.0.6.tgz", + "integrity": "sha1-CC0dVfoB5g29wuvC26N/ZZVUzzo=", + "dev": true, + "requires": { + "base64-js": "0.0.2", + "to-utf8": "0.0.1" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "browser-stdout": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", + "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", + "dev": true + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "^0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "chardet": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", + "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", + "dev": true + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.0.1.tgz", + "integrity": "sha1-AYsYvBx9BzotyCqkhEI0GixN158=", + "dev": true, + "requires": { + "bops": "0.0.6" + } + }, + "contains-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", + "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "curry": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/curry/-/curry-0.0.4.tgz", + "integrity": "sha1-F1DVGNkZxE89N/9E7caT3h8NX8s=", + "dev": true + }, + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "diff": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", + "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", + "dev": true + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", + "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", + "dev": true, + "requires": { + "ajv": "^5.3.0", + "babel-code-frame": "^6.22.0", + "chalk": "^2.1.0", + "concat-stream": "^1.6.0", + "cross-spawn": "^5.1.0", + "debug": "^3.1.0", + "doctrine": "^2.1.0", + "eslint-scope": "^3.7.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^3.5.4", + "esquery": "^1.0.0", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.0.1", + "ignore": "^3.3.3", + "imurmurhash": "^0.1.4", + "inquirer": "^3.0.6", + "is-resolvable": "^1.0.0", + "js-yaml": "^3.9.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.4", + "minimatch": "^3.0.2", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^1.0.1", + "require-uncached": "^1.0.3", + "semver": "^5.3.0", + "strip-ansi": "^4.0.0", + "strip-json-comments": "~2.0.1", + "table": "4.0.2", + "text-table": "~0.2.0" + }, + "dependencies": { + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + } + } + }, + "eslint-config-standard": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", + "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", + "dev": true + }, + "eslint-import-resolver-node": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", + "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", + "dev": true, + "requires": { + "debug": "^2.6.9", + "resolve": "^1.5.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-module-utils": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", + "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", + "dev": true, + "requires": { + "debug": "^2.6.8", + "pkg-dir": "^1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-import": { + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", + "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", + "dev": true, + "requires": { + "contains-path": "^0.1.0", + "debug": "^2.6.8", + "doctrine": "1.5.0", + "eslint-import-resolver-node": "^0.3.1", + "eslint-module-utils": "^2.2.0", + "has": "^1.0.1", + "lodash": "^4.17.4", + "minimatch": "^3.0.3", + "read-pkg-up": "^2.0.0", + "resolve": "^1.6.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "doctrine": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", + "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", + "dev": true, + "requires": { + "esutils": "^2.0.2", + "isarray": "^1.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + } + } + }, + "eslint-plugin-node": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", + "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", + "dev": true, + "requires": { + "ignore": "^3.3.6", + "minimatch": "^3.0.4", + "resolve": "^1.3.3", + "semver": "5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "dev": true + } + } + }, + "eslint-plugin-promise": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz", + "integrity": "sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==", + "dev": true + }, + "eslint-plugin-standard": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz", + "integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==", + "dev": true + }, + "eslint-scope": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", + "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", + "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", + "dev": true, + "requires": { + "acorn": "^5.5.0", + "acorn-jsx": "^3.0.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "external-editor": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", + "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", + "dev": true, + "requires": { + "chardet": "^0.4.0", + "iconv-lite": "^0.4.17", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "flat-cache": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", + "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "graceful-fs": "^4.1.2", + "rimraf": "~2.6.2", + "write": "^0.2.1" + } + }, + "fomatto": { + "version": "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6", + "from": "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6", + "dev": true + }, + "from": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/from/-/from-0.0.2.tgz", + "integrity": "sha1-f/+sZHovmbINV7jig3lFXLtBidA=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz", + "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==", + "dev": true + }, + "graceful-fs": { + "version": "4.1.15", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", + "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "growl": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", + "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "he": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", + "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", + "dev": true + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "inquirer": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^2.0.4", + "figures": "^2.0.0", + "lodash": "^4.3.0", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rx-lite": "^4.0.8", + "rx-lite-aggregates": "^4.0.8", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", + "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json3": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", + "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", + "dev": true + }, + "jsonparse": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", + "dev": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "dependencies": { + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basecreate": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", + "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash.create": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", + "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", + "dev": true, + "requires": { + "lodash._baseassign": "^3.0.0", + "lodash._basecreate": "^3.0.0", + "lodash._isiterateecall": "^3.0.0" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" + } + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "macgyver": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/macgyver/-/macgyver-1.10.1.tgz", + "integrity": "sha1-sJ0VmdizbtWxb1lYlRXZ0UvC/Yg=", + "dev": true + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "mocha": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", + "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", + "dev": true, + "requires": { + "browser-stdout": "1.3.0", + "commander": "2.9.0", + "debug": "2.6.8", + "diff": "3.2.0", + "escape-string-regexp": "1.0.5", + "glob": "7.1.1", + "growl": "1.9.2", + "he": "1.1.1", + "json3": "3.3.2", + "lodash.create": "3.1.1", + "mkdirp": "0.5.1", + "supports-color": "3.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "glob": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", + "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.2", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "supports-color": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", + "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", + "dev": true, + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "packet-reader": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", + "integrity": "sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc=", + "dev": true + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "^1.2.0" + } + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", + "dev": true + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "^2.0.0" + } + }, + "pg": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/pg/-/pg-7.7.1.tgz", + "integrity": "sha512-p3I0mXOmUvCoVlCMFW6iYSrnguPol6q8He15NGgSIdM3sPGjFc+8JGCeKclw8ZR4ETd+Jxy2KNiaPUcocHZeMw==", + "dev": true, + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "0.3.1", + "pg-connection-string": "0.1.3", + "pg-pool": "^2.0.4", + "pg-types": "~1.12.1", + "pgpass": "1.x", + "semver": "4.3.2" + }, + "dependencies": { + "semver": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", + "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=", + "dev": true + } + } + }, + "pg-connection-string": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", + "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=", + "dev": true + }, + "pg-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/pg-cursor/-/pg-cursor-2.0.0.tgz", + "integrity": "sha512-/gYHadqLurektHk6HXiL0hSrn+RZfowkLr+ftC0lLoLBlIm8JIdk9f9g71EEjK63XxqhFqcykHuxQLFzSeyzdQ==" + }, + "pg-pool": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.6.tgz", + "integrity": "sha512-hod2zYQxM8Gt482q+qONGTYcg/qVcV32VHVPtktbBJs0us3Dj7xibISw0BAAXVMCzt8A/jhfJvpZaxUlqtqs0g==", + "dev": true + }, + "pg-types": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.12.1.tgz", + "integrity": "sha1-1kCH45A7WP+q0nnnWVxSIIoUw9I=", + "dev": true, + "requires": { + "postgres-array": "~1.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.0", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", + "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", + "dev": true, + "requires": { + "split": "^1.0.0" + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", + "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", + "dev": true, + "requires": { + "find-up": "^1.0.0" + } + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "postgres-array": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.3.tgz", + "integrity": "sha512-5wClXrAP0+78mcsNX3/ithQ5exKvCyK5lr5NEEEeGwwM6NJdQgzIJBVxLvRW+huFpX92F2QnZ5CcokH0VhK2qQ==", + "dev": true + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", + "dev": true + }, + "postgres-date": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.3.tgz", + "integrity": "sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g=", + "dev": true + }, + "postgres-interval": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.1.2.tgz", + "integrity": "sha512-fC3xNHeTskCxL1dC8KOtxXt7YeFmlbTYtn7ul8MkVERuTmf7pI4DrkAxcw3kh1fQ9uz4wQmd03a1mRiXUZChfQ==", + "dev": true, + "requires": { + "xtend": "^4.0.0" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + } + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "regexpp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", + "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", + "dev": true + }, + "render": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/render/-/render-0.1.4.tgz", + "integrity": "sha1-z7M6NOJgaFkdQYRp4j2Mxc4c7/U=", + "dev": true, + "requires": { + "traverser": "0.0.x" + }, + "dependencies": { + "traverser": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/traverser/-/traverser-0.0.5.tgz", + "integrity": "sha1-xm84xFagwhqIAUsSI1gMfr4GMes=", + "dev": true, + "requires": { + "curry": "0.0.x" + } + } + } + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + } + }, + "resolve": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", + "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", + "dev": true, + "requires": { + "path-parse": "^1.0.6" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "*" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", + "dev": true + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + } + }, + "spdx-correct": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", + "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", + "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", + "dev": true + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "requires": { + "through": "2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "stream-spec": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/stream-spec/-/stream-spec-0.3.6.tgz", + "integrity": "sha1-L92sSge/Pp+JY8Z3prWmzCEVJV4=", + "dev": true, + "requires": { + "macgyver": "~1.10" + } + }, + "stream-tester": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stream-tester/-/stream-tester-0.0.5.tgz", + "integrity": "sha1-T4byUxFJra9t1LP/Ji7fZK6aFxo=", + "dev": true, + "requires": { + "assertions": "~2.3.0", + "from": "~0.0.2", + "through": "~0.0.3" + }, + "dependencies": { + "through": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/through/-/through-0.0.4.tgz", + "integrity": "sha1-C/Lw//r6rEusvFM2Z+mKrQC1iMg=", + "dev": true + } + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + } + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "table": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", + "dev": true, + "requires": { + "ajv": "^5.2.3", + "ajv-keywords": "^2.1.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-utf8": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/to-utf8/-/to-utf8-0.0.1.tgz", + "integrity": "sha1-0Xrqcv8vujm55DYBvns/9y4ImFI=", + "dev": true + }, + "traverser": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/traverser/-/traverser-1.0.0.tgz", + "integrity": "sha1-b1nlgTdZruqzZGuPRRP9SmLk/iA=", + "dev": true, + "requires": { + "curry": "0.0.x" + } + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + } + } +} diff --git a/package.json b/package.json index e106abcba..73e59ae73 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,6 @@ "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "1.3.0" + "pg-cursor": "2.0.0" } } From 7d27bd208673209b56646e4c13812c56a4f364dd Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 8 Jan 2019 09:00:19 -0600 Subject: [PATCH 0444/1037] Bump version. Drop version of pg.js via pg-cursor. --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index b3a4475d2..85cda9c3a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "1.1.2", + "version": "2.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 73e59ae73..da5122926 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "1.1.2", + "version": "2.0.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From ccbccc9716a62adf06515143a575d26b73db0789 Mon Sep 17 00:00:00 2001 From: Gregory Lepsky <44976389+glepsky@users.noreply.github.com> Date: Tue, 8 Jan 2019 10:08:43 -0500 Subject: [PATCH 0445/1037] Issue #1769 - Inability to restrict communication protocols to set in ssl configuration (#1804) - Propagate client's ssl.secureOptions config to TLS. --- lib/connection.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/connection.js b/lib/connection.js index 177739c32..513e58981 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -101,6 +101,7 @@ Connection.prototype.connect = function (port, host) { key: self.ssl.key, passphrase: self.ssl.passphrase, cert: self.ssl.cert, + secureOptions: self.ssl.secureOptions, NPNProtocols: self.ssl.NPNProtocols }) self.attachListeners(self.stream) From 0e11b5c781febec99022e7dac45a31e2caad5c91 Mon Sep 17 00:00:00 2001 From: Ben Drucker Date: Fri, 11 Jan 2019 06:16:29 -0800 Subject: [PATCH 0446/1037] deps: update pg-types to 2 (#1806) drops node < 4 support but pg previously did so (not major) --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b98630c6f..15dc7051e 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "packet-reader": "0.3.1", "pg-connection-string": "0.1.3", "pg-pool": "^2.0.4", - "pg-types": "~1.12.1", + "pg-types": "~2.0.0", "pgpass": "1.x", "semver": "4.3.2" }, From c8f2f2384544ce7ae8fa7f6d9949e5b263829282 Mon Sep 17 00:00:00 2001 From: Ben Holden-Crowther Date: Fri, 11 Jan 2019 14:16:54 +0000 Subject: [PATCH 0447/1037] Update license date (#1800) From 2018 to 2019 --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 6a6bfe763..389a2783c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2010 - 2018 Brian Carlson +Copyright (c) 2010 - 2019 Brian 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 From 896faa56f711133f3e7889e5c9d1af9fb22231c1 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 11 Jan 2019 08:30:37 -0600 Subject: [PATCH 0448/1037] Update SPONSORS.md --- SPONSORS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SPONSORS.md b/SPONSORS.md index 59790b660..375488169 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -17,3 +17,5 @@ node-postgres is made possible by the helpful contributors from the community we - Benjie Gillam - David Hanson - Franklin Davenport +- [Eventbot](https://geteventbot.com/) +- Chuck T From 00123861fbb8a156ae4bf28e602722a6cb6b6880 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 11 Jan 2019 08:32:23 -0600 Subject: [PATCH 0449/1037] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b2f34ac2d..b28b45d1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.8.0 + +- Add support for passing [secureOptions](https://github.com/brianc/node-postgres/pull/1804) SSL config. +- Upgrade [pg-types](https://github.com/brianc/node-postgres/pull/1806) to 2.0. + ### 7.7.0 - Add support for configurable [query timeout](https://github.com/brianc/node-postgres/pull/1760) on a client level. From fcd0f02210f532bf2d823ea05105f4aaade389eb Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 11 Jan 2019 08:32:29 -0600 Subject: [PATCH 0450/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 15dc7051e..04e1e729c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.7.1", + "version": "7.8.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From bf84db7c22bd352bda60578992996f61c6765ef3 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 20 Feb 2019 14:36:27 -0600 Subject: [PATCH 0451/1037] Bump packet-reader version (#1840) * Bump packet-reader version This should fix the deprecation warning from using `new Buffer`. * Remove node 11 tests - its a non-stable (odd) version --- .travis.yml | 3 --- package.json | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 96d28c670..34d78369f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,9 +17,6 @@ matrix: - node_js: "10" addons: postgresql: "9.6" - - node_js: "11" - addons: - postgresql: "9.6" - node_js: "lts/carbon" addons: postgresql: "9.1" diff --git a/package.json b/package.json index 04e1e729c..813349a69 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "main": "./lib", "dependencies": { "buffer-writer": "2.0.0", - "packet-reader": "0.3.1", + "packet-reader": "1.0.0", "pg-connection-string": "0.1.3", "pg-pool": "^2.0.4", "pg-types": "~2.0.0", From e0ebdeff88210d8afcaff966bb960e630e6b28ea Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 20 Feb 2019 14:36:50 -0600 Subject: [PATCH 0452/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 813349a69..576379f81 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.8.0", + "version": "7.8.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 4c6c0e9b77f2205acc0f636cfdbaea7fc0c5039f Mon Sep 17 00:00:00 2001 From: Ben Holden-Crowther <4144334+blrhc@users.noreply.github.com> Date: Wed, 6 Mar 2019 15:34:06 +0000 Subject: [PATCH 0453/1037] Update license date in readme (#1823) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2aa5675f3..60cef5306 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ The causes and solutions to common errors can be found among the [Frequently Ask ## License -Copyright (c) 2010-2018 Brian Carlson (brian.m.carlson@gmail.com) +Copyright (c) 2010-2019 Brian Carlson (brian.m.carlson@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From e6a878cbb5f6d3694913091bf398d6dc35b4fbed Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Wed, 6 Mar 2019 10:35:30 -0500 Subject: [PATCH 0454/1037] compare prepared statement text with previous to prevent incorrect queries (#1814) * compare prepared statement text with previous to prevent incorrect queries - fixes #1813 * make suggested changes to error message --- lib/client.js | 2 +- lib/native/query.js | 6 +++++- lib/query.js | 4 ++++ test/integration/client/prepared-statement-tests.js | 11 +++++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/client.js b/lib/client.js index 8e7d307f7..194bc097a 100644 --- a/lib/client.js +++ b/lib/client.js @@ -276,7 +276,7 @@ Client.prototype._attachListeners = function (con) { // it again on the same client con.on('parseComplete', function (msg) { if (self.activeQuery.name) { - con.parsedStatements[self.activeQuery.name] = true + con.parsedStatements[self.activeQuery.name] = self.activeQuery.text } }) diff --git a/lib/native/query.js b/lib/native/query.js index 7602d161b..db4eb8cca 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -139,12 +139,16 @@ NativeQuery.prototype.submit = function (client) { // check if the client has already executed this named query // if so...just execute it again - skip the planning phase if (client.namedQueries[this.name]) { + if (this.text && client.namedQueries[this.name] !== this.text) { + const err = new Error(`Prepared statements must be unique - '${this.name}' was used for a different statement`) + return after(err) + } return client.native.execute(this.name, values, after) } // plan the named query the first time, then execute it return client.native.prepare(this.name, this.text, values.length, function (err) { if (err) return after(err) - client.namedQueries[self.name] = true + client.namedQueries[self.name] = self.text return self.native.execute(self.name, values, after) }) } else if (this.values) { diff --git a/lib/query.js b/lib/query.js index 94c2bc3c1..9e34b0d2b 100644 --- a/lib/query.js +++ b/lib/query.js @@ -148,6 +148,10 @@ Query.prototype.submit = function (connection) { if (typeof this.text !== 'string' && typeof this.name !== 'string') { return new Error('A query must have either text or a name. Supplying neither is unsupported.') } + const previous = connection.parsedStatements[this.name] + if (this.text && previous && this.text !== previous) { + return new Error(`Prepared statements must be unique - '${this.name}' was used for a different statement`) + } if (this.values && !Array.isArray(this.values)) { return new Error('Query values must be an array') } diff --git a/test/integration/client/prepared-statement-tests.js b/test/integration/client/prepared-statement-tests.js index 188bf8266..76654eaa3 100644 --- a/test/integration/client/prepared-statement-tests.js +++ b/test/integration/client/prepared-statement-tests.js @@ -56,6 +56,17 @@ var suite = new helper.Suite() q.on('end', () => done()) }) + + suite.test('with same name, but with different text', function (done) { + client.query(new Query({ + text: 'select name from person where age >= $1 and name LIKE $2', + name: queryName, + values: [30, '%n%'] + }), assert.calls(err => { + assert.equal(err.message, `Prepared statements must be unique - '${queryName}' was used for a different statement`) + done() + })) + }) })() ;(function () { From bae9fd734ac79c22420fee284dfbfdfccd8014c3 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 7 Mar 2019 08:58:13 -0600 Subject: [PATCH 0455/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 576379f81..bb1b65fc2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.8.1", + "version": "7.8.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 41706e64d48d339f5bb3c4b6769bb82680b68e41 Mon Sep 17 00:00:00 2001 From: Rhys Arkins Date: Thu, 7 Mar 2019 17:37:14 +0100 Subject: [PATCH 0456/1037] chore: don't publish Travis to npm (#1851) --- .npmignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.npmignore b/.npmignore index 4e5fcac5d..50e3c1bbe 100644 --- a/.npmignore +++ b/.npmignore @@ -6,3 +6,4 @@ node_modules/ script/ *.swp test/ +.travis.yml From 5a92ba3701e576b91697e653c6c369500811e9e5 Mon Sep 17 00:00:00 2001 From: andreme Date: Fri, 8 Mar 2019 01:02:21 +0800 Subject: [PATCH 0457/1037] sasl/scram authentication (#1835) --- lib/client.js | 23 +++ lib/connection.js | 78 ++++++++-- lib/sasl.js | 146 ++++++++++++++++++ test/buffer-list.js | 7 + test/integration/client/sasl-scram-tests.js | 41 +++++ test/test-buffers.js | 22 +++ test/unit/client/sasl-scram-tests.js | 135 ++++++++++++++++ test/unit/connection/inbound-parser-tests.js | 29 +++- .../unit/connection/outbound-sending-tests.js | 10 ++ 9 files changed, 473 insertions(+), 18 deletions(-) create mode 100644 lib/sasl.js create mode 100644 test/integration/client/sasl-scram-tests.js create mode 100644 test/unit/client/sasl-scram-tests.js diff --git a/lib/client.js b/lib/client.js index 194bc097a..a518ca011 100644 --- a/lib/client.js +++ b/lib/client.js @@ -10,6 +10,7 @@ var EventEmitter = require('events').EventEmitter var util = require('util') var utils = require('./utils') +var sasl = require('./sasl') var pgPass = require('pgpass') var TypeOverrides = require('./type-overrides') @@ -126,6 +127,28 @@ Client.prototype._connect = function (callback) { con.password(utils.postgresMd5PasswordHash(self.user, self.password, msg.salt)) })) + // password request handling (SASL) + var saslSession + con.on('authenticationSASL', checkPgPass(function (msg) { + saslSession = sasl.startSession(msg.mechanisms) + + con.sendSASLInitialResponseMessage(saslSession.mechanism, saslSession.response) + })) + + // password request handling (SASL) + con.on('authenticationSASLContinue', function (msg) { + sasl.continueSession(saslSession, self.password, msg.data) + + con.sendSCRAMClientFinalMessage(saslSession.response) + }) + + // password request handling (SASL) + con.on('authenticationSASLFinal', function (msg) { + sasl.finalizeSession(saslSession, msg.data) + + saslSession = null + }) + con.once('backendKeyData', function (msg) { self.processID = msg.processID self.secretKey = msg.secretKey diff --git a/lib/connection.js b/lib/connection.js index 513e58981..1f0af2f11 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -191,6 +191,24 @@ Connection.prototype.password = function (password) { this._send(0x70, this.writer.addCString(password)) } +Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) { + // 0x70 = 'p' + this.writer + .addCString(mechanism) + .addInt32(Buffer.byteLength(initialResponse)) + .addString(initialResponse) + + this._send(0x70) +} + +Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) { + // 0x70 = 'p' + this.writer + .addString(additionalData) + + this._send(0x70) +} + Connection.prototype._send = function (code, more) { if (!this.stream.writable) { return false @@ -421,25 +439,53 @@ Connection.prototype.parseMessage = function (buffer) { } Connection.prototype.parseR = function (buffer, length) { - var code = 0 + var code = this.parseInt32(buffer) + var msg = new Message('authenticationOk', length) - if (msg.length === 8) { - code = this.parseInt32(buffer) - if (code === 3) { - msg.name = 'authenticationCleartextPassword' - } - return msg - } - if (msg.length === 12) { - code = this.parseInt32(buffer) - if (code === 5) { // md5 required - msg.name = 'authenticationMD5Password' - msg.salt = Buffer.alloc(4) - buffer.copy(msg.salt, 0, this.offset, this.offset + 4) - this.offset += 4 + + switch (code) { + case 0: // AuthenticationOk + return msg + case 3: // AuthenticationCleartextPassword + if (msg.length === 8) { + msg.name = 'authenticationCleartextPassword' + return msg + } + break + case 5: // AuthenticationMD5Password + if (msg.length === 12) { + msg.name = 'authenticationMD5Password' + msg.salt = Buffer.alloc(4) + buffer.copy(msg.salt, 0, this.offset, this.offset + 4) + this.offset += 4 + return msg + } + + break + case 10: // AuthenticationSASL + msg.name = 'authenticationSASL' + msg.mechanisms = [] + do { + var mechanism = this.parseCString(buffer) + + if (mechanism) { + msg.mechanisms.push(mechanism) + } + } while (mechanism) + + return msg + case 11: // AuthenticationSASLContinue + msg.name = 'authenticationSASLContinue' + msg.data = this.readString(buffer, length - 4) + + return msg + case 12: // AuthenticationSASLFinal + msg.name = 'authenticationSASLFinal' + msg.data = this.readString(buffer, length - 4) + return msg - } } + throw new Error('Unknown authenticationOk message type' + util.inspect(msg)) } diff --git a/lib/sasl.js b/lib/sasl.js new file mode 100644 index 000000000..537ca350b --- /dev/null +++ b/lib/sasl.js @@ -0,0 +1,146 @@ +const crypto = require('crypto') + +function startSession (mechanisms) { + if (mechanisms.indexOf('SCRAM-SHA-256') === -1) { + throw new Error('SASL: Only mechanism SCRAM-SHA-256 is currently supported') + } + + const clientNonce = crypto.randomBytes(18).toString('base64') + + return { + mechanism: 'SCRAM-SHA-256', + clientNonce, + response: 'n,,n=*,r=' + clientNonce, + message: 'SASLInitialResponse' + } +} + +function continueSession (session, password, serverData) { + if (session.message !== 'SASLInitialResponse') { + throw new Error('SASL: Last message was not SASLInitialResponse') + } + + const sv = extractVariablesFromFirstServerMessage(serverData) + + if (!sv.nonce.startsWith(session.clientNonce)) { + throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce does not start with client nonce') + } + + var saltBytes = Buffer.from(sv.salt, 'base64') + + var saltedPassword = Hi(password, saltBytes, sv.iteration) + + var clientKey = createHMAC(saltedPassword, 'Client Key') + var storedKey = crypto.createHash('sha256').update(clientKey).digest() + + var clientFirstMessageBare = 'n=*,r=' + session.clientNonce + var serverFirstMessage = 'r=' + sv.nonce + ',s=' + sv.salt + ',i=' + sv.iteration + + var clientFinalMessageWithoutProof = 'c=biws,r=' + sv.nonce + + var authMessage = clientFirstMessageBare + ',' + serverFirstMessage + ',' + clientFinalMessageWithoutProof + + var clientSignature = createHMAC(storedKey, authMessage) + var clientProofBytes = xorBuffers(clientKey, clientSignature) + var clientProof = clientProofBytes.toString('base64') + + var serverKey = createHMAC(saltedPassword, 'Server Key') + var serverSignatureBytes = createHMAC(serverKey, authMessage) + + session.message = 'SASLResponse' + session.serverSignature = serverSignatureBytes.toString('base64') + session.response = clientFinalMessageWithoutProof + ',p=' + clientProof +} + +function finalizeSession (session, serverData) { + if (session.message !== 'SASLResponse') { + throw new Error('SASL: Last message was not SASLResponse') + } + + var serverSignature + + String(serverData).split(',').forEach(function (part) { + switch (part[0]) { + case 'v': + serverSignature = part.substr(2) + break + } + }) + + if (serverSignature !== session.serverSignature) { + throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature does not match') + } +} + +function extractVariablesFromFirstServerMessage (data) { + var nonce, salt, iteration + + String(data).split(',').forEach(function (part) { + switch (part[0]) { + case 'r': + nonce = part.substr(2) + break + case 's': + salt = part.substr(2) + break + case 'i': + iteration = parseInt(part.substr(2), 10) + break + } + }) + + if (!nonce) { + throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing') + } + + if (!salt) { + throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: salt missing') + } + + if (!iteration) { + throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing') + } + + return { + nonce, + salt, + iteration + } +} + +function xorBuffers (a, b) { + if (!Buffer.isBuffer(a)) a = Buffer.from(a) + if (!Buffer.isBuffer(b)) b = Buffer.from(b) + var res = [] + if (a.length > b.length) { + for (var i = 0; i < b.length; i++) { + res.push(a[i] ^ b[i]) + } + } else { + for (var j = 0; j < a.length; j++) { + res.push(a[j] ^ b[j]) + } + } + return Buffer.from(res) +} + +function createHMAC (key, msg) { + return crypto.createHmac('sha256', key).update(msg).digest() +} + +function Hi (password, saltBytes, iterations) { + var ui1 = createHMAC(password, Buffer.concat([saltBytes, Buffer.from([0, 0, 0, 1])])) + var ui = ui1 + for (var i = 0; i < iterations - 1; i++) { + ui1 = createHMAC(password, ui1) + ui = xorBuffers(ui, ui1) + } + + return ui +} + +module.exports = { + startSession, + continueSession, + finalizeSession +} diff --git a/test/buffer-list.js b/test/buffer-list.js index 527743fb2..e0a9007bf 100644 --- a/test/buffer-list.js +++ b/test/buffer-list.js @@ -36,6 +36,13 @@ p.addCString = function (val, front) { return this.add(buffer, front) } +p.addString = function (val, front) { + var len = Buffer.byteLength(val) + var buffer = Buffer.alloc(len) + buffer.write(val) + return this.add(buffer, front) +} + p.addChar = function (char, first) { return this.add(Buffer.from(char, 'utf8'), first) } diff --git a/test/integration/client/sasl-scram-tests.js b/test/integration/client/sasl-scram-tests.js new file mode 100644 index 000000000..f5326d8ae --- /dev/null +++ b/test/integration/client/sasl-scram-tests.js @@ -0,0 +1,41 @@ +'use strict' +var helper = require(__dirname + '/../test-helper') +var pg = helper.pg + +var suite = new helper.Suite() + +/* +SQL to create test role: + +set password_encryption = 'scram-sha-256'; +create role npgtest login password 'test'; + +pg_hba: +host all npgtest ::1/128 scram-sha-256 +host all npgtest 0.0.0.0/0 scram-sha-256 + + +*/ +/* +suite.test('can connect using sasl/scram', function () { + var connectionString = 'pg://npgtest:test@localhost/postgres' + const pool = new pg.Pool({ connectionString: connectionString }) + pool.connect( + assert.calls(function (err, client, done) { + assert.ifError(err, 'should have connected') + done() + }) + ) +}) + +suite.test('sasl/scram fails when password is wrong', function () { + var connectionString = 'pg://npgtest:bad@localhost/postgres' + const pool = new pg.Pool({ connectionString: connectionString }) + pool.connect( + assert.calls(function (err, client, done) { + assert.ok(err, 'should have a connection error') + done() + }) + ) +}) +*/ diff --git a/test/test-buffers.js b/test/test-buffers.js index 9873a3100..60a549492 100644 --- a/test/test-buffers.js +++ b/test/test-buffers.js @@ -28,6 +28,28 @@ buffers.authenticationMD5Password = function () { .join(true, 'R') } +buffers.authenticationSASL = function () { + return new BufferList() + .addInt32(10) + .addCString('SCRAM-SHA-256') + .addCString('') + .join(true, 'R') +} + +buffers.authenticationSASLContinue = function () { + return new BufferList() + .addInt32(11) + .addString('data') + .join(true, 'R') +} + +buffers.authenticationSASLFinal = function () { + return new BufferList() + .addInt32(12) + .addString('data') + .join(true, 'R') +} + buffers.parameterStatus = function (name, value) { return new BufferList() .addCString(name) diff --git a/test/unit/client/sasl-scram-tests.js b/test/unit/client/sasl-scram-tests.js new file mode 100644 index 000000000..9987c6cfa --- /dev/null +++ b/test/unit/client/sasl-scram-tests.js @@ -0,0 +1,135 @@ +'use strict' +require('./test-helper'); + +var sasl = require('../../../lib/sasl') + +test('sasl/scram', function () { + + test('startSession', function () { + + test('fails when mechanisms does not include SCRAM-SHA-256', function () { + assert.throws(function () { + sasl.startSession([]) + }, { + message: 'SASL: Only mechanism SCRAM-SHA-256 is currently supported', + }) + }) + + test('returns expected session data', function () { + const session = sasl.startSession(['SCRAM-SHA-256']) + + assert.equal(session.mechanism, 'SCRAM-SHA-256') + assert.equal(String(session.clientNonce).length, 24) + assert.equal(session.message, 'SASLInitialResponse') + + assert(session.response.match(/^n,,n=\*,r=.{24}/)) + }) + + test('creates random nonces', function () { + const session1 = sasl.startSession(['SCRAM-SHA-256']) + const session2 = sasl.startSession(['SCRAM-SHA-256']) + + assert(session1.clientNonce != session2.clientNonce) + }) + + }) + + test('continueSession', function () { + + test('fails when last session message was not SASLInitialResponse', function () { + assert.throws(function () { + sasl.continueSession({}) + }, { + message: 'SASL: Last message was not SASLInitialResponse', + }) + }) + + test('fails when nonce is missing in server message', function () { + assert.throws(function () { + sasl.continueSession({ + message: 'SASLInitialResponse', + }, "s=1,i=1") + }, { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing', + }) + }) + + test('fails when salt is missing in server message', function () { + assert.throws(function () { + sasl.continueSession({ + message: 'SASLInitialResponse', + }, "r=1,i=1") + }, { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: salt missing', + }) + }) + + test('fails when iteration is missing in server message', function () { + assert.throws(function () { + sasl.continueSession({ + message: 'SASLInitialResponse', + }, "r=1,s=1") + }, { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing', + }) + }) + + test('fails when server nonce does not start with client nonce', function () { + assert.throws(function () { + sasl.continueSession({ + message: 'SASLInitialResponse', + clientNonce: '2', + }, 'r=1,s=1,i=1') + }, { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce does not start with client nonce', + }) + }) + + test('sets expected session data', function () { + const session = { + message: 'SASLInitialResponse', + clientNonce: 'a', + }; + + sasl.continueSession(session, 'password', 'r=ab,s=x,i=1') + + assert.equal(session.message, 'SASLResponse') + assert.equal(session.serverSignature, 'TtywIrpWDJ0tCSXM2mjkyiaa8iGZsZG7HllQxr8fYAo=') + + assert.equal(session.response, 'c=biws,r=ab,p=KAEPBUTjjofB0IM5UWcZApK1dSzFE0o5vnbWjBbvFHA=') + }) + + }) + + test('continueSession', function () { + + test('fails when last session message was not SASLResponse', function () { + assert.throws(function () { + sasl.finalizeSession({}) + }, { + message: 'SASL: Last message was not SASLResponse', + }) + }) + + test('fails when server signature does not match', function () { + assert.throws(function () { + sasl.finalizeSession({ + message: 'SASLResponse', + serverSignature: '3', + }, "v=4") + }, { + message: 'SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature does not match', + }) + }) + + test('does not fail when eveything is ok', function () { + sasl.finalizeSession({ + message: 'SASLResponse', + serverSignature: '5', + }, "v=5") + }) + + }) + +}) + diff --git a/test/unit/connection/inbound-parser-tests.js b/test/unit/connection/inbound-parser-tests.js index 0eaefcc45..7bb9a4329 100644 --- a/test/unit/connection/inbound-parser-tests.js +++ b/test/unit/connection/inbound-parser-tests.js @@ -135,6 +135,9 @@ var testForMessage = function (buffer, expectedMessage) { var plainPasswordBuffer = buffers.authenticationCleartextPassword() var md5PasswordBuffer = buffers.authenticationMD5Password() +var SASLBuffer = buffers.authenticationSASL() +var SASLContinueBuffer = buffers.authenticationSASLContinue() +var SASLFinalBuffer = buffers.authenticationSASLFinal() var expectedPlainPasswordMessage = { name: 'authenticationCleartextPassword' @@ -144,6 +147,20 @@ var expectedMD5PasswordMessage = { name: 'authenticationMD5Password' } +var expectedSASLMessage = { + name: 'authenticationSASL', +} + +var expectedSASLContinueMessage = { + name: 'authenticationSASLContinue', + data: 'data', +} + +var expectedSASLFinalMessage = { + name: 'authenticationSASLFinal', + data: 'data', +} + var notificationResponseBuffer = buffers.notification(4, 'hi', 'boom') var expectedNotificationResponseMessage = { name: 'notification', @@ -155,10 +172,18 @@ var expectedNotificationResponseMessage = { test('Connection', function () { testForMessage(authOkBuffer, expectedAuthenticationOkayMessage) testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage) - var msg = testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage) + var msgMD5 = testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage) test('md5 has right salt', function () { - assert.equalBuffers(msg.salt, Buffer.from([1, 2, 3, 4])) + assert.equalBuffers(msgMD5.salt, Buffer.from([1, 2, 3, 4])) + }) + + var msgSASL = testForMessage(SASLBuffer, expectedSASLMessage) + test('SASL has the right mechanisms', function () { + assert.deepStrictEqual(msgSASL.mechanisms, ['SCRAM-SHA-256']) }) + testForMessage(SASLContinueBuffer, expectedSASLContinueMessage) + testForMessage(SASLFinalBuffer, expectedSASLFinalMessage) + testForMessage(paramStatusBuffer, expectedParameterStatusMessage) testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage) testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage) diff --git a/test/unit/connection/outbound-sending-tests.js b/test/unit/connection/outbound-sending-tests.js index b8b72a214..6c36401f0 100644 --- a/test/unit/connection/outbound-sending-tests.js +++ b/test/unit/connection/outbound-sending-tests.js @@ -34,6 +34,16 @@ test('sends password message', function () { assert.received(stream, new BufferList().addCString('!').join(true, 'p')) }) +test('sends SASLInitialResponseMessage message', function () { + con.sendSASLInitialResponseMessage('mech', 'data') + assert.received(stream, new BufferList().addCString('mech').addInt32(4).addString('data').join(true, 'p')) +}) + +test('sends SCRAMClientFinalMessage message', function () { + con.sendSCRAMClientFinalMessage('data') + assert.received(stream, new BufferList().addString('data').join(true, 'p')) +}) + test('sends query message', function () { var txt = 'select * from boom' con.query(txt) From 9cf3d324672b7655fb488e5ebce2359564e3bf07 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 15 Mar 2019 13:42:04 -0500 Subject: [PATCH 0458/1037] Update SPONSORS.md --- SPONSORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SPONSORS.md b/SPONSORS.md index 375488169..1bbda390b 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -2,6 +2,7 @@ node-postgres is made possible by the helpful contributors from the community we # Leaders - [MadKudu](https://www.madkudu.com) - [@madkudu](https://twitter.com/madkudu) +- [Third Iron](https://thirdiron.com/) # Supporters - John Fawcett From b12881209beb58a57a495a9a8cfbec632cb11338 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 15 Mar 2019 13:42:24 -0500 Subject: [PATCH 0459/1037] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b28b45d1b..eda24170b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.9.0 + +- Add support for [sasl/scram authentication](https://github.com/brianc/node-postgres/pull/1835). + ### 7.8.0 - Add support for passing [secureOptions](https://github.com/brianc/node-postgres/pull/1804) SSL config. From 6b8176e841584b76bcbd1972bf95e50558ba7395 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 15 Mar 2019 13:42:56 -0500 Subject: [PATCH 0460/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index bb1b65fc2..c912aeea1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.8.2", + "version": "7.9.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 4d84909cbd6f5590dd3b7649750a9e5208907e45 Mon Sep 17 00:00:00 2001 From: Malcolm Date: Tue, 16 Apr 2019 11:37:33 +1200 Subject: [PATCH 0461/1037] Fix integration test for v1.0.4 of postgres-date sub-dependency (#1867) --- test/integration/client/type-coercion-tests.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/client/type-coercion-tests.js b/test/integration/client/type-coercion-tests.js index 44ac89639..d0d740e45 100644 --- a/test/integration/client/type-coercion-tests.js +++ b/test/integration/client/type-coercion-tests.js @@ -179,7 +179,7 @@ suite.test('date range extremes', function (done) { })) client.query('SELECT $1::TIMESTAMPTZ as when', ['4713-12-31 12:31:59 BC GMT'], assert.success(function (res) { - assert.equal(res.rows[0].when.getFullYear(), -4713) + assert.equal(res.rows[0].when.getFullYear(), -4712) })) client.query('SELECT $1::TIMESTAMPTZ as when', ['275760-09-13 00:00:00 -15:00'], assert.success(function (res) { From 43ebcfb6bc5debdb49c32aee87cb0adae5a95935 Mon Sep 17 00:00:00 2001 From: Malcolm Date: Tue, 16 Apr 2019 11:38:20 +1200 Subject: [PATCH 0462/1037] Fix input preparation for date objects with a BC year (#1864) * test: BC date input preparation * Fix input preparation for BC dates --- lib/utils.js | 21 +++++++++++++++++---- test/unit/utils-tests.js | 21 +++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index ca5ab2a0a..879949f0c 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -97,7 +97,12 @@ function pad (number, digits) { function dateToString (date) { var offset = -date.getTimezoneOffset() - var ret = pad(date.getFullYear(), 4) + '-' + + + var year = date.getFullYear() + var isBCYear = year < 1 + if (isBCYear) year = Math.abs(year) + 1 // negative years are 1 off their BC representation + + var ret = pad(year, 4) + '-' + pad(date.getMonth() + 1, 2) + '-' + pad(date.getDate(), 2) + 'T' + pad(date.getHours(), 2) + ':' + @@ -110,11 +115,17 @@ function dateToString (date) { offset *= -1 } else { ret += '+' } - return ret + pad(Math.floor(offset / 60), 2) + ':' + pad(offset % 60, 2) + ret += pad(Math.floor(offset / 60), 2) + ':' + pad(offset % 60, 2) + if (isBCYear) ret += ' BC' + return ret } function dateToStringUTC (date) { - var ret = pad(date.getUTCFullYear(), 4) + '-' + + var year = date.getUTCFullYear() + var isBCYear = year < 1 + if (isBCYear) year = Math.abs(year) + 1 // negative years are 1 off their BC representation + + var ret = pad(year, 4) + '-' + pad(date.getUTCMonth() + 1, 2) + '-' + pad(date.getUTCDate(), 2) + 'T' + pad(date.getUTCHours(), 2) + ':' + @@ -122,7 +133,9 @@ function dateToStringUTC (date) { pad(date.getUTCSeconds(), 2) + '.' + pad(date.getUTCMilliseconds(), 3) - return ret + '+00:00' + ret += '+00:00' + if (isBCYear) ret += ' BC' + return ret } function normalizeQueryConfig (config, values, callback) { diff --git a/test/unit/utils-tests.js b/test/unit/utils-tests.js index 617fe2dd5..0bca25af7 100644 --- a/test/unit/utils-tests.js +++ b/test/unit/utils-tests.js @@ -81,6 +81,27 @@ test('prepareValues: date prepared properly as UTC', function () { defaults.parseInputDatesAsUTC = false }) +test('prepareValues: BC date prepared properly', function () { + helper.setTimezoneOffset(-330) + + var date = new Date(-3245, 1, 1, 11, 11, 1, 7) + var out = utils.prepareValue(date) + assert.strictEqual(out, '3246-02-01T11:11:01.007+05:30 BC') + + helper.resetTimezoneOffset() +}) + +test('prepareValues: 1 BC date prepared properly', function () { + helper.setTimezoneOffset(-330) + + // can't use the multi-argument constructor as year 0 would be interpreted as 1900 + var date = new Date('0000-02-01T11:11:01.007') + var out = utils.prepareValue(date) + assert.strictEqual(out, '0001-02-01T11:11:01.007+05:30 BC') + + helper.resetTimezoneOffset() +}) + test('prepareValues: undefined prepared properly', function () { var out = utils.prepareValue(void 0) assert.strictEqual(out, null) From 566058de17ef0dd532c8005261c1750afa3984f1 Mon Sep 17 00:00:00 2001 From: Tony Wooster Date: Wed, 17 Apr 2019 00:27:39 +0200 Subject: [PATCH 0463/1037] Add support for per per-query types (#1825) The documentation states that you can pass custom type processors to query objects. See: https://node-postgres.com/features/queries#types This didn't actually work. This commit adds an initial implementation of per-query type-parsing. Caveats: * It does not work with pg-native. That would require a separate pull request to pg-native, and a rather significant change to how that library handles query results. * Per-query types do not "inherit" from types assigned to the Client, ala TypeOverrides. --- lib/client.js | 5 ++-- lib/result.js | 7 ++--- test/integration/client/custom-types-tests.js | 28 +++++++++++++++---- 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/lib/client.js b/lib/client.js index a518ca011..3601787c7 100644 --- a/lib/client.js +++ b/lib/client.js @@ -478,8 +478,9 @@ Client.prototype.query = function (config, values, callback) { if (this.binary && !query.binary) { query.binary = true } - if (query._result) { - query._result._getTypeParser = this._types.getTypeParser.bind(this._types) + + if (query._result && !query._result._types) { + query._result._types = this._types } if (!this._queryable) { diff --git a/lib/result.js b/lib/result.js index 1e6bf849d..088298bc4 100644 --- a/lib/result.js +++ b/lib/result.js @@ -12,13 +12,14 @@ var types = require('pg-types') // result object returned from query // in the 'end' event and also // passed as second argument to provided callback -var Result = function (rowMode) { +var Result = function (rowMode, types) { this.command = null this.rowCount = null this.oid = null this.rows = [] this.fields = [] this._parsers = [] + this._types = types this.RowCtor = null this.rowAsArray = rowMode === 'array' if (this.rowAsArray) { @@ -94,11 +95,9 @@ Result.prototype.addFields = function (fieldDescriptions) { for (var i = 0; i < fieldDescriptions.length; i++) { var desc = fieldDescriptions[i] this.fields.push(desc) - var parser = this._getTypeParser(desc.dataTypeID, desc.format || 'text') + var parser = (this._types || types).getTypeParser(desc.dataTypeID, desc.format || 'text') this._parsers.push(parser) } } -Result.prototype._getTypeParser = types.getTypeParser - module.exports = Result diff --git a/test/integration/client/custom-types-tests.js b/test/integration/client/custom-types-tests.js index 99e04d01d..2b50fef08 100644 --- a/test/integration/client/custom-types-tests.js +++ b/test/integration/client/custom-types-tests.js @@ -3,13 +3,13 @@ const helper = require('./test-helper') const Client = helper.pg.Client const suite = new helper.Suite() -const client = new Client({ - types: { - getTypeParser: () => () => 'okay!' - } -}) +const customTypes = { + getTypeParser: () => () => 'okay!' +} suite.test('custom type parser in client config', (done) => { + const client = new Client({ types: customTypes }) + client.connect() .then(() => { client.query('SELECT NOW() as val', assert.success(function (res) { @@ -18,3 +18,21 @@ suite.test('custom type parser in client config', (done) => { })) }) }) + +// Custom type-parsers per query are not supported in native +if (!helper.args.native) { + suite.test('custom type parser in query', (done) => { + const client = new Client() + + client.connect() + .then(() => { + client.query({ + text: 'SELECT NOW() as val', + types: customTypes + }, assert.success(function (res) { + assert.equal(res.rows[0].val, 'okay!') + client.end().then(done) + })) + }) + }) +} From 13c14f1de0198952914bab2c9ba1613bea6f7371 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Tue, 16 Apr 2019 18:29:40 -0400 Subject: [PATCH 0464/1037] fix: Catch and emit query parameter prepareValue(...) errors (#1855) Adds a try/catch block around the prepareValue(...) invocations in query.prepare(...) to ensure that any that throw an error are caught and bubbled up to the caller. --- lib/query.js | 7 ++++- test/integration/gh-issues/1854-tests.js | 33 ++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 test/integration/gh-issues/1854-tests.js diff --git a/lib/query.js b/lib/query.js index 9e34b0d2b..41ed77ea2 100644 --- a/lib/query.js +++ b/lib/query.js @@ -194,7 +194,12 @@ Query.prototype.prepare = function (connection) { } if (self.values) { - self.values = self.values.map(utils.prepareValue) + try { + self.values = self.values.map(utils.prepareValue) + } catch (err) { + this.handleError(err, connection) + return + } } // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY diff --git a/test/integration/gh-issues/1854-tests.js b/test/integration/gh-issues/1854-tests.js new file mode 100644 index 000000000..8dbe37ab5 --- /dev/null +++ b/test/integration/gh-issues/1854-tests.js @@ -0,0 +1,33 @@ +"use strict" +var helper = require('./../test-helper') + +const suite = new helper.Suite() + +suite.test('Parameter serialization errors should not cause query to hang', (done) => { + if (helper.config.native) { + // pg-native cannot handle non-string parameters so skip this entirely + return done() + } + const client = new helper.pg.Client() + const expectedErr = new Error('Serialization error') + client.connect() + .then(() => { + const obj = { + toPostgres: function () { + throw expectedErr + } + } + return client.query('SELECT $1::text', [obj]) + .then(() => { + throw new Error('Expected a serialization error to be thrown but no error was thrown') + }) + }) + .catch((err) => { + client.end(() => {}) + if (err !== expectedErr) { + done(new Error('Expected a serialization error to be thrown but instead caught: ' + err)) + return + } + done() + }) +}) From 0f50d92ea6ccec371da4438ca3408dee534a6757 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 16 Apr 2019 17:35:08 -0500 Subject: [PATCH 0465/1037] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index eda24170b..1ec130170 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.10.0 +- Add support for [per-query types](https://github.com/brianc/node-postgres/pull/1825). + ### 7.9.0 - Add support for [sasl/scram authentication](https://github.com/brianc/node-postgres/pull/1835). From 4b530a9e0fb317567766260a2c57e28c88d55861 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 16 Apr 2019 17:35:20 -0500 Subject: [PATCH 0466/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c912aeea1..a2650dde1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.9.0", + "version": "7.10.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From c11dbb1c2b3409964372721666d3a2898dd2097e Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Thu, 18 Apr 2019 14:46:36 +0100 Subject: [PATCH 0467/1037] Only publish the required files Details: https://docs.npmjs.com/files/package.json#files --- package.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 5b75ea37a..b625a16d7 100644 --- a/package.json +++ b/package.json @@ -30,5 +30,9 @@ "chai": "^4.1.1", "istanbul": "^0.4.5", "mocha": "^3.5.0" - } + }, + "files": [ + "index.js", + "index.d.ts" + ] } From 0993e4b61ad1bafabc84b0335bc9b4caa8b72847 Mon Sep 17 00:00:00 2001 From: Peter Boromissza <2242020+boromisp@users.noreply.github.com> Date: Fri, 10 May 2019 18:48:38 +0200 Subject: [PATCH 0468/1037] Added the missing connect_timeout and keepalives_idle config parameters (#1847) * Added the missing connect_timeout and keepalives_idle config parameters * Implementation and tests for keepAliveInitialDelayMillis and connectionTimeoutMillis [squashed 4] --- lib/client.js | 12 +++ lib/connection-parameters.js | 21 ++++- lib/connection.js | 7 +- lib/defaults.js | 8 +- .../client/connection-timeout-tests.js | 85 +++++++++++++++++++ test/test-helper.js | 2 +- test/unit/client/set-keepalives.js | 32 +++++++ 7 files changed, 160 insertions(+), 7 deletions(-) create mode 100644 test/integration/client/connection-timeout-tests.js create mode 100644 test/unit/client/set-keepalives.js diff --git a/lib/client.js b/lib/client.js index 3601787c7..517f5cc14 100644 --- a/lib/client.js +++ b/lib/client.js @@ -44,6 +44,7 @@ var Client = function (config) { stream: c.stream, ssl: this.connectionParameters.ssl, keepAlive: c.keepAlive || false, + keepAliveInitialDelayMillis: c.keepAliveInitialDelayMillis || 0, encoding: this.connectionParameters.client_encoding || 'utf8' }) this.queryQueue = [] @@ -51,6 +52,7 @@ var Client = function (config) { this.processID = null this.secretKey = null this.ssl = this.connectionParameters.ssl || false + this._connectionTimeoutMillis = c.connectionTimeoutMillis || 0 } util.inherits(Client, EventEmitter) @@ -83,6 +85,14 @@ Client.prototype._connect = function (callback) { } this._connecting = true + var connectionTimeoutHandle + if (this._connectionTimeoutMillis > 0) { + connectionTimeoutHandle = setTimeout(() => { + con._ending = true + con.stream.destroy(new Error('timeout expired')) + }, this._connectionTimeoutMillis) + } + if (this.host && this.host.indexOf('/') === 0) { con.connect(this.host + '/.s.PGSQL.' + this.port) } else { @@ -159,6 +169,7 @@ Client.prototype._connect = function (callback) { return } this._connectionError = true + clearTimeout(connectionTimeoutHandle) if (callback) { return callback(err) } @@ -196,6 +207,7 @@ Client.prototype._connect = function (callback) { con.removeListener('errorMessage', connectingErrorHandler) con.on('error', connectedErrorHandler) con.on('errorMessage', connectedErrorMessageHandler) + clearTimeout(connectionTimeoutHandle) // process possible callback argument to Client#connect if (callback) { diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index 745311ad0..f45dc50a4 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -66,6 +66,22 @@ var ConnectionParameters = function (config) { this.fallback_application_name = val('fallback_application_name', config, false) this.statement_timeout = val('statement_timeout', config, false) this.query_timeout = val('query_timeout', config, false) + + if (config.connectionTimeoutMillis === undefined) { + this.connect_timeout = process.env.PGCONNECT_TIMEOUT || 0 + } else { + this.connect_timeout = Math.floor(config.connectionTimeoutMillis / 1000) + } + + if (config.keepAlive === false) { + this.keepalives = 0 + } else if (config.keepAlive === true) { + this.keepalives = 1 + } + + if (typeof config.keepAliveInitialDelayMillis === 'number') { + this.keepalives_idle = Math.floor(config.keepAliveInitialDelayMillis / 1000) + } } // Convert arg to a string, surround in single quotes, and escape single quotes and backslashes @@ -75,7 +91,7 @@ var quoteParamValue = function (value) { var add = function (params, config, paramName) { var value = config[paramName] - if (value) { + if (value !== undefined && value !== null) { params.push(paramName + '=' + quoteParamValue(value)) } } @@ -87,8 +103,9 @@ ConnectionParameters.prototype.getLibpqConnectionString = function (cb) { add(params, this, 'port') add(params, this, 'application_name') add(params, this, 'fallback_application_name') + add(params, this, 'connect_timeout') - var ssl = typeof this.ssl === 'object' ? this.ssl : { sslmode: this.ssl } + var ssl = typeof this.ssl === 'object' ? this.ssl : this.ssl ? { sslmode: this.ssl } : {} add(params, ssl, 'sslmode') add(params, ssl, 'sslca') add(params, ssl, 'sslkey') diff --git a/lib/connection.js b/lib/connection.js index 1f0af2f11..1ac2f668f 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -21,6 +21,7 @@ var Connection = function (config) { config = config || {} this.stream = config.stream || new net.Socket() this._keepAlive = config.keepAlive + this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis this.lastBuffer = false this.lastOffset = 0 this.buffer = null @@ -47,17 +48,17 @@ var Connection = function (config) { util.inherits(Connection, EventEmitter) Connection.prototype.connect = function (port, host) { + var self = this + if (this.stream.readyState === 'closed') { this.stream.connect(port, host) } else if (this.stream.readyState === 'open') { this.emit('connect') } - var self = this - this.stream.on('connect', function () { if (self._keepAlive) { - self.stream.setKeepAlive(true) + self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis) } self.emit('connect') }) diff --git a/lib/defaults.js b/lib/defaults.js index 6b0a98f1b..c520eb56b 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -58,7 +58,13 @@ module.exports = { statement_timeout: false, // max miliseconds to wait for query to complete (client side) - query_timeout: false + query_timeout: false, + + connect_timeout: 0, + + keepalives: 1, + + keepalives_idle: 0 } var pgTypes = require('pg-types') diff --git a/test/integration/client/connection-timeout-tests.js b/test/integration/client/connection-timeout-tests.js new file mode 100644 index 000000000..35e418858 --- /dev/null +++ b/test/integration/client/connection-timeout-tests.js @@ -0,0 +1,85 @@ +'use strict' +const net = require('net') +const buffers = require('../../test-buffers') +const helper = require('./test-helper') + +const suite = new helper.Suite() + +const options = { + host: 'localhost', + port: 54321, + connectionTimeoutMillis: 2000, + user: 'not', + database: 'existing' +} + +const serverWithConnectionTimeout = (timeout, callback) => { + const sockets = new Set() + + const server = net.createServer(socket => { + sockets.add(socket) + socket.once('end', () => sockets.delete(socket)) + + socket.on('data', data => { + // deny request for SSL + if (data.length === 8) { + socket.write(Buffer.from('N', 'utf8')) + // consider all authentication requests as good + } else if (!data[0]) { + socket.write(buffers.authenticationOk()) + // send ReadyForQuery `timeout` ms after authentication + setTimeout(() => socket.write(buffers.readyForQuery()), timeout).unref() + // respond with our canned response + } else { + socket.write(buffers.readyForQuery()) + } + }) + }) + + let closing = false + const closeServer = done => { + if (closing) return + closing = true + + server.close(done) + for (const socket of sockets) { + socket.destroy() + } + } + + server.listen(options.port, options.host, () => callback(closeServer)) +} + +suite.test('successful connection', done => { + serverWithConnectionTimeout(0, closeServer => { + const timeoutId = setTimeout(() => { + throw new Error('Client should have connected successfully but it did not.') + }, 3000) + + const client = new helper.Client(options) + client.connect() + .then(() => client.end()) + .then(() => closeServer(done)) + .catch(err => closeServer(() => done(err))) + .then(() => clearTimeout(timeoutId)) + }) +}) + +suite.test('expired connection timeout', done => { + serverWithConnectionTimeout(options.connectionTimeoutMillis * 2, closeServer => { + const timeoutId = setTimeout(() => { + throw new Error('Client should have emitted an error but it did not.') + }, 3000) + + const client = new helper.Client(options) + client.connect() + .then(() => client.end()) + .then(() => closeServer(() => done(new Error('Connection timeout should have expired but it did not.')))) + .catch(err => { + assert(err instanceof Error) + assert(/timeout expired\s*/.test(err.message)) + closeServer(done) + }) + .then(() => clearTimeout(timeoutId)) + }) +}) diff --git a/test/test-helper.js b/test/test-helper.js index 2f39be2aa..4c14b8578 100644 --- a/test/test-helper.js +++ b/test/test-helper.js @@ -134,7 +134,7 @@ var expect = function (callback, timeout) { assert.ok(executed, 'Expected execution of function to be fired within ' + timeout + ' milliseconds ' + - +' (hint: export TEST_TIMEOUT=' + + ' (hint: export TEST_TIMEOUT=' + ' to change timeout globally)' + callback.toString()) }, timeout) diff --git a/test/unit/client/set-keepalives.js b/test/unit/client/set-keepalives.js new file mode 100644 index 000000000..55ff04f39 --- /dev/null +++ b/test/unit/client/set-keepalives.js @@ -0,0 +1,32 @@ +'use strict' +const net = require('net') +const pg = require('../../../lib/index.js') +const helper = require('./test-helper') + +const suite = new helper.Suite() + +suite.test('setting keep alive', done => { + const server = net.createServer(c => { + c.destroy() + server.close() + }) + + server.listen(7777, () => { + const stream = new net.Socket() + stream.setKeepAlive = (enable, initialDelay) => { + assert(enable === true) + assert(initialDelay === 10000) + done() + } + + const client = new pg.Client({ + host: 'localhost', + port: 7777, + keepAlive: true, + keepAliveInitialDelayMillis: 10000, + stream + }) + + client.connect().catch(() => {}) + }) +}) From 697bdae507cd9007a255e99edf007e1c41dee600 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 10 May 2019 12:12:02 -0500 Subject: [PATCH 0469/1037] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ec130170..738afe7c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.11.0 +- Add support for [connection_timeout](https://github.com/brianc/node-postgres/pull/1847/files#diff-5391bde944956870128be1136e7bc176R63) and [keepalives_idle](https://github.com/brianc/node-postgres/pull/1847). + ### 7.10.0 - Add support for [per-query types](https://github.com/brianc/node-postgres/pull/1825). From 61cc3d26e2a1b399a6c945ef74123163c481da43 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 10 May 2019 12:12:16 -0500 Subject: [PATCH 0470/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a2650dde1..e787b048d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.10.0", + "version": "7.11.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 8ba1d2c5728bf41c663f05063e7b2cfc05421925 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Fri, 10 May 2019 13:23:49 -0400 Subject: [PATCH 0471/1037] Enable eslint:recommended and plugin/node/recommended (#1856) * Fix typo * Enable eslint:recommended and remove unused eslint plugins Enables eslint:recommended by disabling the options that would not pass. Also removes dependencies for included but unused eslint plugins. * Convert console.error(...) calls to use %s placeholders * Enable eslint no-console rule * Add and enable eslint-node-plugin * Correct typo * Enable eslint no-unused-vars --- .eslintrc | 16 ++++++++++++++-- lib/client.js | 6 +++++- lib/connection.js | 4 +++- lib/index.js | 2 ++ lib/native/client.js | 1 + lib/native/query.js | 4 +++- lib/query.js | 1 + lib/sasl.js | 1 + package.json | 4 ---- test/suite.js | 2 +- 10 files changed, 31 insertions(+), 10 deletions(-) diff --git a/.eslintrc b/.eslintrc index 6f96eccce..4a130fab6 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,6 +1,18 @@ { - "extends": "standard", + "plugins": [ + "node" + ], + "extends": [ + "eslint:recommended", + "plugin:node/recommended" + ], + "parserOptions": { + "ecmaVersion": 2017 + }, + "env": { + "node": true, + "es6": true + }, "rules": { - "no-new-func": "off" } } diff --git a/lib/client.js b/lib/client.js index 517f5cc14..147637ee7 100644 --- a/lib/client.js +++ b/lib/client.js @@ -292,11 +292,13 @@ Client.prototype._attachListeners = function (con) { }) // delegate portalSuspended to active query + // eslint-disable-next-line no-unused-vars con.on('portalSuspended', function (msg) { self.activeQuery.handlePortalSuspended(con) }) - // deletagate emptyQuery to active query + // delegate emptyQuery to active query + // eslint-disable-next-line no-unused-vars con.on('emptyQuery', function (msg) { self.activeQuery.handleEmptyQuery(con) }) @@ -309,12 +311,14 @@ Client.prototype._attachListeners = function (con) { // if a prepared statement has a name and properly parses // we track that its already been executed so we don't parse // it again on the same client + // eslint-disable-next-line no-unused-vars con.on('parseComplete', function (msg) { if (self.activeQuery.name) { con.parsedStatements[self.activeQuery.name] = self.activeQuery.text } }) + // eslint-disable-next-line no-unused-vars con.on('copyInResponse', function (msg) { self.activeQuery.handleCopyInResponse(self.connection) }) diff --git a/lib/connection.js b/lib/connection.js index 1ac2f668f..abb6ad6dd 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -237,9 +237,11 @@ Connection.prototype.parse = function (query, more) { // normalize missing query names to allow for null query.name = query.name || '' if (query.name.length > 63) { + /* eslint-disable no-console */ console.error('Warning! Postgres only supports 63 characters for query names.') - console.error('You supplied', query.name, '(', query.name.length, ')') + console.error('You supplied %s (%s)', query.name, query.name.length) console.error('This can cause conflicts and silent errors executing queries') + /* eslint-enable no-console */ } // normalize null type array query.types = query.types || [] diff --git a/lib/index.js b/lib/index.js index 00e3ceed4..8e000a378 100644 --- a/lib/index.js +++ b/lib/index.js @@ -49,7 +49,9 @@ if (typeof process.env.NODE_PG_FORCE_NATIVE !== 'undefined') { if (err.code !== 'MODULE_NOT_FOUND') { throw err } + /* eslint-disable no-console */ console.error(err.message) + /* eslint-enable no-console */ } module.exports.native = native return native diff --git a/lib/native/client.js b/lib/native/client.js index 5338f7f10..0084d0250 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -7,6 +7,7 @@ * README.md file in the root directory of this source tree. */ +// eslint-disable-next-line node/no-missing-require var Native = require('pg-native') var TypeOverrides = require('../type-overrides') var semver = require('semver') diff --git a/lib/native/query.js b/lib/native/query.js index db4eb8cca..74bfb0601 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -130,9 +130,11 @@ NativeQuery.prototype.submit = function (client) { // named query if (this.name) { if (this.name.length > 63) { + /* eslint-disable no-console */ console.error('Warning! Postgres only supports 63 characters for query names.') - console.error('You supplied', this.name, '(', this.name.length, ')') + console.error('You supplied %s (%s)', this.name, this.name.length) console.error('This can cause conflicts and silent errors executing queries') + /* eslint-enable no-console */ } var values = (this.values || []).map(utils.prepareValue) diff --git a/lib/query.js b/lib/query.js index 41ed77ea2..250e8950d 100644 --- a/lib/query.js +++ b/lib/query.js @@ -222,6 +222,7 @@ Query.prototype.handleCopyInResponse = function (connection) { connection.sendCopyFail('No source stream defined') } +// eslint-disable-next-line no-unused-vars Query.prototype.handleCopyData = function (msg, connection) { // noop } diff --git a/lib/sasl.js b/lib/sasl.js index 537ca350b..39c24bb33 100644 --- a/lib/sasl.js +++ b/lib/sasl.js @@ -1,3 +1,4 @@ +'use strict' const crypto = require('crypto') function startSession (mechanisms) { diff --git a/package.json b/package.json index e787b048d..c7b3ce039 100644 --- a/package.json +++ b/package.json @@ -32,11 +32,7 @@ "bluebird": "3.5.2", "co": "4.6.0", "eslint": "^4.19.1", - "eslint-config-standard": "^11.0.0", - "eslint-plugin-import": "^2.14.0", "eslint-plugin-node": "^6.0.1", - "eslint-plugin-promise": "^4.0.1", - "eslint-plugin-standard": "^3.1.0", "pg-copy-streams": "0.3.0" }, "minNativeVersion": "2.0.0", diff --git a/test/suite.js b/test/suite.js index 72a4fdcb0..eca96159e 100644 --- a/test/suite.js +++ b/test/suite.js @@ -76,7 +76,7 @@ class Suite { process.on('unhandledRejection', (e) => { setImmediate(() => { - console.error('Uhandled promise rejection') + console.error('Unhandled promise rejection') throw e }) }) From e9270e89af6c6e5b84b8c668bf206c8f9ab97a45 Mon Sep 17 00:00:00 2001 From: "Herman J. Radtke III" Date: Fri, 17 May 2019 07:38:25 -0700 Subject: [PATCH 0472/1037] Add support for TLS parameters in URI The connection string now supports the following parameters: - sslcert - sslkey - sslrootcert Fixes #25. --- index.js | 17 +++++++++++++++++ test/example.ca | 1 + test/example.cert | 1 + test/example.key | 1 + test/parse.js | 24 ++++++++++++++++++++++++ 5 files changed, 44 insertions(+) create mode 100644 test/example.ca create mode 100644 test/example.cert create mode 100644 test/example.key diff --git a/index.js b/index.js index 0042faec0..981bdcda3 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,7 @@ 'use strict'; var url = require('url'); +var fs = require('fs'); //Parse method copied from https://github.com/brianc/node-postgres //Copyright (c) 2010-2014 Brian Carlson (brian.m.carlson@gmail.com) @@ -48,6 +49,22 @@ function parse(str) { config.ssl = true; } + if (config.sslcert || config.sslkey || config.sslrootcert) { + config.ssl = {}; + } + + if (config.sslcert) { + config.ssl.cert = fs.readFileSync(config.sslcert).toString(); + } + + if (config.sslkey) { + config.ssl.key = fs.readFileSync(config.sslkey).toString(); + } + + if (config.sslrootcert) { + config.ssl.ca = fs.readFileSync(config.sslrootcert).toString(); + } + return config; } diff --git a/test/example.ca b/test/example.ca new file mode 100644 index 000000000..0a6dcf40e --- /dev/null +++ b/test/example.ca @@ -0,0 +1 @@ +example ca diff --git a/test/example.cert b/test/example.cert new file mode 100644 index 000000000..7693b3fed --- /dev/null +++ b/test/example.cert @@ -0,0 +1 @@ +example cert diff --git a/test/example.key b/test/example.key new file mode 100644 index 000000000..1aef9935f --- /dev/null +++ b/test/example.key @@ -0,0 +1 @@ +example key diff --git a/test/parse.js b/test/parse.js index 8ff3ee81d..6632cc712 100644 --- a/test/parse.js +++ b/test/parse.js @@ -147,6 +147,30 @@ describe('parse', function(){ subject.ssl.should.equal(true); }); + it('configuration parameter sslcert=/path/to/cert', function(){ + var connectionString = 'pg:///?sslcert=' + __dirname + '/example.cert'; + var subject = parse(connectionString); + subject.ssl.should.eql({ + cert: 'example cert\n' + }); + }); + + it('configuration parameter sslkey=/path/to/key', function(){ + var connectionString = 'pg:///?sslkey=' + __dirname + '/example.key'; + var subject = parse(connectionString); + subject.ssl.should.eql({ + key: 'example key\n' + }); + }); + + it('configuration parameter sslrootcert=/path/to/ca', function(){ + var connectionString = 'pg:///?sslrootcert=' + __dirname + '/example.ca'; + var subject = parse(connectionString); + subject.ssl.should.eql({ + ca: 'example ca\n' + }); + }); + it('allow other params like max, ...', function () { var subject = parse('pg://myhost/db?max=18&min=4'); subject.max.should.equal('18'); From 7b62226d573bdde749e4c94ed21d67c74d1f3bd2 Mon Sep 17 00:00:00 2001 From: "Herman J. Radtke III" Date: Thu, 23 May 2019 14:23:55 -0700 Subject: [PATCH 0473/1037] ssl=0 is now parses to false Fixes #20 --- index.js | 4 ++++ test/parse.js | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/index.js b/index.js index 667984018..3cabb372f 100644 --- a/index.js +++ b/index.js @@ -49,6 +49,10 @@ function parse(str) { config.ssl = true; } + if (config.ssl === '0') { + config.ssl = false; + } + if (config.sslcert || config.sslkey || config.sslrootcert) { config.ssl = {}; } diff --git a/test/parse.js b/test/parse.js index abf2c4f9e..4de28719e 100644 --- a/test/parse.js +++ b/test/parse.js @@ -150,6 +150,12 @@ describe('parse', function(){ subject.ssl.should.equal(true); }); + it('configuration parameter ssl=0', function(){ + var connectionString = 'pg:///?ssl=0'; + var subject = parse(connectionString); + subject.ssl.should.equal(false); + }); + it('set ssl', function () { var subject = parse('pg://myhost/db?ssl=1'); subject.ssl.should.equal(true); From 726f6202fa7eb89096bf6cb8d32526ebacf4be49 Mon Sep 17 00:00:00 2001 From: benny-medflyt Date: Mon, 27 May 2019 08:30:21 -0400 Subject: [PATCH 0474/1037] Update index.d.ts --- index.d.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.d.ts b/index.d.ts index 2a6574600..1d2f1606e 100644 --- a/index.d.ts +++ b/index.d.ts @@ -4,10 +4,10 @@ export interface ConnectionOptions { host: string | null; password?: string; user?: string; - port: string | null; + port?: string | null; database: string | null | undefined; - client_encoding?: string | undefined; - ssl?: boolean; + client_encoding?: string; + ssl?: boolean | string; application_name?: string; fallback_application_name?: string; From 2c7be86104e6f4e3ad5f2992b80a54e11a8edff3 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Mon, 17 Jun 2019 22:51:16 +0100 Subject: [PATCH 0475/1037] minor text improvement in defaults (#1893) --- lib/defaults.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/defaults.js b/lib/defaults.js index c520eb56b..f883e982f 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -50,14 +50,16 @@ module.exports = { ssl: false, application_name: undefined, + fallback_application_name: undefined, parseInputDatesAsUTC: false, - // max milliseconds any query using this connection will execute for before timing out in error. false=unlimited + // max milliseconds any query using this connection will execute for before timing out in error. + // false=unlimited statement_timeout: false, - // max miliseconds to wait for query to complete (client side) + // max milliseconds to wait for query to complete (client side) query_timeout: false, connect_timeout: 0, From 06c46ac12b2a9540483450305f841938a759ba4d Mon Sep 17 00:00:00 2001 From: Andrew Bowerman Date: Tue, 18 Jun 2019 20:12:03 -0700 Subject: [PATCH 0476/1037] 2.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b625a16d7..c39da5f2c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "2.0.0", + "version": "2.1.0", "description": "Functions for dealing with a PostgresSQL connection string", "main": "./index.js", "types": "./index.d.ts", From c9ee9cd19970c93dda8ce66b2dd7fd1efa6b056f Mon Sep 17 00:00:00 2001 From: Andrew Bowerman Date: Tue, 18 Jun 2019 20:25:32 -0700 Subject: [PATCH 0477/1037] Update coveralls badge Closes #15 --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 2228b80e1..cb4b1accf 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,7 @@ pg-connection-string [![NPM](https://nodei.co/npm/pg-connection-string.png?compact=true)](https://nodei.co/npm/pg-connection-string/) [![Build Status](https://travis-ci.org/iceddev/pg-connection-string.svg?branch=master)](https://travis-ci.org/iceddev/pg-connection-string) -[![Coverage Status](https://coveralls.io/repos/iceddev/pg-connection-string/badge.svg?branch=master)](https://coveralls.io/r/iceddev/pg-connection-string?branch=master) - +[![Coverage Status](https://coveralls.io/repos/github/iceddev/pg-connection-string/badge.svg?branch=master)](https://coveralls.io/github/iceddev/pg-connection-string?branch=master) Functions for dealing with a PostgresSQL connection string `parse` method taken from [node-postgres](https://github.com/brianc/node-postgres.git) From c75c3929654401fbf8654f6df3613ef2748c1428 Mon Sep 17 00:00:00 2001 From: Andrew Bowerman Date: Tue, 18 Jun 2019 20:41:10 -0700 Subject: [PATCH 0478/1037] fix readme newline typo --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index cb4b1accf..4943d885b 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ pg-connection-string [![Build Status](https://travis-ci.org/iceddev/pg-connection-string.svg?branch=master)](https://travis-ci.org/iceddev/pg-connection-string) [![Coverage Status](https://coveralls.io/repos/github/iceddev/pg-connection-string/badge.svg?branch=master)](https://coveralls.io/github/iceddev/pg-connection-string?branch=master) + Functions for dealing with a PostgresSQL connection string `parse` method taken from [node-postgres](https://github.com/brianc/node-postgres.git) From e4c1002e2e9413636c32929236e96f893010a317 Mon Sep 17 00:00:00 2001 From: Andrew Bowerman Date: Tue, 18 Jun 2019 20:49:39 -0700 Subject: [PATCH 0479/1037] actually include coveralls --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index c39da5f2c..415638f07 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "dependencies": {}, "devDependencies": { "chai": "^4.1.1", + "coveralls": "^3.0.4", "istanbul": "^0.4.5", "mocha": "^3.5.0" }, From b0f79582992d776ecb47f2aa80e38f819c425d66 Mon Sep 17 00:00:00 2001 From: Juneidy Date: Thu, 27 Jun 2019 11:22:04 +0800 Subject: [PATCH 0480/1037] Fix hanging listener when error occured --- index.js | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/index.js b/index.js index 1984e4685..d333e2598 100644 --- a/index.js +++ b/index.js @@ -19,10 +19,23 @@ function Cursor (text, values, config) { this._cb = null this._rows = null this._portal = null + this._ifNoData = this._ifNoData.bind(this) + this._rowDescription = this._rowDescription.bind(this) } util.inherits(Cursor, EventEmitter) +Cursor.prototype._ifNoData = function () { + this.state = 'idle' + this._shiftQueue() +} + +Cursor.prototype._rowDescription = function () { + if (this.connection) { + this.connection.removeListener('noData', this._ifNoData) + } +} + Cursor.prototype.submit = function (connection) { this.connection = connection this._portal = 'C_' + (nextUniqueID++) @@ -45,19 +58,12 @@ Cursor.prototype.submit = function (connection) { con.flush() - const ifNoData = () => { - this.state = 'idle' - this._shiftQueue() - } - if (this._conf.types) { this._result._getTypeParser = this._conf.types.getTypeParser } - con.once('noData', ifNoData) - con.once('rowDescription', () => { - con.removeListener('noData', ifNoData) - }) + con.once('noData', this._ifNoData) + con.once('rowDescription', this._rowDescription) } Cursor.prototype._shiftQueue = function () { @@ -114,6 +120,8 @@ Cursor.prototype.handleEmptyQuery = function () { } Cursor.prototype.handleError = function (msg) { + this.connection.removeListener('noData', this._ifNoData) + this.connection.removeListener('rowDescription', this._rowDescription) this.state = 'error' this._error = msg // satisfy any waiting callback From d8a0e1e95083396ffad24f620745ab13154da5e6 Mon Sep 17 00:00:00 2001 From: darkgl0w <31093081+darkgl0w@users.noreply.github.com> Date: Tue, 16 Jul 2019 21:14:41 +0200 Subject: [PATCH 0481/1037] Update CI to allow tests to pass on Node.js >= 10.16.0 (#1912) * Add CI build environment scripts * Update Travis configuration * Don't publish CI scripts to npm * Add Node.js 12 to CI matrix --- .npmignore | 1 + .travis.yml | 14 ++++++++++++- ci_scripts/build.sh | 9 +++++++++ ci_scripts/install_libpq.sh | 38 +++++++++++++++++++++++++++++++++++ ci_scripts/install_openssl.sh | 35 ++++++++++++++++++++++++++++++++ 5 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 ci_scripts/build.sh create mode 100644 ci_scripts/install_libpq.sh create mode 100644 ci_scripts/install_openssl.sh diff --git a/.npmignore b/.npmignore index 50e3c1bbe..6223e474b 100644 --- a/.npmignore +++ b/.npmignore @@ -7,3 +7,4 @@ script/ *.swp test/ .travis.yml +ci_scripts/ diff --git a/.travis.yml b/.travis.yml index 34d78369f..ee95ab265 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,17 @@ language: node_js -sudo: false +sudo: true dist: trusty + before_script: - node script/create-test-tables.js pg://postgres@127.0.0.1:5432/postgres + +before_install: + - if [ $TRAVIS_OS_NAME == "linux" ]; then + if [[ $(node -v) =~ v[1-9][0-9] ]]; then + source ./ci_scripts/build.sh; + fi + fi + env: - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres @@ -17,6 +26,9 @@ matrix: - node_js: "10" addons: postgresql: "9.6" + - node_js: "12" + addons: + postgresql: "9.6" - node_js: "lts/carbon" addons: postgresql: "9.1" diff --git a/ci_scripts/build.sh b/ci_scripts/build.sh new file mode 100644 index 000000000..707bf4d55 --- /dev/null +++ b/ci_scripts/build.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +BUILD_DIR="$(pwd)" +source ./ci_scripts/install_openssl.sh 1.1.1b +sudo updatedb +source ./ci_scripts/install_libpq.sh +sudo updatedb +sudo ldconfig +cd $BUILD_DIR diff --git a/ci_scripts/install_libpq.sh b/ci_scripts/install_libpq.sh new file mode 100644 index 000000000..936c7d645 --- /dev/null +++ b/ci_scripts/install_libpq.sh @@ -0,0 +1,38 @@ +#!/bin/bash + +set -e + +OPENSSL_DIR="$(pwd)/openssl-1.1.1b" +POSTGRES_VERSION="11.3" +POSTGRES_DIR="$(pwd)/postgres-${POSTGRES_VERSION}" +TMP_DIR="/tmp/postgres" +JOBS="-j$(nproc || echo 1)" + +if [ -d "${TMP_DIR}" ]; then + rm -rf "${TMP_DIR}" +fi + +mkdir -p "${TMP_DIR}" + +curl https://ftp.postgresql.org/pub/source/v${POSTGRES_VERSION}/postgresql-${POSTGRES_VERSION}.tar.gz | \ + tar -C "${TMP_DIR}" -xzf - + +cd "${TMP_DIR}/postgresql-${POSTGRES_VERSION}" + +if [ -d "${POSTGRES_DIR}" ]; then + rm -rf "${POSTGRES_DIR}" +fi +mkdir -p $POSTGRES_DIR + +./configure --prefix=$POSTGRES_DIR --with-openssl --with-includes=${OPENSSL_DIR}/include --with-libraries=${OPENSSL_DIR}/lib --without-readline + +cd src/interfaces/libpq; make; make install; cd - +cd src/bin/pg_config; make install; cd - +cd src/backend; make generated-headers; cd - +cd src/include; make install; cd - + +export PATH="${POSTGRES_DIR}/bin:${PATH}" +export CFLAGS="-I${POSTGRES_DIR}/include" +export LDFLAGS="-L${POSTGRES_DIR}/lib" +export LD_LIBRARY_PATH="${POSTGRES_DIR}/lib:$LD_LIBRARY_PATH" +export PKG_CONFIG_PATH="${POSTGRES_DIR}/lib/pkgconfig:$PKG_CONFIG_PATH" diff --git a/ci_scripts/install_openssl.sh b/ci_scripts/install_openssl.sh new file mode 100644 index 000000000..24c0d3a5a --- /dev/null +++ b/ci_scripts/install_openssl.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +if [ ${#} -lt 1 ]; then + echo "OpenSSL version required." 1>&2 + exit 1 +fi + +OPENSSL_VERSION="${1}" +OPENSSL_DIR="$(pwd)/openssl-${OPENSSL_VERSION}" +TMP_DIR="/tmp/openssl" +JOBS="-j$(nproc)" + +if [ -d "${TMP_DIR}" ]; then + rm -rf "${TMP_DIR}" +fi +mkdir -p "${TMP_DIR}" +curl -s https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz | \ + tar -C "${TMP_DIR}" -xzf - +pushd "${TMP_DIR}/openssl-${OPENSSL_VERSION}" +if [ -d "${OPENSSL_DIR}" ]; then + rm -rf "${OPENSSL_DIR}" +fi +./Configure \ + --prefix=${OPENSSL_DIR} \ + enable-crypto-mdebug enable-crypto-mdebug-backtrace \ + linux-x86_64 +make -s $JOBS +make install_sw +popd + +export PATH="${OPENSSL_DIR}/bin:${PATH}" +export CFLAGS="-I${OPENSSL_DIR}/include" +export LDFLAGS="-L${OPENSSL_DIR}/lib" +export LD_LIBRARY_PATH="${OPENSSL_DIR}/lib:$LD_LIBRARY_PATH" +export PKG_CONFIG_PATH="${OPENSSL_DIR}/lib/pkgconfig:$PKG_CONFIG_PATH" From 0acaf9d8ff3e96fd2a71c786c8ee883c2b2006d2 Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 16 Jul 2019 18:41:54 -0500 Subject: [PATCH 0482/1037] Fix compare (#1923) * Fix deepEqual compare In node 12 assert.deepEqual against a buffer & array no longer passes if the values are the same. This makes sense. Updated the test to not use deepEqual in this case. --- lib/native/client.js | 2 +- test/unit/utils-tests.js | 35 ++++++++++++++++++----------------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/lib/native/client.js b/lib/native/client.js index 0084d0250..6859bc2cc 100644 --- a/lib/native/client.js +++ b/lib/native/client.js @@ -7,7 +7,7 @@ * README.md file in the root directory of this source tree. */ -// eslint-disable-next-line node/no-missing-require +// eslint-disable-next-line var Native = require('pg-native') var TypeOverrides = require('../type-overrides') var semver = require('semver') diff --git a/test/unit/utils-tests.js b/test/unit/utils-tests.js index 0bca25af7..4308f7a18 100644 --- a/test/unit/utils-tests.js +++ b/test/unit/utils-tests.js @@ -29,22 +29,22 @@ test('EventEmitter.once', function (t) { test('normalizing query configs', function () { var config - var callback = function () {} + var callback = function () { } - config = utils.normalizeQueryConfig({text: 'TEXT'}) - assert.same(config, {text: 'TEXT'}) + config = utils.normalizeQueryConfig({ text: 'TEXT' }) + assert.same(config, { text: 'TEXT' }) - config = utils.normalizeQueryConfig({text: 'TEXT'}, [10]) - assert.deepEqual(config, {text: 'TEXT', values: [10]}) + config = utils.normalizeQueryConfig({ text: 'TEXT' }, [10]) + assert.deepEqual(config, { text: 'TEXT', values: [10] }) - config = utils.normalizeQueryConfig({text: 'TEXT', values: [10]}) - assert.deepEqual(config, {text: 'TEXT', values: [10]}) + config = utils.normalizeQueryConfig({ text: 'TEXT', values: [10] }) + assert.deepEqual(config, { text: 'TEXT', values: [10] }) config = utils.normalizeQueryConfig('TEXT', [10], callback) - assert.deepEqual(config, {text: 'TEXT', values: [10], callback: callback}) + assert.deepEqual(config, { text: 'TEXT', values: [10], callback: callback }) - config = utils.normalizeQueryConfig({text: 'TEXT', values: [10]}, callback) - assert.deepEqual(config, {text: 'TEXT', values: [10], callback: callback}) + config = utils.normalizeQueryConfig({ text: 'TEXT', values: [10] }, callback) + assert.deepEqual(config, { text: 'TEXT', values: [10], callback: callback }) }) test('prepareValues: buffer prepared properly', function () { @@ -57,7 +57,8 @@ test('prepareValues: Uint8Array prepared properly', function () { var buf = new Uint8Array([1, 2, 3]).subarray(1, 2) var out = utils.prepareValue(buf) assert.ok(Buffer.isBuffer(out)) - assert.deepEqual(out, [2]) + assert.equal(out.length, 1) + assert.deepEqual(out[0], 2) }) test('prepareValues: date prepared properly', function () { @@ -167,12 +168,12 @@ test('prepareValue: objects with simple toPostgres prepared properly', function assert.strictEqual(out, 'zomgcustom!') }) -test('prepareValue: buffer array prepared properly', function() { - var buffer1 = Buffer.from('dead', 'hex') - var buffer2 = Buffer.from('beef', 'hex') - var out = utils.prepareValue([buffer1, buffer2]) - assert.strictEqual(out, '{\\\\xdead,\\\\xbeef}') - }) +test('prepareValue: buffer array prepared properly', function () { + var buffer1 = Buffer.from('dead', 'hex') + var buffer2 = Buffer.from('beef', 'hex') + var out = utils.prepareValue([buffer1, buffer2]) + assert.strictEqual(out, '{\\\\xdead,\\\\xbeef}') +}) test('prepareValue: objects with complex toPostgres prepared properly', function () { var buf = Buffer.from('zomgcustom!') From f9fc232db36a09633425d16aeb46099ac6a1a3c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20W=C3=BCrbach?= Date: Thu, 25 Jul 2019 19:38:21 +0200 Subject: [PATCH 0483/1037] Remove idleListener when client is in-use (#123) * Prevent double release with callback When using the callback instead of client.release, double releasing a client was possible causing clients to be re-added multiple times. * Remove idleListener when client is in-use When a client is in-use, the error handling should be done by the consumer and not by the pool itself as this otherwise might cause errors to be handled multiple times. * Handle verify failures --- index.js | 120 ++++++++++++++++++++++++++--------------- test/error-handling.js | 65 ++++++++++++++++++++-- 2 files changed, 138 insertions(+), 47 deletions(-) diff --git a/index.js b/index.js index cfe377c35..e93cc96c9 100644 --- a/index.js +++ b/index.js @@ -12,8 +12,9 @@ const removeWhere = (list, predicate) => { } class IdleItem { - constructor (client, timeoutId) { + constructor (client, idleListener, timeoutId) { this.client = client + this.idleListener = idleListener this.timeoutId = timeoutId } } @@ -28,27 +29,6 @@ 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 } @@ -68,6 +48,7 @@ function promisify (Promise, callback) { function makeIdleListener (pool, client) { return function idleListener (err) { err.client = client + client.removeListener('error', idleListener) client.on('error', () => { pool.log('additional client error after disconnection due to error', err) @@ -132,17 +113,17 @@ class Pool extends EventEmitter { if (!this._idle.length && this._isFull()) { return } - const waiter = this._pendingQueue.shift() + const pendingItem = 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.callback(undefined, client, client.release) + const idleListener = idleItem.idleListener + + return this._acquireClient(client, pendingItem, idleListener, false) } if (!this._isFull()) { - return this.newClient(waiter) + return this.newClient(pendingItem) } throw new Error('unexpected condition') } @@ -249,26 +230,79 @@ class Pool extends EventEmitter { } } else { this.log('new client connected') - client.release = release.bind(this, client) - this.emit('connect', client) - this.emit('acquire', client) - if (!pendingItem.timedOut) { - if (this.options.verify) { - this.options.verify(client, pendingItem.callback) - } else { - pendingItem.callback(undefined, client, client.release) - } - } else { - if (this.options.verify) { - this.options.verify(client, client.release) - } else { - client.release() - } - } + + return this._acquireClient(client, pendingItem, idleListener, true) } }) } + // acquire a client for a pending work item + _acquireClient (client, pendingItem, idleListener, isNew) { + if (isNew) { + this.emit('connect', client) + } + + this.emit('acquire', client) + + let released = false + + client.release = (err) => { + if (released) { + throwOnRelease() + } + + released = true + this._release(client, idleListener, err) + } + + client.removeListener('error', idleListener) + + if (!pendingItem.timedOut) { + if (isNew && this.options.verify) { + this.options.verify(client, (err) => { + if (err) { + client.release(err) + return pendingItem.callback(err, undefined, NOOP) + } + + pendingItem.callback(undefined, client, client.release) + }) + } else { + pendingItem.callback(undefined, client, client.release) + } + } else { + if (isNew && this.options.verify) { + this.options.verify(client, client.release) + } else { + client.release() + } + } + } + + // release a client back to the poll, include an error + // to remove it from the pool + _release (client, idleListener, err) { + client.on('error', idleListener) + + 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, idleListener, tid)) + this._pulseQueue() + } + query (text, values, cb) { // guard clause against passing a function as the first parameter if (typeof text === 'function') { diff --git a/test/error-handling.js b/test/error-handling.js index e899c350e..1e4166838 100644 --- a/test/error-handling.js +++ b/test/error-handling.js @@ -43,6 +43,20 @@ describe('pool error handling', function () { expect(() => client.release()).to.throwError() return yield pool.end() })) + + it('should throw each time with callbacks', function (done) { + const pool = new Pool() + + pool.connect(function (err, client, clientDone) { + expect(err).not.to.be.an(Error) + clientDone() + + expect(() => clientDone()).to.throwError() + expect(() => clientDone()).to.throwError() + + pool.end(done) + }) + }) }) describe('calling connect after end', () => { @@ -101,13 +115,56 @@ describe('pool error handling', function () { client.release() yield new Promise((resolve, reject) => { process.nextTick(() => { + let poolError + pool.once('error', (err) => { + poolError = err + }) + + let clientError + client.once('error', (err) => { + clientError = err + }) + + client.emit('error', new Error('expected')) + + expect(clientError.message).to.equal('expected') + expect(poolError.message).to.equal('expected') + expect(pool.idleCount).to.equal(0) + expect(pool.totalCount).to.equal(0) + pool.end().then(resolve, reject) + }) + }) + })) + }) + + describe('error from in-use client', () => { + it('keeps the client in the 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) + + yield new Promise((resolve, reject) => { + process.nextTick(() => { + let poolError 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) + poolError = err }) + + let clientError + client.once('error', (err) => { + clientError = err + }) + client.emit('error', new Error('expected')) + + expect(clientError.message).to.equal('expected') + expect(poolError).not.to.be.ok() + expect(pool.idleCount).to.equal(0) + expect(pool.totalCount).to.equal(1) + client.release() + pool.end().then(resolve, reject) }) }) })) From e59a7667ffd4ae20c75a057ad4beadfbe830e6ce Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 25 Jul 2019 12:39:44 -0500 Subject: [PATCH 0484/1037] Bump version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index f977e2645..4099fbfd7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "2.0.6", + "version": "2.0.7", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index c4583b3ba..0609ddbdb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "2.0.6", + "version": "2.0.7", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From 70d5c0995852fba68391a5d4a19e234043d86198 Mon Sep 17 00:00:00 2001 From: Jonathan Baudanza Date: Thu, 25 Jul 2019 10:41:28 -0700 Subject: [PATCH 0485/1037] Remove reference to "min" config option (#126) Because it no longer exists. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index a02fa32cc..b77b65d86 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,6 @@ var pool2 = new Pool({ 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 }) From 0894a3ce07cbc3530b61075d8a39e96801d97d6f Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Thu, 25 Jul 2019 13:48:48 -0400 Subject: [PATCH 0486/1037] feat: Add dynamic retrieval for client password (#1926) * feat: Add dynamic retrieval for client password Adds option to specify a function for a client password. When the client is connected, if the value of password is a function then it is invoked to get the password to use for that connection. The function must return either a string or a Promise that resolves to a string. If the function throws or rejects with an error then it will be bubbled up to the client. * test: Add testAsync() helper to Suite Add testAsync() helper function to Suite to simplify running tests that return a Promise. The test action is executed and if a syncronous error is thrown then it is immediately considered failed. If the Promise resolves successfully then the test is considered successful. If the Promise rejects with an Error then the test is considered failed. * test: Add tests for dynamic password * test: Simplify testAsync error handling * fix: Clean up dynamic password error handling and misc style * test: Remove extra semicolons * test: Change testAsync(...) calls to use arrow functions * fix: Wrap self.password() invocation in an arrow function * test: Add a comment to testAsync(...) --- lib/client.js | 19 ++- .../connection/dynamic-password.js | 113 ++++++++++++++++++ test/suite.js | 14 +++ 3 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 test/integration/connection/dynamic-password.js diff --git a/lib/client.js b/lib/client.js index 147637ee7..cca5e66e8 100644 --- a/lib/client.js +++ b/lib/client.js @@ -114,7 +114,24 @@ Client.prototype._connect = function (callback) { function checkPgPass (cb) { return function (msg) { - if (self.password !== null) { + if (typeof self.password === 'function') { + self._Promise.resolve() + .then(() => self.password()) + .then(pass => { + if (pass !== undefined) { + if (typeof pass !== 'string') { + con.emit('error', new TypeError('Password must be a string')) + return + } + self.connectionParameters.password = self.password = pass + } else { + self.connectionParameters.password = self.password = null + } + cb(msg) + }).catch(err => { + con.emit('error', err) + }) + } else if (self.password !== null) { cb(msg) } else { pgPass(self.connectionParameters, function (pass) { diff --git a/test/integration/connection/dynamic-password.js b/test/integration/connection/dynamic-password.js new file mode 100644 index 000000000..ebda433c1 --- /dev/null +++ b/test/integration/connection/dynamic-password.js @@ -0,0 +1,113 @@ +'use strict' +const assert = require('assert') +const helper = require('./../test-helper') +const suite = new helper.Suite() +const pg = require('../../../lib/index') +const Client = pg.Client; + +const password = process.env.PGPASSWORD || null +const sleep = millis => new Promise(resolve => setTimeout(resolve, millis)) + +suite.testAsync('Get password from a sync function', () => { + let wasCalled = false + function getPassword() { + wasCalled = true + return password + } + const client = new Client({ + password: getPassword, + }) + return client.connect() + .then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + return client.end() + }) +}) + +suite.testAsync('Throw error from a sync function', () => { + let wasCalled = false + const myError = new Error('Oops!') + function getPassword() { + wasCalled = true + throw myError + } + const client = new Client({ + password: getPassword, + }) + let wasThrown = false + return client.connect() + .catch(err => { + assert.equal(err, myError, 'Our sync error should have been thrown') + wasThrown = true + }) + .then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + assert.ok(wasThrown, 'Our error should have been thrown') + return client.end() + }) +}) + +suite.testAsync('Get password from a function asynchronously', () => { + let wasCalled = false + function getPassword() { + wasCalled = true + return sleep(100).then(() => password) + } + const client = new Client({ + password: getPassword, + }) + return client.connect() + .then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + return client.end() + }) +}) + +suite.testAsync('Throw error from an async function', () => { + let wasCalled = false + const myError = new Error('Oops!') + function getPassword() { + wasCalled = true + return sleep(100).then(() => { + throw myError + }) + } + const client = new Client({ + password: getPassword, + }) + let wasThrown = false + return client.connect() + .catch(err => { + assert.equal(err, myError, 'Our async error should have been thrown') + wasThrown = true + }) + .then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + assert.ok(wasThrown, 'Our error should have been thrown') + return client.end() + }) +}) + +suite.testAsync('Password function must return a string', () => { + let wasCalled = false + function getPassword() { + wasCalled = true + // Return a password that is not a string + return 12345 + } + const client = new Client({ + password: getPassword, + }) + let wasThrown = false + return client.connect() + .catch(err => { + assert.ok(err instanceof TypeError, 'A TypeError should have been thrown') + assert.equal(err.message, 'Password must be a string') + wasThrown = true + }) + .then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + assert.ok(wasThrown, 'Our error should have been thrown') + return client.end() + }) +}) diff --git a/test/suite.js b/test/suite.js index eca96159e..4161ddc0a 100644 --- a/test/suite.js +++ b/test/suite.js @@ -72,6 +72,20 @@ class Suite { const test = new Test(name, cb) this._queue.push(test) } + + /** + * Run an async test that can return a Promise. If the Promise resolves + * successfully then the test will pass. If the Promise rejects with an + * error then the test will be considered failed. + */ + testAsync (name, action) { + const test = new Test(name, cb => { + Promise.resolve() + .then(action) + .then(() => cb(null), cb) + }) + this._queue.push(test) + } } process.on('unhandledRejection', (e) => { From 3ead90034930536ebeb11a48dada75323e9eb2fe Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Thu, 25 Jul 2019 14:00:14 -0400 Subject: [PATCH 0487/1037] Fix eslint and add back standard (#1928) * lint: Enable standard rules again * lint: Replace hasOwnProperty(...) call * lint: Remove trailing spaces * lint: Remove spaces within array brackets * lint: Disable quote-props to silence linter * lint: Skip linting on older node versions --- .eslintrc | 1 + Makefile | 4 +++- lib/connection-parameters.js | 4 ++-- lib/connection.js | 2 +- lib/defaults.js | 2 +- lib/native/query.js | 1 + package.json | 8 ++++++-- 7 files changed, 15 insertions(+), 7 deletions(-) diff --git a/.eslintrc b/.eslintrc index 4a130fab6..43aee6027 100644 --- a/.eslintrc +++ b/.eslintrc @@ -3,6 +3,7 @@ "node" ], "extends": [ + "standard", "eslint:recommended", "plugin:node/recommended" ], diff --git a/Makefile b/Makefile index a5b0bc1da..52d0545d3 100644 --- a/Makefile +++ b/Makefile @@ -62,4 +62,6 @@ test-pool: lint: @echo "***Starting lint***" - node_modules/.bin/eslint lib + node -e "process.exit(Number(process.versions.node.split('.')[0]) < 8 ? 0 : 1)" \ + && echo "***Skipping lint (node version too old)***" \ + || node_modules/.bin/eslint lib diff --git a/lib/connection-parameters.js b/lib/connection-parameters.js index f45dc50a4..00ea76111 100644 --- a/lib/connection-parameters.js +++ b/lib/connection-parameters.js @@ -15,11 +15,11 @@ var parse = require('pg-connection-string').parse // parses a connection string var val = function (key, config, envVar) { if (envVar === undefined) { - envVar = process.env[ 'PG' + key.toUpperCase() ] + envVar = process.env['PG' + key.toUpperCase()] } else if (envVar === false) { // do nothing ... use false } else { - envVar = process.env[ envVar ] + envVar = process.env[envVar] } return config[key] || diff --git a/lib/connection.js b/lib/connection.js index abb6ad6dd..48d65d25f 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -604,7 +604,7 @@ Connection.prototype.parseE = function (buffer, length) { msg = new Error(fields.M) for (item in input) { // copy input properties to the error - if (input.hasOwnProperty(item)) { + if (Object.prototype.hasOwnProperty.call(input, item)) { msg[item] = input[item] } } diff --git a/lib/defaults.js b/lib/defaults.js index f883e982f..bd1bf6de6 100644 --- a/lib/defaults.js +++ b/lib/defaults.js @@ -50,7 +50,7 @@ module.exports = { ssl: false, application_name: undefined, - + fallback_application_name: undefined, parseInputDatesAsUTC: false, diff --git a/lib/native/query.js b/lib/native/query.js index 74bfb0601..0c83e27e3 100644 --- a/lib/native/query.js +++ b/lib/native/query.js @@ -35,6 +35,7 @@ var NativeQuery = module.exports = function (config, values, callback) { util.inherits(NativeQuery, EventEmitter) var errorFieldMap = { + /* eslint-disable quote-props */ 'sqlState': 'code', 'statementPosition': 'position', 'messagePrimary': 'message', diff --git a/package.json b/package.json index c7b3ce039..20fc16122 100644 --- a/package.json +++ b/package.json @@ -31,8 +31,12 @@ "async": "0.9.0", "bluebird": "3.5.2", "co": "4.6.0", - "eslint": "^4.19.1", - "eslint-plugin-node": "^6.0.1", + "eslint": "^6.0.1", + "eslint-config-standard": "^13.0.1", + "eslint-plugin-import": "^2.18.1", + "eslint-plugin-node": "^9.1.0", + "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-standard": "^4.0.0", "pg-copy-streams": "0.3.0" }, "minNativeVersion": "2.0.0", From 94ad322eb9b949ebe097b5cd57c07217930c43a5 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 25 Jul 2019 13:06:23 -0500 Subject: [PATCH 0488/1037] Update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 738afe7c9..7792612f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,16 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.12.0 + +- Add support for [async password lookup](https://github.com/brianc/node-postgres/pull/1926). + ### 7.11.0 + - Add support for [connection_timeout](https://github.com/brianc/node-postgres/pull/1847/files#diff-5391bde944956870128be1136e7bc176R63) and [keepalives_idle](https://github.com/brianc/node-postgres/pull/1847). ### 7.10.0 + - Add support for [per-query types](https://github.com/brianc/node-postgres/pull/1825). ### 7.9.0 From d44376ad060f11e00e0678aedcd87d185fb9b91c Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 25 Jul 2019 13:06:51 -0500 Subject: [PATCH 0489/1037] Update sponsors file --- SPONSORS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SPONSORS.md b/SPONSORS.md index 1bbda390b..29aae9e02 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -1,10 +1,13 @@ node-postgres is made possible by the helpful contributors from the community well as the following generous supporters on [Patreon](https://www.patreon.com/node_postgres). # Leaders + - [MadKudu](https://www.madkudu.com) - [@madkudu](https://twitter.com/madkudu) - [Third Iron](https://thirdiron.com/) +- [Timescale](https://timescale.com) # Supporters + - John Fawcett - Lalit Kapoor [@lalitkapoor](https://twitter.com/lalitkapoor) - Paul Frazee [@pfrazee](https://twitter.com/pfrazee) From e4578d2c7bca60cfb02ec004daa22c8ff810140e Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 25 Jul 2019 13:07:00 -0500 Subject: [PATCH 0490/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 20fc16122..b96580f03 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.11.0", + "version": "7.12.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 05d20a6a6d5924572069a4ea0b75a835459cbdf0 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Fri, 9 Aug 2019 22:00:47 +0100 Subject: [PATCH 0491/1037] Update package.json (#1937) Fixes #1936 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b96580f03..e57f58d17 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "packet-reader": "1.0.0", "pg-connection-string": "0.1.3", "pg-pool": "^2.0.4", - "pg-types": "~2.0.0", + "pg-types": "^2.1.0", "pgpass": "1.x", "semver": "4.3.2" }, From 60d8df659c5481723abada2344ac14d77377338c Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 9 Aug 2019 16:02:25 -0500 Subject: [PATCH 0492/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e57f58d17..9eaf4c256 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.12.0", + "version": "7.12.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 2d2a87392ceaf73ba0d2ed13ed9f6857e1d72ddd Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Wed, 4 Sep 2019 01:45:45 -0400 Subject: [PATCH 0493/1037] Minor cleanup - inline throwOnRelease() (#129) The throwOnRelease() function does not appear to be exposed anywhere, and it does not appear to make any sense to have it as a standalone func, as it ovecomplicates things and makes function call as non-returning. Inlined it. --- index.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/index.js b/index.js index e93cc96c9..e517f76f3 100644 --- a/index.js +++ b/index.js @@ -25,10 +25,6 @@ class PendingItem { } } -function throwOnRelease () { - throw new Error('Release called on client which has already been released to the pool.') -} - function promisify (Promise, callback) { if (callback) { return { callback: callback, result: undefined } @@ -248,7 +244,7 @@ class Pool extends EventEmitter { client.release = (err) => { if (released) { - throwOnRelease() + throw new Error('Release called on client which has already been released to the pool.') } released = true From fde5ec586e49258dfc4a2fcd861fcdecb4794fc3 Mon Sep 17 00:00:00 2001 From: Ravi van Rooijen Date: Tue, 27 Aug 2019 15:57:19 +0200 Subject: [PATCH 0494/1037] Use arrow character in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 60cef5306..f1368773d 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ $ npm install pg * Pure JavaScript client and native libpq bindings share _the same API_ * Connection pooling -* Extensible JS<->PostgreSQL data-type coercion +* Extensible JS ↔ PostgreSQL data-type coercion * Supported PostgreSQL features * Parameterized queries * Named statements with query plan caching From 414fac6a054b971ef0273d58f0673bf204dea61a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 25 Oct 2019 12:14:27 -0500 Subject: [PATCH 0495/1037] Apply prettier to code, change lint rules --- .eslintrc | 12 +- .travis.yml | 4 +- Makefile | 5 +- index.js | 71 +- package-lock.json | 1807 -------------------------------------- package.json | 20 +- test/close.js | 16 +- test/error-handling.js | 30 +- test/index.js | 80 +- test/no-data-handling.js | 16 +- test/pool.js | 20 +- test/query-config.js | 6 +- yarn.lock | 1549 ++++++++++++++++++++++++++++++++ 13 files changed, 1699 insertions(+), 1937 deletions(-) delete mode 100644 package-lock.json create mode 100644 yarn.lock diff --git a/.eslintrc b/.eslintrc index 95f4d0c65..148d48bd9 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,9 +1,13 @@ { - "extends": "standard", - "env": { - "mocha": true - }, + "extends": "eslint:recommended", + "plugins": ["prettier"], "rules": { + "prettier/prettier": "error", "no-new-func": "off" + }, + "env": { + "es6": true, + "node": true, + "mocha": true } } diff --git a/.travis.yml b/.travis.yml index 54d66546e..b2ef3881c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,9 @@ language: node_js dist: trusty sudo: false node_js: - - "4.2" - - "6" - "8" + - "10" + - "12" env: - PGUSER=postgres services: diff --git a/Makefile b/Makefile index d7ec83d54..fea33ad64 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,14 @@ -.PHONY: publish-patch test - +.PHONY: test test: npm test +.PHONY: patch patch: test npm version patch -m "Bump version" git push origin master --tags npm publish +.PHONY: minor minor: test npm version minor -m "Bump version" git push origin master --tags diff --git a/index.js b/index.js index 1984e4685..d10229241 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,7 @@ const util = require('util') var nextUniqueID = 1 // concept borrowed from org.postgresql.core.v3.QueryExecutorImpl -function Cursor (text, values, config) { +function Cursor(text, values, config) { EventEmitter.call(this) this._conf = config || {} @@ -23,25 +23,34 @@ function Cursor (text, values, config) { util.inherits(Cursor, EventEmitter) -Cursor.prototype.submit = function (connection) { +Cursor.prototype.submit = function(connection) { this.connection = connection - this._portal = 'C_' + (nextUniqueID++) + this._portal = 'C_' + nextUniqueID++ const con = connection - con.parse({ - text: this.text - }, true) - - con.bind({ - portal: this._portal, - values: this.values - }, true) - - con.describe({ - type: 'P', - name: this._portal // AWS Redshift requires a portal name - }, true) + con.parse( + { + text: this.text, + }, + true + ) + + con.bind( + { + portal: this._portal, + values: this.values, + }, + true + ) + + con.describe( + { + type: 'P', + name: this._portal, // AWS Redshift requires a portal name + }, + true + ) con.flush() @@ -60,25 +69,25 @@ Cursor.prototype.submit = function (connection) { }) } -Cursor.prototype._shiftQueue = function () { +Cursor.prototype._shiftQueue = function() { if (this._queue.length) { this._getRows.apply(this, this._queue.shift()) } } -Cursor.prototype.handleRowDescription = function (msg) { +Cursor.prototype.handleRowDescription = function(msg) { this._result.addFields(msg.fields) this.state = 'idle' this._shiftQueue() } -Cursor.prototype.handleDataRow = function (msg) { +Cursor.prototype.handleDataRow = function(msg) { const row = this._result.parseRow(msg.fields) this.emit('row', row, this._result) this._rows.push(row) } -Cursor.prototype._sendRows = function () { +Cursor.prototype._sendRows = function() { this.state = 'idle' setImmediate(() => { const cb = this._cb @@ -94,26 +103,26 @@ Cursor.prototype._sendRows = function () { }) } -Cursor.prototype.handleCommandComplete = function (msg) { +Cursor.prototype.handleCommandComplete = function(msg) { this._result.addCommandComplete(msg) this.connection.sync() } -Cursor.prototype.handlePortalSuspended = function () { +Cursor.prototype.handlePortalSuspended = function() { this._sendRows() } -Cursor.prototype.handleReadyForQuery = function () { +Cursor.prototype.handleReadyForQuery = function() { this._sendRows() this.emit('end', this._result) this.state = 'done' } -Cursor.prototype.handleEmptyQuery = function () { +Cursor.prototype.handleEmptyQuery = function() { this.connection.sync() } -Cursor.prototype.handleError = function (msg) { +Cursor.prototype.handleError = function(msg) { this.state = 'error' this._error = msg // satisfy any waiting callback @@ -133,19 +142,19 @@ Cursor.prototype.handleError = function (msg) { this.connection.sync() } -Cursor.prototype._getRows = function (rows, cb) { +Cursor.prototype._getRows = function(rows, cb) { this.state = 'busy' this._cb = cb this._rows = [] const msg = { portal: this._portal, - rows: rows + rows: rows, } this.connection.execute(msg, true) this.connection.flush() } -Cursor.prototype.end = function (cb) { +Cursor.prototype.end = function(cb) { if (this.state !== 'initialized') { this.connection.sync() } @@ -153,7 +162,7 @@ Cursor.prototype.end = function (cb) { this.connection.end() } -Cursor.prototype.close = function (cb) { +Cursor.prototype.close = function(cb) { if (this.state === 'done') { return setImmediate(cb) } @@ -161,13 +170,13 @@ Cursor.prototype.close = function (cb) { this.connection.sync() this.state = 'done' if (cb) { - this.connection.once('closeComplete', function () { + this.connection.once('closeComplete', function() { cb() }) } } -Cursor.prototype.read = function (rows, cb) { +Cursor.prototype.read = function(rows, cb) { if (this.state === 'idle') { return this._getRows(rows, cb) } diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 571f921d8..000000000 --- a/package-lock.json +++ /dev/null @@ -1,1807 +0,0 @@ -{ - "name": "pg-cursor", - "version": "2.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "^3.0.4" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } - }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", - "dev": true - }, - "ansi-escapes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-writer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-1.0.1.tgz", - "integrity": "sha1-Iqk2kB4wKa/NdUfrRIfOtpejvwg=", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } - }, - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", - "dev": true - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "eslint": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", - "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", - "dev": true, - "requires": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", - "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^3.7.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.4", - "esquery": "^1.0.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", - "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", - "progress": "^2.0.0", - "regexpp": "^1.0.1", - "require-uncached": "^1.0.3", - "semver": "^5.3.0", - "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", - "table": "4.0.2", - "text-table": "~0.2.0" - } - }, - "eslint-config-standard": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", - "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", - "dev": true - }, - "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.5.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-module-utils": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", - "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", - "dev": true, - "requires": { - "debug": "^2.6.8", - "pkg-dir": "^1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-plugin-import": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", - "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", - "dev": true, - "requires": { - "contains-path": "^0.1.0", - "debug": "^2.6.8", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.1", - "eslint-module-utils": "^2.2.0", - "has": "^1.0.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.3", - "read-pkg-up": "^2.0.0", - "resolve": "^1.6.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-plugin-node": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", - "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", - "dev": true, - "requires": { - "ignore": "^3.3.6", - "minimatch": "^3.0.4", - "resolve": "^1.3.3", - "semver": "5.3.0" - }, - "dependencies": { - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - } - } - }, - "eslint-plugin-promise": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz", - "integrity": "sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==", - "dev": true - }, - "eslint-plugin-standard": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz", - "integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==", - "dev": true - }, - "eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", - "dev": true - }, - "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true, - "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "dev": true, - "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" - } - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "flat-cache": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", - "dev": true, - "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "generic-pool": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-2.4.3.tgz", - "integrity": "sha1-eAw29p360FpaBF3Te+etyhGk9v8=", - "dev": true - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "globals": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz", - "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==", - "dev": true - }, - "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", - "dev": true - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "js-string-escape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", - "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=", - "dev": true - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", - "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "dependencies": { - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } - } - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "^3.0.0", - "lodash._basecreate": "^3.0.0", - "lodash._isiterateecall": "^3.0.0" - } - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "mocha": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.6.8", - "diff": "3.2.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", - "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "packet-reader": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", - "integrity": "sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc=", - "dev": true - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pg": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/pg/-/pg-6.4.2.tgz", - "integrity": "sha1-w2QBEGDqx6UHoq4GPrhX7OkQ4n8=", - "dev": true, - "requires": { - "buffer-writer": "1.0.1", - "js-string-escape": "1.0.1", - "packet-reader": "0.3.1", - "pg-connection-string": "0.1.3", - "pg-pool": "1.*", - "pg-types": "1.*", - "pgpass": "1.*", - "semver": "4.3.2" - }, - "dependencies": { - "semver": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", - "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=", - "dev": true - } - } - }, - "pg-connection-string": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", - "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=", - "dev": true - }, - "pg-int8": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", - "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", - "dev": true - }, - "pg-pool": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-1.8.0.tgz", - "integrity": "sha1-9+xzgkw3oD8Hb1G/33DjQBR8Tzc=", - "dev": true, - "requires": { - "generic-pool": "2.4.3", - "object-assign": "4.1.0" - }, - "dependencies": { - "object-assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.0.tgz", - "integrity": "sha1-ejs9DpgGPUP0wD8uiubNUahog6A=", - "dev": true - } - } - }, - "pg-types": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.13.0.tgz", - "integrity": "sha512-lfKli0Gkl/+za/+b6lzENajczwZHc7D5kiUCZfgm914jipD2kIOIvEkAhZ8GrW3/TUoP9w8FHjwpPObBye5KQQ==", - "dev": true, - "requires": { - "pg-int8": "1.0.1", - "postgres-array": "~1.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.0", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "dev": true, - "requires": { - "split": "^1.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - } - }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", - "dev": true - }, - "postgres-array": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.3.tgz", - "integrity": "sha512-5wClXrAP0+78mcsNX3/ithQ5exKvCyK5lr5NEEEeGwwM6NJdQgzIJBVxLvRW+huFpX92F2QnZ5CcokH0VhK2qQ==", - "dev": true - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", - "dev": true - }, - "postgres-date": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.3.tgz", - "integrity": "sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g=", - "dev": true - }, - "postgres-interval": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.1.2.tgz", - "integrity": "sha512-fC3xNHeTskCxL1dC8KOtxXt7YeFmlbTYtn7ul8MkVERuTmf7pI4DrkAxcw3kh1fQ9uz4wQmd03a1mRiXUZChfQ==", - "dev": true, - "requires": { - "xtend": "^4.0.0" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - } - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "regexpp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", - "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", - "dev": true - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - } - }, - "resolve": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", - "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true, - "requires": { - "rx-lite": "*" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0" - } - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", - "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", - "dev": true - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "requires": { - "through": "2" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - } - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "table": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", - "dev": true, - "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - } -} diff --git a/package.json b/package.json index 2841be631..941853c71 100644 --- a/package.json +++ b/package.json @@ -16,14 +16,18 @@ "author": "Brian M. Carlson", "license": "MIT", "devDependencies": { - "eslint": "^4.4.0", - "eslint-config-standard": "^10.2.1", + "eslint": "^6.5.1", + "eslint-config-prettier": "^6.4.0", "eslint-plugin-import": "^2.7.0", - "eslint-plugin-node": "^5.1.1", - "eslint-plugin-promise": "^3.5.0", - "eslint-plugin-standard": "^3.0.1", - "mocha": "^3.5.0", - "pg": "6.x" + "eslint-plugin-prettier": "^3.1.1", + "mocha": "^6.2.2", + "pg": "^7.12.1", + "prettier": "^1.18.2" }, - "dependencies": {} + "prettier": { + "semi": false, + "printWidth": 120, + "trailingComma": "es5", + "singleQuote": true + } } diff --git a/test/close.js b/test/close.js index 59ea3c71a..e9b4009b5 100644 --- a/test/close.js +++ b/test/close.js @@ -3,30 +3,30 @@ var Cursor = require('../') var pg = require('pg') var text = 'SELECT generate_series as num FROM generate_series(0, 50)' -describe('close', function () { - beforeEach(function (done) { - var client = this.client = new pg.Client() +describe('close', function() { + beforeEach(function(done) { + var client = (this.client = new pg.Client()) client.connect(done) client.on('drain', client.end.bind(client)) }) - it('closes cursor early', function (done) { + it('closes cursor early', function(done) { var cursor = new Cursor(text) this.client.query(cursor) this.client.query('SELECT NOW()', done) - cursor.read(25, function (err, res) { + cursor.read(25, function(err) { assert.ifError(err) cursor.close() }) }) - it('works with callback style', function (done) { + it('works with callback style', function(done) { var cursor = new Cursor(text) var client = this.client client.query(cursor) - cursor.read(25, function (err, res) { + cursor.read(25, function(err) { assert.ifError(err) - cursor.close(function (err) { + cursor.close(function(err) { assert.ifError(err) client.query('SELECT NOW()', done) }) diff --git a/test/error-handling.js b/test/error-handling.js index bfcbf71f1..4b2ea5009 100644 --- a/test/error-handling.js +++ b/test/error-handling.js @@ -5,14 +5,14 @@ var pg = require('pg') var text = 'SELECT generate_series as num FROM generate_series(0, 4)' -describe('error handling', function () { - it('can continue after error', function (done) { +describe('error handling', function() { + it('can continue after error', function(done) { var client = new pg.Client() client.connect() var cursor = client.query(new Cursor('asdfdffsdf')) - cursor.read(1, function (err) { + cursor.read(1, function(err) { assert(err) - client.query('SELECT NOW()', function (err, res) { + client.query('SELECT NOW()', function(err) { assert.ifError(err) client.end() done() @@ -22,16 +22,16 @@ describe('error handling', function () { }) describe('read callback does not fire sync', () => { - it('does not fire error callback sync', (done) => { + it('does not fire error callback sync', done => { var client = new pg.Client() client.connect() var cursor = client.query(new Cursor('asdfdffsdf')) let after = false - cursor.read(1, function (err) { + cursor.read(1, function(err) { assert(err, 'error should be returned') assert.equal(after, true, 'should not call read sync') after = false - cursor.read(1, function (err) { + cursor.read(1, function(err) { assert(err, 'error should be returned') assert.equal(after, true, 'should not call read sync') client.end() @@ -42,18 +42,18 @@ describe('read callback does not fire sync', () => { after = true }) - it('does not fire result sync after finished', (done) => { + it('does not fire result sync after finished', done => { var client = new pg.Client() client.connect() var cursor = client.query(new Cursor('SELECT NOW()')) let after = false - cursor.read(1, function (err) { + cursor.read(1, function(err) { assert(!err) assert.equal(after, true, 'should not call read sync') - cursor.read(1, function (err) { + cursor.read(1, function(err) { assert(!err) after = false - cursor.read(1, function (err) { + cursor.read(1, function(err) { assert(!err) assert.equal(after, true, 'should not call read sync') client.end() @@ -66,16 +66,16 @@ describe('read callback does not fire sync', () => { }) }) -describe('proper cleanup', function () { - it('can issue multiple cursors on one client', function (done) { +describe('proper cleanup', function() { + it('can issue multiple cursors on one client', function(done) { var client = new pg.Client() client.connect() var cursor1 = client.query(new Cursor(text)) - cursor1.read(8, function (err, rows) { + cursor1.read(8, function(err, rows) { assert.ifError(err) assert.equal(rows.length, 5) var cursor2 = client.query(new Cursor(text)) - cursor2.read(8, function (err, rows) { + cursor2.read(8, function(err, rows) { assert.ifError(err) assert.equal(rows.length, 5) client.end() diff --git a/test/index.js b/test/index.js index 31a676e98..884edc250 100644 --- a/test/index.js +++ b/test/index.js @@ -4,59 +4,59 @@ var pg = require('pg') var text = 'SELECT generate_series as num FROM generate_series(0, 5)' -describe('cursor', function () { - beforeEach(function (done) { - var client = this.client = new pg.Client() +describe('cursor', function() { + beforeEach(function(done) { + var client = (this.client = new pg.Client()) client.connect(done) - this.pgCursor = function (text, values) { + this.pgCursor = function(text, values) { client.on('drain', client.end.bind(client)) return client.query(new Cursor(text, values || [])) } }) - afterEach(function () { + afterEach(function() { this.client.end() }) - it('fetch 6 when asking for 10', function (done) { + it('fetch 6 when asking for 10', function(done) { var cursor = this.pgCursor(text) - cursor.read(10, function (err, res) { + cursor.read(10, function(err, res) { assert.ifError(err) assert.equal(res.length, 6) done() }) }) - it('end before reading to end', function (done) { + it('end before reading to end', function(done) { var cursor = this.pgCursor(text) - cursor.read(3, function (err, res) { + cursor.read(3, function(err, res) { assert.ifError(err) assert.equal(res.length, 3) cursor.end(done) }) }) - it('callback with error', function (done) { + it('callback with error', function(done) { var cursor = this.pgCursor('select asdfasdf') - cursor.read(1, function (err) { + cursor.read(1, function(err) { assert(err) done() }) }) - it('read a partial chunk of data', function (done) { + it('read a partial chunk of data', function(done) { var cursor = this.pgCursor(text) - cursor.read(2, function (err, res) { + cursor.read(2, function(err, res) { assert.ifError(err) assert.equal(res.length, 2) - cursor.read(3, function (err, res) { + cursor.read(3, function(err, res) { assert(!err) assert.equal(res.length, 3) - cursor.read(1, function (err, res) { + cursor.read(1, function(err, res) { assert(!err) assert.equal(res.length, 1) - cursor.read(1, function (err, res) { + cursor.read(1, function(err, res) { assert(!err) assert.ifError(err) assert.strictEqual(res.length, 0) @@ -67,14 +67,14 @@ describe('cursor', function () { }) }) - it('read return length 0 past the end', function (done) { + it('read return length 0 past the end', function(done) { var cursor = this.pgCursor(text) - cursor.read(2, function (err, res) { + cursor.read(2, function(err) { assert(!err) - cursor.read(100, function (err, res) { + cursor.read(100, function(err, res) { assert(!err) assert.equal(res.length, 4) - cursor.read(100, function (err, res) { + cursor.read(100, function(err, res) { assert(!err) assert.equal(res.length, 0) done() @@ -83,14 +83,14 @@ describe('cursor', function () { }) }) - it('read huge result', function (done) { + it('read huge result', function(done) { this.timeout(10000) var text = 'SELECT generate_series as num FROM generate_series(0, 100000)' var values = [] var cursor = this.pgCursor(text, values) var count = 0 - var read = function () { - cursor.read(100, function (err, rows) { + var read = function() { + cursor.read(100, function(err, rows) { if (err) return done(err) if (!rows.length) { assert.equal(count, 100001) @@ -106,14 +106,14 @@ describe('cursor', function () { read() }) - it('normalizes parameter values', function (done) { + it('normalizes parameter values', function(done) { var text = 'SELECT $1::json me' var values = [{ name: 'brian' }] var cursor = this.pgCursor(text, values) - cursor.read(1, function (err, rows) { + cursor.read(1, function(err, rows) { if (err) return done(err) assert.equal(rows[0].me.name, 'brian') - cursor.read(1, function (err, rows) { + cursor.read(1, function(err, rows) { assert(!err) assert.equal(rows.length, 0) done() @@ -121,9 +121,9 @@ describe('cursor', function () { }) }) - it('returns result along with rows', function (done) { + it('returns result along with rows', function(done) { var cursor = this.pgCursor(text) - cursor.read(1, function (err, rows, result) { + cursor.read(1, function(err, rows, result) { assert.ifError(err) assert.equal(rows.length, 1) assert.strictEqual(rows, result.rows) @@ -132,20 +132,20 @@ describe('cursor', function () { }) }) - it('emits row events', function (done) { + it('emits row events', function(done) { var cursor = this.pgCursor(text) cursor.read(10) cursor.on('row', (row, result) => result.addRow(row)) - cursor.on('end', (result) => { + cursor.on('end', result => { assert.equal(result.rows.length, 6) done() }) }) - it('emits row events when cursor is closed manually', function (done) { + it('emits row events when cursor is closed manually', function(done) { var cursor = this.pgCursor(text) cursor.on('row', (row, result) => result.addRow(row)) - cursor.on('end', (result) => { + cursor.on('end', result => { assert.equal(result.rows.length, 3) done() }) @@ -153,25 +153,27 @@ describe('cursor', function () { cursor.read(3, () => cursor.close()) }) - it('emits error events', function (done) { + it('emits error events', function(done) { var cursor = this.pgCursor('select asdfasdf') - cursor.on('error', function (err) { + cursor.on('error', function(err) { assert(err) done() }) }) - it('returns rowCount on insert', function (done) { + it('returns rowCount on insert', function(done) { var pgCursor = this.pgCursor - this.client.query('CREATE TEMPORARY TABLE pg_cursor_test (foo VARCHAR(1), bar VARCHAR(1))') - .then(function () { + this.client + .query('CREATE TEMPORARY TABLE pg_cursor_test (foo VARCHAR(1), bar VARCHAR(1))') + .then(function() { var cursor = pgCursor('insert into pg_cursor_test values($1, $2)', ['a', 'b']) - cursor.read(1, function (err, rows, result) { + cursor.read(1, function(err, rows, result) { assert.ifError(err) assert.equal(rows.length, 0) assert.equal(result.rowCount, 1) done() }) - }).catch(done) + }) + .catch(done) }) }) diff --git a/test/no-data-handling.js b/test/no-data-handling.js index 2218b41de..7c653e718 100644 --- a/test/no-data-handling.js +++ b/test/no-data-handling.js @@ -2,30 +2,30 @@ var assert = require('assert') var pg = require('pg') var Cursor = require('../') -describe('queries with no data', function () { - beforeEach(function (done) { - var client = this.client = new pg.Client() +describe('queries with no data', function() { + beforeEach(function(done) { + var client = (this.client = new pg.Client()) client.connect(done) }) - afterEach(function () { + afterEach(function() { this.client.end() }) - it('handles queries that return no data', function (done) { + it('handles queries that return no data', function(done) { var cursor = new Cursor('CREATE TEMPORARY TABLE whatwhat (thing int)') this.client.query(cursor) - cursor.read(100, function (err, rows) { + cursor.read(100, function(err, rows) { assert.ifError(err) assert.equal(rows.length, 0) done() }) }) - it('handles empty query', function (done) { + it('handles empty query', function(done) { var cursor = new Cursor('-- this is a comment') cursor = this.client.query(cursor) - cursor.read(100, function (err, rows) { + cursor.read(100, function(err, rows) { assert.ifError(err) assert.equal(rows.length, 0) done() diff --git a/test/pool.js b/test/pool.js index e3d3bc1d9..bd487807b 100644 --- a/test/pool.js +++ b/test/pool.js @@ -5,7 +5,7 @@ const pg = require('pg') const text = 'SELECT generate_series as num FROM generate_series(0, 50)' -function poolQueryPromise (pool, readRowCount) { +function poolQueryPromise(pool, readRowCount) { return new Promise((resolve, reject) => { pool.connect((err, client, done) => { if (err) { @@ -13,7 +13,7 @@ function poolQueryPromise (pool, readRowCount) { return reject(err) } const cursor = client.query(new Cursor(text)) - cursor.read(readRowCount, (err, res) => { + cursor.read(readRowCount, err => { if (err) { done(err) return reject(err) @@ -31,16 +31,16 @@ function poolQueryPromise (pool, readRowCount) { }) } -describe('pool', function () { - beforeEach(function () { - this.pool = new pg.Pool({max: 1}) +describe('pool', function() { + beforeEach(function() { + this.pool = new pg.Pool({ max: 1 }) }) - afterEach(function () { + afterEach(function() { this.pool.end() }) - it('closes cursor early, single pool query', function (done) { + it('closes cursor early, single pool query', function(done) { poolQueryPromise(this.pool, 25) .then(() => done()) .catch(err => { @@ -49,7 +49,7 @@ describe('pool', function () { }) }) - it('closes cursor early, saturated pool', function (done) { + it('closes cursor early, saturated pool', function(done) { const promises = [] for (let i = 0; i < 10; i++) { promises.push(poolQueryPromise(this.pool, 25)) @@ -62,7 +62,7 @@ describe('pool', function () { }) }) - it('closes exhausted cursor, single pool query', function (done) { + it('closes exhausted cursor, single pool query', function(done) { poolQueryPromise(this.pool, 100) .then(() => done()) .catch(err => { @@ -71,7 +71,7 @@ describe('pool', function () { }) }) - it('closes exhausted cursor, saturated pool', function (done) { + it('closes exhausted cursor, saturated pool', function(done) { const promises = [] for (let i = 0; i < 10; i++) { promises.push(poolQueryPromise(this.pool, 100)) diff --git a/test/query-config.js b/test/query-config.js index 596adb9c2..53b612c8b 100644 --- a/test/query-config.js +++ b/test/query-config.js @@ -4,7 +4,7 @@ const Cursor = require('../') const pg = require('pg') describe('query config passed to result', () => { - it('passes rowMode to result', (done) => { + it('passes rowMode to result', done => { const client = new pg.Client() client.connect() const text = 'SELECT generate_series as num FROM generate_series(0, 5)' @@ -17,12 +17,12 @@ describe('query config passed to result', () => { }) }) - it('passes types to result', (done) => { + it('passes types to result', done => { const client = new pg.Client() client.connect() const text = 'SELECT generate_series as num FROM generate_series(0, 2)' const types = { - getTypeParser: () => () => 'foo' + getTypeParser: () => () => 'foo', } const cursor = client.query(new Cursor(text, null, { types })) cursor.read(10, (err, rows) => { diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..fedde16d3 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1549 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0": + version "7.5.5" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha1-vAeC9tafe31JUxIZaZuYj2aaj50= + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/highlight@^7.0.0": + version "7.5.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha1-VtETEr2SSPphlZHQJHK+boyzJUA= + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +acorn-jsx@^5.1.0: + version "5.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" + integrity sha1-KUrbcbVzmLBoABXwo4xWPuHbU4Q= + +acorn@^7.1.0: + version "7.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" + integrity sha1-lJ028sKSU12mAig1hsJHfFfrLWw= + +ajv@^6.10.0, ajv@^6.10.2: + version "6.10.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" + integrity sha1-086gTWsBeyiUrWkED+yLYj60vVI= + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha1-V9NbhoboUeLMBMQD8cACA5dqGBM= + +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha1-h4C5j/nb9WOBUtHx/lwde0RCl2s= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc= + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0= + dependencies: + color-convert "^1.9.0" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE= + dependencies: + sprintf-js "~1.0.2" + +array-includes@^3.0.3: + version "3.0.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" + integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.7.0" + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha1-bIw/uCfdQ+45GPJ7gngqt2WKb9k= + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0= + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha1-uqVZ7hTO1zRSIputcyZGfGH6vWA= + +buffer-writer@2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" + integrity sha1-zn64Gjj3gp2wnIc/L7t5LAyY7AQ= + +callsites@^3.0.0: + version "3.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M= + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA= + +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.2: + version "2.4.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ= + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chardet@^0.7.0: + version "0.7.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha1-kAlISfCTfy7twkJdDSip5fDLrZ4= + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + +cliui@^5.0.0: + version "5.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha1-3u/P2y6AB4SqNPRvoI4GhRx7u8U= + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg= + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +concat-map@0.0.1: + version "0.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +contains-path@^0.1.0: + version "0.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= + +cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q= + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +debug@3.2.6: + version "3.2.6" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha1-6D0X3hbYp++3cX7b5fsQE17uYps= + dependencies: + ms "^2.1.1" + +debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8= + dependencies: + ms "2.0.0" + +debug@^4.0.1: + version "4.1.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E= + dependencies: + ms "^2.1.1" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE= + dependencies: + object-keys "^1.0.12" + +diff@3.5.0: + version "3.5.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI= + +doctrine@1.5.0: + version "1.5.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha1-rd6+rXKmV023g2OdyHoSF3OXOWE= + dependencies: + esutils "^2.0.2" + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY= + +error-ex@^1.2.0: + version "1.3.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha1-tKxAZIEH/c3PriQvQovqihTU8b8= + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.12.0, es-abstract@^1.5.1, es-abstract@^1.7.0: + version "1.16.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" + integrity sha1-06JtycMoOsl1DcpWlYbpdtncwG0= + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.0" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-inspect "^1.6.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.1.0" + string.prototype.trimright "^2.1.0" + +es-to-primitive@^1.2.0: + version "1.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha1-7fckeAM0VujdqO8J4ArZZQcH83c= + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +eslint-config-prettier@^6.4.0: + version "6.4.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-config-prettier/-/eslint-config-prettier-6.4.0.tgz#0a04f147e31d33c6c161b2dd0971418ac52d0477" + integrity sha1-CgTxR+MdM8bBYbLdCXFBisUtBHc= + dependencies: + get-stdin "^6.0.0" + +eslint-import-resolver-node@^0.3.2: + version "0.3.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" + integrity sha1-WPFfuDm40FdsqYBBNHaqskcttmo= + dependencies: + debug "^2.6.9" + resolve "^1.5.0" + +eslint-module-utils@^2.4.0: + version "2.4.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz#7b4675875bf96b0dbf1b21977456e5bb1f5e018c" + integrity sha1-e0Z1h1v5aw2/GyGXdFblux9eAYw= + dependencies: + debug "^2.6.8" + pkg-dir "^2.0.0" + +eslint-plugin-import@^2.7.0: + version "2.18.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz#02f1180b90b077b33d447a17a2326ceb400aceb6" + integrity sha1-AvEYC5Cwd7M9RHoXojJs60AKzrY= + dependencies: + array-includes "^3.0.3" + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.2" + eslint-module-utils "^2.4.0" + has "^1.0.3" + minimatch "^3.0.4" + object.values "^1.1.0" + read-pkg-up "^2.0.0" + resolve "^1.11.0" + +eslint-plugin-prettier@^3.1.1: + version "3.1.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.1.tgz#507b8562410d02a03f0ddc949c616f877852f2ba" + integrity sha1-UHuFYkENAqA/DdyUnGFvh3hS8ro= + dependencies: + prettier-linter-helpers "^1.0.0" + +eslint-scope@^5.0.0: + version "5.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" + integrity sha1-6HyIh8c+jR7ITxylkWRcNYv8j7k= + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-utils@^1.4.2: + version "1.4.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha1-dP7HxU0Hdrb2fgJRBAtYBlZOmB8= + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.1.0: + version "1.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha1-4qgs6oT/JGrW+1f5veW0ZiFFnsI= + +eslint@^6.5.1: + version "6.5.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint/-/eslint-6.5.1.tgz#828e4c469697d43bb586144be152198b91e96ed6" + integrity sha1-go5MRpaX1Du1hhRL4VIZi5HpbtY= + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.10.0" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^5.0.0" + eslint-utils "^1.4.2" + eslint-visitor-keys "^1.1.0" + espree "^6.1.1" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^6.4.1" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.14" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^6.1.1: + version "6.1.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" + integrity sha1-bCcmUJMrT5HDcU5ee19eLs9HJi0= + dependencies: + acorn "^7.1.0" + acorn-jsx "^5.1.0" + eslint-visitor-keys "^1.1.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha1-E7BM2z5sXRnfkatph6hpVhmwqnE= + +esquery@^1.0.1: + version "1.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + integrity sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg= + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8= + dependencies: + estraverse "^4.1.0" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: + version "4.3.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha1-OYrT88WiSUi+dyXoPRGn3ijNvR0= + +esutils@^2.0.2: + version "2.0.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q= + +external-editor@^3.0.3: + version "3.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha1-ywP3QL764D6k0oPK7SdBqD8zVJU= + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha1-c+4RmC2Gyq95WYKNUZz+kn+sXwM= + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +fast-levenshtein@~2.0.4: + version "2.0.6" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +figures@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha1-yg9u+m3T1WEzP7FFFQZcL6/fQ5w= + dependencies: + flat-cache "^2.0.1" + +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha1-SRafHXmTQwZG2mHsxa41XCHJe3M= + dependencies: + locate-path "^3.0.0" + +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha1-XSltbwS9pEpGMKMBQTvbwuwIXsA= + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flat@^4.1.0: + version "4.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" + integrity sha1-CQvsiwXjnLowl0fx1YjwTbr5jbI= + dependencies: + is-buffer "~2.0.3" + +flatted@^2.0.0: + version "2.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" + integrity sha1-aeV8qo8OrLwoHS4stFjUb9tEngg= + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0= + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha1-T5RBKoLbMvNuOwuXQfipf+sDH34= + +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha1-ngm/cSs2CrkiXoEgSPcf3pyJZXs= + +glob-parent@^5.0.0: + version "5.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" + integrity sha1-X0wdHnSNMM1zrSlEs1d6gbCB6MI= + dependencies: + is-glob "^4.0.1" + +glob@7.1.3: + version "7.1.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha1-OWCDLT8VdBCDQtr9OmezMsCWnfE= + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.1.3: + version "7.1.5" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/glob/-/glob-7.1.5.tgz#6714c69bee20f3c3e64c4dd905553e532b40cdc0" + integrity sha1-ZxTGm+4g88PmTE3ZBVU+UytAzcA= + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.7.0: + version "11.12.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha1-q4eVM4hooLq9hSV1gBjCp+uVxC4= + +graceful-fs@^4.1.2: + version "4.2.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha1-ShL/G2A3bvCYYsIJPt2Qgyi+hCM= + +growl@1.10.5: + version "1.10.5" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha1-8nNdwig2dPpnR4sQGBBZNVw2nl4= + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + +has@^1.0.1, has@^1.0.3: + version "1.0.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y= + dependencies: + function-bind "^1.1.1" + +he@1.2.0: + version "1.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha1-hK5l+n6vsWX922FWauFLrwVmTw8= + +hosted-git-info@^2.1.4: + version "2.8.5" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" + integrity sha1-dZz88sTRVq3lmwst+r3cQqa5xww= + +iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha1-ICK0sl+93CHS9SSXSkdKr+czkIs= + dependencies: + safer-buffer ">= 2.1.2 < 3" + +ignore@^4.0.6: + version "4.0.6" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw= + +import-fresh@^3.0.0: + version "3.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" + integrity sha1-bTP6Hc7235MPrgA0RvM0Fa+QURg= + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w= + +inquirer@^6.4.1: + version "6.5.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha1-rVCUI3XQNtMn/1KMCL1fqwiZKMo= + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-buffer@~2.0.3: + version "2.0.4" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha1-PlcvI8hBGlz9lVfISeNmXgspBiM= + +is-callable@^1.1.4: + version "1.1.4" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU= + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-glob@^4.0.0, is-glob@^4.0.1: + version "4.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw= + dependencies: + is-extglob "^2.1.1" + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" + +is-symbol@^1.0.2: + version "1.0.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha1-oFX2rlcZLK7jKeeoYBGLSXqVDzg= + dependencies: + has-symbols "^1.0.0" + +isarray@^1.0.0: + version "1.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha1-GSA/tZmR35jjoocFDUZHzerzJJk= + +js-yaml@3.13.1, js-yaml@^3.13.1: + version "3.13.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha1-r/FRswv9+o5J4F2iLnQV6d+jeEc= + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha1-afaofZUTq4u4/mO9sJecRI5oRmA= + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4= + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15: + version "4.17.15" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg= + +log-symbols@2.2.0: + version "2.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo= + dependencies: + chalk "^2.0.1" + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI= + +minimatch@3.0.4, minimatch@^3.0.4: + version "3.0.4" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM= + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +mkdirp@0.5.1, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +mocha@^6.2.2: + version "6.2.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" + integrity sha1-XYmH4olAyviVen12ZLkQ3Fsv6iA= + dependencies: + ansi-colors "3.2.3" + browser-stdout "1.3.1" + debug "3.2.6" + diff "3.5.0" + escape-string-regexp "1.0.5" + find-up "3.0.0" + glob "7.1.3" + growl "1.10.5" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "2.2.0" + minimatch "3.0.4" + mkdirp "0.5.1" + ms "2.1.1" + node-environment-flags "1.0.5" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.0" + yargs-parser "13.1.1" + yargs-unparser "1.6.0" + +ms@2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.1: + version "2.1.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo= + +ms@^2.1.1: + version "2.1.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk= + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y= + +node-environment-flags@1.0.5: + version "1.0.5" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha1-+pMCdfW/Xa4YjWGSsktMi7rD12o= + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + +normalize-package-data@^2.3.2: + version "2.5.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg= + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +object-inspect@^1.6.0: + version "1.6.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + integrity sha1-xwtsv3LydKq0w0wMgvUWe/gs8Vs= + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha1-HEfyct8nfzsdrwYWd9nILiMixg4= + +object.assign@4.1.0: + version "4.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha1-lovxEA15Vrs8oIbwBvhGs7xACNo= + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + +object.values@^1.1.0: + version "1.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" + integrity sha1-v2gQ712j5TJXkOqqK+IT6oRiTak= + dependencies: + define-properties "^1.1.3" + es-abstract "^1.12.0" + function-bind "^1.1.1" + has "^1.0.3" + +once@^1.3.0: + version "1.4.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + dependencies: + mimic-fn "^1.0.0" + +optionator@^0.8.2: + version "0.8.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.4" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + wordwrap "~1.0.0" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg= + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0: + version "2.2.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha1-qgeniMwxUck5tRMfY1cPDdIAlTc= + dependencies: + p-try "^2.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ= + dependencies: + p-limit "^2.0.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha1-yyhoVA4xPWHeWPr741zpAE1VQOY= + +packet-reader@1.0.0: + version "1.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" + integrity sha1-kjjlSA3tq6z+H+PydxBj8WQVfXQ= + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha1-aR0nCeeMefrjoVZiJFLQB2LKqqI= + dependencies: + callsites "^3.0.0" + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^2.0.1: + version "2.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha1-1i27VnlAXXLEc37FhgDp3c8G0kw= + +path-type@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= + dependencies: + pify "^2.0.0" + +pg-connection-string@0.1.3: + version "0.1.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" + integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc= + +pg-int8@1.0.1: + version "1.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" + integrity sha1-lDvUY79bcbQXARX4D478mgwOt4w= + +pg-pool@^2.0.4: + version "2.0.7" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pg-pool/-/pg-pool-2.0.7.tgz#f14ecab83507941062c313df23f6adcd9fd0ce54" + integrity sha1-8U7KuDUHlBBiwxPfI/atzZ/QzlQ= + +pg-types@^2.1.0: + version "2.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" + integrity sha1-LQJQ1jZFT3z6O2rgOC/fqAYyVKM= + dependencies: + pg-int8 "1.0.1" + postgres-array "~2.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.4" + postgres-interval "^1.1.0" + +pg@^7.12.1: + version "7.12.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pg/-/pg-7.12.1.tgz#880636d46d2efbe0968e64e9fe0eeece8ef72a7e" + integrity sha1-iAY21G0u++CWjmTp/g7uzo73Kn4= + dependencies: + buffer-writer "2.0.0" + packet-reader "1.0.0" + pg-connection-string "0.1.3" + pg-pool "^2.0.4" + pg-types "^2.1.0" + pgpass "1.x" + semver "4.3.2" + +pgpass@1.x: + version "1.0.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" + integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY= + dependencies: + split "^1.0.0" + +pify@^2.0.0: + version "2.3.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + dependencies: + find-up "^2.1.0" + +postgres-array@~2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" + integrity sha1-SPj84FT7xpZxmZMpuINLdyZS2C4= + +postgres-bytea@~1.0.0: + version "1.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU= + +postgres-date@~1.0.4: + version "1.0.4" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/postgres-date/-/postgres-date-1.0.4.tgz#1c2728d62ef1bff49abdd35c1f86d4bdf118a728" + integrity sha1-HCco1i7xv/SavdNcH4bUvfEYpyg= + +postgres-interval@^1.1.0: + version "1.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" + integrity sha1-tGDILLFYdQd4iBmgaqD//bNURpU= + dependencies: + xtend "^4.0.0" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha1-0j1B/hN1ZG3i0BBNNFSjAIgCz3s= + dependencies: + fast-diff "^1.1.2" + +prettier@^1.18.2: + version "1.18.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" + integrity sha1-aCPnxZAAF7S9Os9G/prEtNe9qeo= + +progress@^2.0.0: + version "2.0.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha1-foz42PW48jnBvGi+tOt4Vn1XLvg= + +punycode@^2.1.0: + version "2.1.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha1-tYsBCsQMIsVldhbI0sLALHv0eew= + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +regexpp@^2.0.1: + version "2.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha1-jRnTHPYySCtYkEn4KB+T28uk0H8= + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha1-0LMp7MfMD2Fkn2IhW+aa9UqomJs= + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY= + +resolve@^1.10.0, resolve@^1.11.0, resolve@^1.5.0: + version "1.12.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" + integrity sha1-P8ZEo1yEpIVUYJ/ybsUrZvpXffY= + dependencies: + path-parse "^1.0.6" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +rimraf@2.6.3: + version "2.6.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha1-stEE/g2Psnz54KHNqCYt04M8bKs= + dependencies: + glob "^7.1.3" + +run-async@^2.2.0: + version "2.3.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= + dependencies: + is-promise "^2.1.0" + +rxjs@^6.4.0: + version "6.5.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" + integrity sha1-UQ4mMX9NuRp+sd532d2boKSJmjo= + dependencies: + tslib "^1.9.0" + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo= + +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.7.0: + version "5.7.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha1-qVT5Ma66UI0we78Gnv8MAclhFvc= + +semver@4.3.2: + version "4.3.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" + integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= + +semver@^6.1.2: + version "6.3.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0= + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +signal-exit@^3.0.2: + version "3.0.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha1-ys12k0YaY3pXiNkqfdT7oGjoFjY= + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +spdx-correct@^3.0.0: + version "3.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha1-+4PlBERSaPFUsHTiGMh8ADzTHfQ= + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha1-LqRQrudPKom/uUUZwH/Nb0EyKXc= + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha1-meEZt6XaAOBUkcn6M4t5BII7QdA= + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.5" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" + integrity sha1-NpS1gEVnpFjTyARYQqY1hjL2JlQ= + +split@^1.0.0: + version "1.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" + integrity sha1-YFvZvjA6pZ+zX5Ip++oN3snqB9k= + dependencies: + through "2" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +"string-width@^1.0.2 || 2", string-width@^2.1.0: + version "2.1.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4= + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha1-InZ74htirxCBV0MG9prFG2IgOWE= + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string.prototype.trimleft@^2.1.0: + version "2.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" + integrity sha1-bMR/DX641isPNwFhFxWjlUWR1jQ= + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.1.0: + version "2.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" + integrity sha1-Zp0WS+nfm291WfqOiZRbFopabFg= + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4= + dependencies: + ansi-regex "^4.1.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-json-comments@2.0.1: + version "2.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +strip-json-comments@^3.0.1: + version "3.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha1-hXE5dakfuHvxswXMp3OV5A0qZKc= + +supports-color@6.0.0: + version "6.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha1-ds/nQs8fQbubHCmtAwaMBbTA5Ao= + dependencies: + has-flag "^3.0.0" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha1-4uaaRKyHcveKHsCzW2id9lMO/I8= + dependencies: + has-flag "^3.0.0" + +table@^5.2.3: + version "5.4.6" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha1-EpLRlQDOP4YFOwXw6Ofko7shB54= + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +through@2, through@^2.3.6: + version "2.3.8" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +tmp@^0.0.33: + version "0.0.33" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha1-bTQzWIl2jSGyvNoKonfO07G/rfk= + dependencies: + os-tmpdir "~1.0.2" + +tslib@^1.9.0: + version "1.10.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha1-w8GflZc/sKYpc/sJ2Q2WHuQ+XIo= + +type-check@~0.3.2: + version "0.3.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha1-lMVA4f93KVbiKZUHwBCupsiDjrA= + dependencies: + punycode "^2.1.0" + +v8-compile-cache@^2.0.3: + version "2.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" + integrity sha1-4U3jezGm0ZT1aQ1n78Tn9vxqsw4= + +validate-npm-package-license@^3.0.1: + version "3.0.4" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha1-/JH2uce6FchX9MssXe/uw51PQQo= + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@1.3.1, which@^1.2.9: + version "1.3.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo= + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: + version "1.1.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha1-rgdOa9wMFKQx6ATmJFScYzsABFc= + dependencies: + string-width "^1.0.2 || 2" + +wordwrap@~1.0.0: + version "1.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha1-H9H2cjXVttD+54EFYAG/tpTAOwk= + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write@1.0.3: + version "1.0.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha1-CADhRSO5I6OH5BUSPIZWFqrg9cM= + dependencies: + mkdirp "^0.5.1" + +xtend@^4.0.0: + version "4.0.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q= + +y18n@^4.0.0: + version "4.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha1-le+U+F7MgdAHwmThkKEg8KPIVms= + +yargs-parser@13.1.1, yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha1-0mBYUyqgbTZf4JH2ofwGsvfl7KA= + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha1-7yXCx2n/a9CeSw+dfGBfsnhG6p8= + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + +yargs@13.3.0, yargs@^13.3.0: + version "13.3.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha1-TGV6VeB+Xyz5R/ijZlZ8BKDe3IM= + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1" From 4164686c4b6ae94e043c56719b5c78e97a74acc8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 25 Oct 2019 18:03:07 -0500 Subject: [PATCH 0496/1037] meh --- .eslintrc | 5 +- index.js | 6 +- package.json | 1 - test/close.js | 16 +- test/error-handling.js | 26 +- test/index.js | 51 ++- test/no-data-handling.js | 12 +- yarn.lock | 903 ++++++++++++++------------------------- 8 files changed, 385 insertions(+), 635 deletions(-) diff --git a/.eslintrc b/.eslintrc index 148d48bd9..5ce7148ea 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,9 +1,10 @@ { - "extends": "eslint:recommended", + "extends": ["eslint:recommended"], "plugins": ["prettier"], "rules": { "prettier/prettier": "error", - "no-new-func": "off" + "prefer-const": "error", + "no-var": "error" }, "env": { "es6": true, diff --git a/index.js b/index.js index d10229241..202cd9b6a 100644 --- a/index.js +++ b/index.js @@ -4,7 +4,7 @@ const prepare = require('pg/lib/utils.js').prepareValue const EventEmitter = require('events').EventEmitter const util = require('util') -var nextUniqueID = 1 // concept borrowed from org.postgresql.core.v3.QueryExecutorImpl +let nextUniqueID = 1 // concept borrowed from org.postgresql.core.v3.QueryExecutorImpl function Cursor(text, values, config) { EventEmitter.call(this) @@ -130,7 +130,7 @@ Cursor.prototype.handleError = function(msg) { this._cb(msg) } // dispatch error to all waiting callbacks - for (var i = 0; i < this._queue.length; i++) { + for (let i = 0; i < this._queue.length; i++) { this._queue.pop()[1](msg) } @@ -155,6 +155,7 @@ Cursor.prototype._getRows = function(rows, cb) { } Cursor.prototype.end = function(cb) { + console.log(this.state) if (this.state !== 'initialized') { this.connection.sync() } @@ -177,6 +178,7 @@ Cursor.prototype.close = function(cb) { } Cursor.prototype.read = function(rows, cb) { + console.log('state', this.state) if (this.state === 'idle') { return this._getRows(rows, cb) } diff --git a/package.json b/package.json index 941853c71..233f3e1a3 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,6 @@ "devDependencies": { "eslint": "^6.5.1", "eslint-config-prettier": "^6.4.0", - "eslint-plugin-import": "^2.7.0", "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", "pg": "^7.12.1", diff --git a/test/close.js b/test/close.js index e9b4009b5..a1226be01 100644 --- a/test/close.js +++ b/test/close.js @@ -1,17 +1,17 @@ -var assert = require('assert') -var Cursor = require('../') -var pg = require('pg') +const assert = require('assert') +const Cursor = require('../') +const pg = require('pg') -var text = 'SELECT generate_series as num FROM generate_series(0, 50)' +const text = 'SELECT generate_series as num FROM generate_series(0, 50)' describe('close', function() { beforeEach(function(done) { - var client = (this.client = new pg.Client()) + const client = (this.client = new pg.Client()) client.connect(done) client.on('drain', client.end.bind(client)) }) it('closes cursor early', function(done) { - var cursor = new Cursor(text) + const cursor = new Cursor(text) this.client.query(cursor) this.client.query('SELECT NOW()', done) cursor.read(25, function(err) { @@ -21,8 +21,8 @@ describe('close', function() { }) it('works with callback style', function(done) { - var cursor = new Cursor(text) - var client = this.client + const cursor = new Cursor(text) + const client = this.client client.query(cursor) cursor.read(25, function(err) { assert.ifError(err) diff --git a/test/error-handling.js b/test/error-handling.js index 4b2ea5009..e559d9090 100644 --- a/test/error-handling.js +++ b/test/error-handling.js @@ -1,15 +1,15 @@ 'use strict' -var assert = require('assert') -var Cursor = require('../') -var pg = require('pg') +const assert = require('assert') +const Cursor = require('../') +const pg = require('pg') -var text = 'SELECT generate_series as num FROM generate_series(0, 4)' +const text = 'SELECT generate_series as num FROM generate_series(0, 4)' describe('error handling', function() { it('can continue after error', function(done) { - var client = new pg.Client() + const client = new pg.Client() client.connect() - var cursor = client.query(new Cursor('asdfdffsdf')) + const cursor = client.query(new Cursor('asdfdffsdf')) cursor.read(1, function(err) { assert(err) client.query('SELECT NOW()', function(err) { @@ -23,9 +23,9 @@ describe('error handling', function() { describe('read callback does not fire sync', () => { it('does not fire error callback sync', done => { - var client = new pg.Client() + const client = new pg.Client() client.connect() - var cursor = client.query(new Cursor('asdfdffsdf')) + const cursor = client.query(new Cursor('asdfdffsdf')) let after = false cursor.read(1, function(err) { assert(err, 'error should be returned') @@ -43,9 +43,9 @@ describe('read callback does not fire sync', () => { }) it('does not fire result sync after finished', done => { - var client = new pg.Client() + const client = new pg.Client() client.connect() - var cursor = client.query(new Cursor('SELECT NOW()')) + const cursor = client.query(new Cursor('SELECT NOW()')) let after = false cursor.read(1, function(err) { assert(!err) @@ -68,13 +68,13 @@ describe('read callback does not fire sync', () => { describe('proper cleanup', function() { it('can issue multiple cursors on one client', function(done) { - var client = new pg.Client() + const client = new pg.Client() client.connect() - var cursor1 = client.query(new Cursor(text)) + const cursor1 = client.query(new Cursor(text)) cursor1.read(8, function(err, rows) { assert.ifError(err) assert.equal(rows.length, 5) - var cursor2 = client.query(new Cursor(text)) + const cursor2 = client.query(new Cursor(text)) cursor2.read(8, function(err, rows) { assert.ifError(err) assert.equal(rows.length, 5) diff --git a/test/index.js b/test/index.js index 884edc250..81c3703f5 100644 --- a/test/index.js +++ b/test/index.js @@ -1,16 +1,15 @@ -var assert = require('assert') -var Cursor = require('../') -var pg = require('pg') +const assert = require('assert') +const Cursor = require('../') +const pg = require('pg') -var text = 'SELECT generate_series as num FROM generate_series(0, 5)' +const text = 'SELECT generate_series as num FROM generate_series(0, 5)' describe('cursor', function() { beforeEach(function(done) { - var client = (this.client = new pg.Client()) + const client = (this.client = new pg.Client()) client.connect(done) this.pgCursor = function(text, values) { - client.on('drain', client.end.bind(client)) return client.query(new Cursor(text, values || [])) } }) @@ -20,7 +19,7 @@ describe('cursor', function() { }) it('fetch 6 when asking for 10', function(done) { - var cursor = this.pgCursor(text) + const cursor = this.pgCursor(text) cursor.read(10, function(err, res) { assert.ifError(err) assert.equal(res.length, 6) @@ -28,8 +27,8 @@ describe('cursor', function() { }) }) - it('end before reading to end', function(done) { - var cursor = this.pgCursor(text) + it.only('end before reading to end', function(done) { + const cursor = this.pgCursor(text) cursor.read(3, function(err, res) { assert.ifError(err) assert.equal(res.length, 3) @@ -38,7 +37,7 @@ describe('cursor', function() { }) it('callback with error', function(done) { - var cursor = this.pgCursor('select asdfasdf') + const cursor = this.pgCursor('select asdfasdf') cursor.read(1, function(err) { assert(err) done() @@ -46,7 +45,7 @@ describe('cursor', function() { }) it('read a partial chunk of data', function(done) { - var cursor = this.pgCursor(text) + const cursor = this.pgCursor(text) cursor.read(2, function(err, res) { assert.ifError(err) assert.equal(res.length, 2) @@ -68,7 +67,7 @@ describe('cursor', function() { }) it('read return length 0 past the end', function(done) { - var cursor = this.pgCursor(text) + const cursor = this.pgCursor(text) cursor.read(2, function(err) { assert(!err) cursor.read(100, function(err, res) { @@ -85,11 +84,11 @@ describe('cursor', function() { it('read huge result', function(done) { this.timeout(10000) - var text = 'SELECT generate_series as num FROM generate_series(0, 100000)' - var values = [] - var cursor = this.pgCursor(text, values) - var count = 0 - var read = function() { + const text = 'SELECT generate_series as num FROM generate_series(0, 100000)' + const values = [] + const cursor = this.pgCursor(text, values) + let count = 0 + const read = function() { cursor.read(100, function(err, rows) { if (err) return done(err) if (!rows.length) { @@ -107,9 +106,9 @@ describe('cursor', function() { }) it('normalizes parameter values', function(done) { - var text = 'SELECT $1::json me' - var values = [{ name: 'brian' }] - var cursor = this.pgCursor(text, values) + const text = 'SELECT $1::json me' + const values = [{ name: 'brian' }] + const cursor = this.pgCursor(text, values) cursor.read(1, function(err, rows) { if (err) return done(err) assert.equal(rows[0].me.name, 'brian') @@ -122,7 +121,7 @@ describe('cursor', function() { }) it('returns result along with rows', function(done) { - var cursor = this.pgCursor(text) + const cursor = this.pgCursor(text) cursor.read(1, function(err, rows, result) { assert.ifError(err) assert.equal(rows.length, 1) @@ -133,7 +132,7 @@ describe('cursor', function() { }) it('emits row events', function(done) { - var cursor = this.pgCursor(text) + const cursor = this.pgCursor(text) cursor.read(10) cursor.on('row', (row, result) => result.addRow(row)) cursor.on('end', result => { @@ -143,7 +142,7 @@ describe('cursor', function() { }) it('emits row events when cursor is closed manually', function(done) { - var cursor = this.pgCursor(text) + const cursor = this.pgCursor(text) cursor.on('row', (row, result) => result.addRow(row)) cursor.on('end', result => { assert.equal(result.rows.length, 3) @@ -154,7 +153,7 @@ describe('cursor', function() { }) it('emits error events', function(done) { - var cursor = this.pgCursor('select asdfasdf') + const cursor = this.pgCursor('select asdfasdf') cursor.on('error', function(err) { assert(err) done() @@ -162,11 +161,11 @@ describe('cursor', function() { }) it('returns rowCount on insert', function(done) { - var pgCursor = this.pgCursor + const pgCursor = this.pgCursor this.client .query('CREATE TEMPORARY TABLE pg_cursor_test (foo VARCHAR(1), bar VARCHAR(1))') .then(function() { - var cursor = pgCursor('insert into pg_cursor_test values($1, $2)', ['a', 'b']) + const cursor = pgCursor('insert into pg_cursor_test values($1, $2)', ['a', 'b']) cursor.read(1, function(err, rows, result) { assert.ifError(err) assert.equal(rows.length, 0) diff --git a/test/no-data-handling.js b/test/no-data-handling.js index 7c653e718..ab2ed3f6a 100644 --- a/test/no-data-handling.js +++ b/test/no-data-handling.js @@ -1,10 +1,10 @@ -var assert = require('assert') -var pg = require('pg') -var Cursor = require('../') +const assert = require('assert') +const pg = require('pg') +const Cursor = require('../') describe('queries with no data', function() { beforeEach(function(done) { - var client = (this.client = new pg.Client()) + const client = (this.client = new pg.Client()) client.connect(done) }) @@ -13,7 +13,7 @@ describe('queries with no data', function() { }) it('handles queries that return no data', function(done) { - var cursor = new Cursor('CREATE TEMPORARY TABLE whatwhat (thing int)') + const cursor = new Cursor('CREATE TEMPORARY TABLE whatwhat (thing int)') this.client.query(cursor) cursor.read(100, function(err, rows) { assert.ifError(err) @@ -23,7 +23,7 @@ describe('queries with no data', function() { }) it('handles empty query', function(done) { - var cursor = new Cursor('-- this is a comment') + let cursor = new Cursor('-- this is a comment') cursor = this.client.query(cursor) cursor.read(100, function(err, rows) { assert.ifError(err) diff --git a/yarn.lock b/yarn.lock index fedde16d3..63b1a42b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4,15 +4,15 @@ "@babel/code-frame@^7.0.0": version "7.5.5" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" - integrity sha1-vAeC9tafe31JUxIZaZuYj2aaj50= + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== dependencies: "@babel/highlight" "^7.0.0" "@babel/highlight@^7.0.0": version "7.5.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha1-VtETEr2SSPphlZHQJHK+boyzJUA= + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== dependencies: chalk "^2.0.0" esutils "^2.0.2" @@ -20,18 +20,18 @@ acorn-jsx@^5.1.0: version "5.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" - integrity sha1-KUrbcbVzmLBoABXwo4xWPuHbU4Q= + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" + integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== acorn@^7.1.0: version "7.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" - integrity sha1-lJ028sKSU12mAig1hsJHfFfrLWw= + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" + integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== ajv@^6.10.0, ajv@^6.10.2: version "6.10.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" - integrity sha1-086gTWsBeyiUrWkED+yLYj60vVI= + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" + integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== dependencies: fast-deep-equal "^2.0.1" fast-json-stable-stringify "^2.0.0" @@ -40,88 +40,80 @@ ajv@^6.10.0, ajv@^6.10.2: ansi-colors@3.2.3: version "3.2.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" - integrity sha1-V9NbhoboUeLMBMQD8cACA5dqGBM= + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== ansi-escapes@^3.2.0: version "3.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha1-h4C5j/nb9WOBUtHx/lwde0RCl2s= + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== ansi-regex@^3.0.0: version "3.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= ansi-regex@^4.1.0: version "4.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha1-i5+PCM8ay4Q3Vqg5yox+MWjFGZc= + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha1-QfuyAkPlCxK+DwS43tvwdSDOhB0= + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" argparse@^1.0.7: version "1.0.10" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE= + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" -array-includes@^3.0.3: - version "3.0.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" - integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.7.0" - astral-regex@^1.0.0: version "1.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha1-bIw/uCfdQ+45GPJ7gngqt2WKb9k= + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== balanced-match@^1.0.0: version "1.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= brace-expansion@^1.1.7: version "1.1.11" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0= + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== dependencies: balanced-match "^1.0.0" concat-map "0.0.1" browser-stdout@1.3.1: version "1.3.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha1-uqVZ7hTO1zRSIputcyZGfGH6vWA= + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== buffer-writer@2.0.0: version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" - integrity sha1-zn64Gjj3gp2wnIc/L7t5LAyY7AQ= + resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" + integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== callsites@^3.0.0: version "3.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha1-s2MKvYlDQy9Us/BRkjjjPNffL3M= + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camelcase@^5.0.0: version "5.3.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha1-48mzFWnhBoEd8kL3FXJaH0xJQyA= + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.2: version "2.4.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha1-zUJUFnelQzPPVBpJEIwUMrRMlCQ= + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== dependencies: ansi-styles "^3.2.1" escape-string-regexp "^1.0.5" @@ -129,25 +121,25 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.2: chardet@^0.7.0: version "0.7.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha1-kAlISfCTfy7twkJdDSip5fDLrZ4= + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== cli-cursor@^2.1.0: version "2.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= dependencies: restore-cursor "^2.0.0" cli-width@^2.0.0: version "2.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= cliui@^5.0.0: version "5.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha1-3u/P2y6AB4SqNPRvoI4GhRx7u8U= + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== dependencies: string-width "^3.1.0" strip-ansi "^5.2.0" @@ -155,30 +147,25 @@ cliui@^5.0.0: color-convert@^1.9.0: version "1.9.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha1-u3GFBpDh8TZWfeYp0tVHHe2kweg= + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" color-name@1.1.3: version "1.1.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= concat-map@0.0.1: version "0.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -contains-path@^0.1.0: - version "0.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= - cross-spawn@^6.0.5: version "6.0.5" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha1-Sl7Hxk364iw6FBJNus3uhG2Ay8Q= + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== dependencies: nice-try "^1.0.4" path-key "^2.0.1" @@ -188,78 +175,56 @@ cross-spawn@^6.0.5: debug@3.2.6: version "3.2.6" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha1-6D0X3hbYp++3cX7b5fsQE17uYps= + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: ms "^2.1.1" -debug@^2.6.8, debug@^2.6.9: - version "2.6.9" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha1-XRKFFd8TT/Mn6QpMk/Tgd6U2NB8= - dependencies: - ms "2.0.0" - debug@^4.0.1: version "4.1.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E= + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== dependencies: ms "^2.1.1" decamelize@^1.2.0: version "1.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= deep-is@~0.1.3: version "0.1.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= define-properties@^1.1.2, define-properties@^1.1.3: version "1.1.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha1-z4jabL7ib+bbcJT2HYcMvYTO6fE= + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== dependencies: object-keys "^1.0.12" diff@3.5.0: version "3.5.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI= - -doctrine@1.5.0: - version "1.5.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= - dependencies: - esutils "^2.0.2" - isarray "^1.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== doctrine@^3.0.0: version "3.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha1-rd6+rXKmV023g2OdyHoSF3OXOWE= + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== dependencies: esutils "^2.0.2" emoji-regex@^7.0.1: version "7.0.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha1-kzoEBShgyF6DwSJHnEdIqOTHIVY= - -error-ex@^1.2.0: - version "1.3.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - integrity sha1-tKxAZIEH/c3PriQvQovqihTU8b8= - dependencies: - is-arrayish "^0.2.1" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== -es-abstract@^1.12.0, es-abstract@^1.5.1, es-abstract@^1.7.0: +es-abstract@^1.5.1: version "1.16.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" - integrity sha1-06JtycMoOsl1DcpWlYbpdtncwG0= + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" + integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== dependencies: es-to-primitive "^1.2.0" function-bind "^1.1.1" @@ -274,8 +239,8 @@ es-abstract@^1.12.0, es-abstract@^1.5.1, es-abstract@^1.7.0: es-to-primitive@^1.2.0: version "1.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha1-7fckeAM0VujdqO8J4ArZZQcH83c= + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== dependencies: is-callable "^1.1.4" is-date-object "^1.0.1" @@ -283,80 +248,47 @@ es-to-primitive@^1.2.0: escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= eslint-config-prettier@^6.4.0: version "6.4.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-config-prettier/-/eslint-config-prettier-6.4.0.tgz#0a04f147e31d33c6c161b2dd0971418ac52d0477" - integrity sha1-CgTxR+MdM8bBYbLdCXFBisUtBHc= + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.4.0.tgz#0a04f147e31d33c6c161b2dd0971418ac52d0477" + integrity sha512-YrKucoFdc7SEko5Sxe4r6ixqXPDP1tunGw91POeZTTRKItf/AMFYt/YLEQtZMkR2LVpAVhcAcZgcWpm1oGPW7w== dependencies: get-stdin "^6.0.0" -eslint-import-resolver-node@^0.3.2: - version "0.3.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" - integrity sha1-WPFfuDm40FdsqYBBNHaqskcttmo= - dependencies: - debug "^2.6.9" - resolve "^1.5.0" - -eslint-module-utils@^2.4.0: - version "2.4.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz#7b4675875bf96b0dbf1b21977456e5bb1f5e018c" - integrity sha1-e0Z1h1v5aw2/GyGXdFblux9eAYw= - dependencies: - debug "^2.6.8" - pkg-dir "^2.0.0" - -eslint-plugin-import@^2.7.0: - version "2.18.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz#02f1180b90b077b33d447a17a2326ceb400aceb6" - integrity sha1-AvEYC5Cwd7M9RHoXojJs60AKzrY= - dependencies: - array-includes "^3.0.3" - contains-path "^0.1.0" - debug "^2.6.9" - doctrine "1.5.0" - eslint-import-resolver-node "^0.3.2" - eslint-module-utils "^2.4.0" - has "^1.0.3" - minimatch "^3.0.4" - object.values "^1.1.0" - read-pkg-up "^2.0.0" - resolve "^1.11.0" - eslint-plugin-prettier@^3.1.1: version "3.1.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.1.tgz#507b8562410d02a03f0ddc949c616f877852f2ba" - integrity sha1-UHuFYkENAqA/DdyUnGFvh3hS8ro= + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.1.tgz#507b8562410d02a03f0ddc949c616f877852f2ba" + integrity sha512-A+TZuHZ0KU0cnn56/9mfR7/KjUJ9QNVXUhwvRFSR7PGPe0zQR6PTkmyqg1AtUUEOzTqeRsUwyKFh0oVZKVCrtA== dependencies: prettier-linter-helpers "^1.0.0" eslint-scope@^5.0.0: version "5.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" - integrity sha1-6HyIh8c+jR7ITxylkWRcNYv8j7k= + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" + integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" eslint-utils@^1.4.2: version "1.4.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha1-dP7HxU0Hdrb2fgJRBAtYBlZOmB8= + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== dependencies: eslint-visitor-keys "^1.1.0" eslint-visitor-keys@^1.1.0: version "1.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha1-4qgs6oT/JGrW+1f5veW0ZiFFnsI= + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== eslint@^6.5.1: version "6.5.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint/-/eslint-6.5.1.tgz#828e4c469697d43bb586144be152198b91e96ed6" - integrity sha1-go5MRpaX1Du1hhRL4VIZi5HpbtY= + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.5.1.tgz#828e4c469697d43bb586144be152198b91e96ed6" + integrity sha512-32h99BoLYStT1iq1v2P9uwpyznQ4M2jRiFB6acitKz52Gqn+vPaMDUTB1bYi1WN4Nquj2w+t+bimYUG83DC55A== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -398,8 +330,8 @@ eslint@^6.5.1: espree@^6.1.1: version "6.1.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" - integrity sha1-bCcmUJMrT5HDcU5ee19eLs9HJi0= + resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" + integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== dependencies: acorn "^7.1.0" acorn-jsx "^5.1.0" @@ -407,37 +339,37 @@ espree@^6.1.1: esprima@^4.0.0: version "4.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha1-E7BM2z5sXRnfkatph6hpVhmwqnE= + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.0.1: version "1.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha1-QGxRZYsfWZGl+bYrHcJbAOPlxwg= + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== dependencies: estraverse "^4.0.0" esrecurse@^4.1.0: version "4.2.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha1-AHo7n9vCs7uH5IeeoZyS/b05Qs8= + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== dependencies: estraverse "^4.1.0" estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: version "4.3.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha1-OYrT88WiSUi+dyXoPRGn3ijNvR0= + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== esutils@^2.0.2: version "2.0.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha1-dNLrTeC42hKTcRkQ1Qd1ubcQ72Q= + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== external-editor@^3.0.3: version "3.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha1-ywP3QL764D6k0oPK7SdBqD8zVJU= + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== dependencies: chardet "^0.7.0" iconv-lite "^0.4.24" @@ -445,56 +377,49 @@ external-editor@^3.0.3: fast-deep-equal@^2.0.1: version "2.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= fast-diff@^1.1.2: version "1.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha1-c+4RmC2Gyq95WYKNUZz+kn+sXwM= + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== fast-json-stable-stringify@^2.0.0: version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= fast-levenshtein@~2.0.4: version "2.0.6" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= figures@^2.0.0: version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= dependencies: escape-string-regexp "^1.0.5" file-entry-cache@^5.0.1: version "5.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha1-yg9u+m3T1WEzP7FFFQZcL6/fQ5w= + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== dependencies: flat-cache "^2.0.1" find-up@3.0.0, find-up@^3.0.0: version "3.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha1-SRafHXmTQwZG2mHsxa41XCHJe3M= + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== dependencies: locate-path "^3.0.0" -find-up@^2.0.0, find-up@^2.1.0: - version "2.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= - dependencies: - locate-path "^2.0.0" - flat-cache@^2.0.1: version "2.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha1-XSltbwS9pEpGMKMBQTvbwuwIXsA= + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== dependencies: flatted "^2.0.0" rimraf "2.6.3" @@ -502,52 +427,52 @@ flat-cache@^2.0.1: flat@^4.1.0: version "4.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" - integrity sha1-CQvsiwXjnLowl0fx1YjwTbr5jbI= + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" + integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== dependencies: is-buffer "~2.0.3" flatted@^2.0.0: version "2.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" - integrity sha1-aeV8qo8OrLwoHS4stFjUb9tEngg= + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" + integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== fs.realpath@^1.0.0: version "1.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= function-bind@^1.1.1: version "1.1.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha1-pWiZ0+o8m6uHS7l3O3xe3pL0iV0= + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== functional-red-black-tree@^1.0.1: version "1.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= get-caller-file@^2.0.1: version "2.0.5" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha1-T5RBKoLbMvNuOwuXQfipf+sDH34= + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== get-stdin@^6.0.0: version "6.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha1-ngm/cSs2CrkiXoEgSPcf3pyJZXs= + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== glob-parent@^5.0.0: version "5.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" - integrity sha1-X0wdHnSNMM1zrSlEs1d6gbCB6MI= + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" + integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== dependencies: is-glob "^4.0.1" glob@7.1.3: version "7.1.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha1-OWCDLT8VdBCDQtr9OmezMsCWnfE= + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -558,8 +483,8 @@ glob@7.1.3: glob@^7.1.3: version "7.1.5" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/glob/-/glob-7.1.5.tgz#6714c69bee20f3c3e64c4dd905553e532b40cdc0" - integrity sha1-ZxTGm+4g88PmTE3ZBVU+UytAzcA= + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.5.tgz#6714c69bee20f3c3e64c4dd905553e532b40cdc0" + integrity sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -570,74 +495,64 @@ glob@^7.1.3: globals@^11.7.0: version "11.12.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha1-q4eVM4hooLq9hSV1gBjCp+uVxC4= - -graceful-fs@^4.1.2: - version "4.2.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" - integrity sha1-ShL/G2A3bvCYYsIJPt2Qgyi+hCM= + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== growl@1.10.5: version "1.10.5" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha1-8nNdwig2dPpnR4sQGBBZNVw2nl4= + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== has-flag@^3.0.0: version "3.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-symbols@^1.0.0: version "1.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= has@^1.0.1, has@^1.0.3: version "1.0.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha1-ci18v8H2qoJB8W3YFOAR4fQeh5Y= + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== dependencies: function-bind "^1.1.1" he@1.2.0: version "1.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha1-hK5l+n6vsWX922FWauFLrwVmTw8= - -hosted-git-info@^2.1.4: - version "2.8.5" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" - integrity sha1-dZz88sTRVq3lmwst+r3cQqa5xww= + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== iconv-lite@^0.4.24: version "0.4.24" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha1-ICK0sl+93CHS9SSXSkdKr+czkIs= + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" ignore@^4.0.6: version "4.0.6" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha1-dQ49tYYgh7RzfrrIIH/9HvJ7Jfw= + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== import-fresh@^3.0.0: version "3.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" - integrity sha1-bTP6Hc7235MPrgA0RvM0Fa+QURg= + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" + integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" imurmurhash@^0.1.4: version "0.1.4" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= inflight@^1.0.4: version "1.0.6" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" @@ -645,13 +560,13 @@ inflight@^1.0.4: inherits@2: version "2.0.4" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w= + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== inquirer@^6.4.1: version "6.5.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" - integrity sha1-rVCUI3XQNtMn/1KMCL1fqwiZKMo= + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== dependencies: ansi-escapes "^3.2.0" chalk "^2.4.2" @@ -667,169 +582,141 @@ inquirer@^6.4.1: strip-ansi "^5.1.0" through "^2.3.6" -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - is-buffer@~2.0.3: version "2.0.4" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" - integrity sha1-PlcvI8hBGlz9lVfISeNmXgspBiM= + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== is-callable@^1.1.4: version "1.1.4" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha1-HhrfIZ4e62hNaR+dagX/DTCiTXU= + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== is-date-object@^1.0.1: version "1.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= is-extglob@^2.1.1: version "2.1.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-fullwidth-code-point@^2.0.0: version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= is-glob@^4.0.0, is-glob@^4.0.1: version "4.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha1-dWfb6fL14kZ7x3q4PEopSCQHpdw= + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== dependencies: is-extglob "^2.1.1" is-promise@^2.1.0: version "2.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= is-regex@^1.0.4: version "1.0.4" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= dependencies: has "^1.0.1" is-symbol@^1.0.2: version "1.0.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha1-oFX2rlcZLK7jKeeoYBGLSXqVDzg= + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== dependencies: has-symbols "^1.0.0" -isarray@^1.0.0: - version "1.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - isexe@^2.0.0: version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= js-tokens@^4.0.0: version "4.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha1-GSA/tZmR35jjoocFDUZHzerzJJk= + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== js-yaml@3.13.1, js-yaml@^3.13.1: version "3.13.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha1-r/FRswv9+o5J4F2iLnQV6d+jeEc= + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== dependencies: argparse "^1.0.7" esprima "^4.0.0" json-schema-traverse@^0.4.1: version "0.4.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha1-afaofZUTq4u4/mO9sJecRI5oRmA= + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= levn@^0.3.0, levn@~0.3.0: version "0.3.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= dependencies: prelude-ls "~1.1.2" type-check "~0.3.2" -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.0.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - locate-path@^3.0.0: version "3.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha1-2+w7OrdZdYBxtY/ln8QYca8hQA4= + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== dependencies: p-locate "^3.0.0" path-exists "^3.0.0" lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15: version "4.17.15" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg= + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== log-symbols@2.2.0: version "2.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo= + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== dependencies: chalk "^2.0.1" mimic-fn@^1.0.0: version "1.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha1-ggyGo5M0ZA6ZUWkovQP8qIBX0CI= + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM= + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== dependencies: brace-expansion "^1.1.7" minimist@0.0.8: version "0.0.8" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= mkdirp@0.5.1, mkdirp@^0.5.1: version "0.5.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" mocha@^6.2.2: version "6.2.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" - integrity sha1-XYmH4olAyviVen12ZLkQ3Fsv6iA= + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" + integrity sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A== dependencies: ansi-colors "3.2.3" browser-stdout "1.3.1" @@ -855,68 +742,53 @@ mocha@^6.2.2: yargs-parser "13.1.1" yargs-unparser "1.6.0" -ms@2.0.0: - version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - ms@2.1.1: version "2.1.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo= + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== ms@^2.1.1: version "2.1.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk= + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== mute-stream@0.0.7: version "0.0.7" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= natural-compare@^1.4.0: version "1.4.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= nice-try@^1.0.4: version "1.0.5" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha1-ozeKdpbOfSI+iPybdkvX7xCJ42Y= + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== node-environment-flags@1.0.5: version "1.0.5" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" - integrity sha1-+pMCdfW/Xa4YjWGSsktMi7rD12o= + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== dependencies: object.getownpropertydescriptors "^2.0.3" semver "^5.7.0" -normalize-package-data@^2.3.2: - version "2.5.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" - integrity sha1-5m2xg4sgDB38IzIl0SyzZSDiNKg= - dependencies: - hosted-git-info "^2.1.4" - resolve "^1.10.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - object-inspect@^1.6.0: version "1.6.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - integrity sha1-xwtsv3LydKq0w0wMgvUWe/gs8Vs= + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha1-HEfyct8nfzsdrwYWd9nILiMixg4= + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object.assign@4.1.0: version "4.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha1-lovxEA15Vrs8oIbwBvhGs7xACNo= + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== dependencies: define-properties "^1.1.2" function-bind "^1.1.1" @@ -925,39 +797,29 @@ object.assign@4.1.0: object.getownpropertydescriptors@^2.0.3: version "2.0.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= dependencies: define-properties "^1.1.2" es-abstract "^1.5.1" -object.values@^1.1.0: - version "1.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" - integrity sha1-v2gQ712j5TJXkOqqK+IT6oRiTak= - dependencies: - define-properties "^1.1.3" - es-abstract "^1.12.0" - function-bind "^1.1.1" - has "^1.0.3" - once@^1.3.0: version "1.4.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= dependencies: wrappy "1" onetime@^2.0.0: version "2.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= dependencies: mimic-fn "^1.0.0" optionator@^0.8.2: version "0.8.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= dependencies: deep-is "~0.1.3" @@ -969,112 +831,74 @@ optionator@^0.8.2: os-tmpdir@~1.0.2: version "1.0.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -p-limit@^1.1.0: - version "1.3.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha1-uGvV8MJWkJEcdZD8v8IBDVSzzLg= - dependencies: - p-try "^1.0.0" - p-limit@^2.0.0: version "2.2.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha1-qgeniMwxUck5tRMfY1cPDdIAlTc= + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== dependencies: p-try "^2.0.0" -p-locate@^2.0.0: - version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= - dependencies: - p-limit "^1.1.0" - p-locate@^3.0.0: version "3.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha1-Mi1poFwCZLJZl9n0DNiokasAZKQ= + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== dependencies: p-limit "^2.0.0" -p-try@^1.0.0: - version "1.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= - p-try@^2.0.0: version "2.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha1-yyhoVA4xPWHeWPr741zpAE1VQOY= + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== packet-reader@1.0.0: version "1.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" - integrity sha1-kjjlSA3tq6z+H+PydxBj8WQVfXQ= + resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" + integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== parent-module@^1.0.0: version "1.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha1-aR0nCeeMefrjoVZiJFLQB2LKqqI= + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== dependencies: callsites "^3.0.0" -parse-json@^2.2.0: - version "2.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= - dependencies: - error-ex "^1.2.0" - path-exists@^3.0.0: version "3.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= path-is-absolute@^1.0.0: version "1.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= path-key@^2.0.1: version "2.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= -path-parse@^1.0.6: - version "1.0.6" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha1-1i27VnlAXXLEc37FhgDp3c8G0kw= - -path-type@^2.0.0: - version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= - dependencies: - pify "^2.0.0" - pg-connection-string@0.1.3: version "0.1.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc= pg-int8@1.0.1: version "1.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" - integrity sha1-lDvUY79bcbQXARX4D478mgwOt4w= + resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" + integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== pg-pool@^2.0.4: version "2.0.7" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pg-pool/-/pg-pool-2.0.7.tgz#f14ecab83507941062c313df23f6adcd9fd0ce54" - integrity sha1-8U7KuDUHlBBiwxPfI/atzZ/QzlQ= + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.7.tgz#f14ecab83507941062c313df23f6adcd9fd0ce54" + integrity sha512-UiJyO5B9zZpu32GSlP0tXy8J2NsJ9EFGFfz5v6PSbdz/1hBLX1rNiiy5+mAm5iJJYwfCv4A0EBcQLGWwjbpzZw== pg-types@^2.1.0: version "2.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" - integrity sha1-LQJQ1jZFT3z6O2rgOC/fqAYyVKM= + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" + integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== dependencies: pg-int8 "1.0.1" postgres-array "~2.0.0" @@ -1084,8 +908,8 @@ pg-types@^2.1.0: pg@^7.12.1: version "7.12.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pg/-/pg-7.12.1.tgz#880636d46d2efbe0968e64e9fe0eeece8ef72a7e" - integrity sha1-iAY21G0u++CWjmTp/g7uzo73Kn4= + resolved "https://registry.yarnpkg.com/pg/-/pg-7.12.1.tgz#880636d46d2efbe0968e64e9fe0eeece8ef72a7e" + integrity sha512-l1UuyfEvoswYfcUe6k+JaxiN+5vkOgYcVSbSuw3FvdLqDbaoa2RJo1zfJKfPsSYPFVERd4GHvX3s2PjG1asSDA== dependencies: buffer-writer "2.0.0" packet-reader "1.0.0" @@ -1097,119 +921,83 @@ pg@^7.12.1: pgpass@1.x: version "1.0.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY= dependencies: split "^1.0.0" -pify@^2.0.0: - version "2.3.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= - -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= - dependencies: - find-up "^2.1.0" - postgres-array@~2.0.0: version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" - integrity sha1-SPj84FT7xpZxmZMpuINLdyZS2C4= + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" + integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== postgres-bytea@~1.0.0: version "1.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU= postgres-date@~1.0.4: version "1.0.4" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/postgres-date/-/postgres-date-1.0.4.tgz#1c2728d62ef1bff49abdd35c1f86d4bdf118a728" - integrity sha1-HCco1i7xv/SavdNcH4bUvfEYpyg= + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.4.tgz#1c2728d62ef1bff49abdd35c1f86d4bdf118a728" + integrity sha512-bESRvKVuTrjoBluEcpv2346+6kgB7UlnqWZsnbnCccTNq/pqfj1j6oBaN5+b/NrDXepYUT/HKadqv3iS9lJuVA== postgres-interval@^1.1.0: version "1.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" - integrity sha1-tGDILLFYdQd4iBmgaqD//bNURpU= + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" + integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== dependencies: xtend "^4.0.0" prelude-ls@~1.1.2: version "1.1.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= prettier-linter-helpers@^1.0.0: version "1.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha1-0j1B/hN1ZG3i0BBNNFSjAIgCz3s= + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== dependencies: fast-diff "^1.1.2" prettier@^1.18.2: version "1.18.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" - integrity sha1-aCPnxZAAF7S9Os9G/prEtNe9qeo= + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" + integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== progress@^2.0.0: version "2.0.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha1-foz42PW48jnBvGi+tOt4Vn1XLvg= + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== punycode@^2.1.0: version "2.1.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha1-tYsBCsQMIsVldhbI0sLALHv0eew= - -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= - dependencies: - find-up "^2.0.0" - read-pkg "^2.0.0" - -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== regexpp@^2.0.1: version "2.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha1-jRnTHPYySCtYkEn4KB+T28uk0H8= + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== require-directory@^2.1.1: version "2.1.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= require-main-filename@^2.0.0: version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha1-0LMp7MfMD2Fkn2IhW+aa9UqomJs= + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== resolve-from@^4.0.0: version "4.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha1-SrzYUq0y3Xuqv+m0DgCjbbXzkuY= - -resolve@^1.10.0, resolve@^1.11.0, resolve@^1.5.0: - version "1.12.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/resolve/-/resolve-1.12.0.tgz#3fc644a35c84a48554609ff26ec52b66fa577df6" - integrity sha1-P8ZEo1yEpIVUYJ/ybsUrZvpXffY= - dependencies: - path-parse "^1.0.6" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== restore-cursor@^2.0.0: version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= dependencies: onetime "^2.0.0" @@ -1217,126 +1005,100 @@ restore-cursor@^2.0.0: rimraf@2.6.3: version "2.6.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha1-stEE/g2Psnz54KHNqCYt04M8bKs= + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: glob "^7.1.3" run-async@^2.2.0: version "2.3.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= dependencies: is-promise "^2.1.0" rxjs@^6.4.0: version "6.5.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" - integrity sha1-UQ4mMX9NuRp+sd532d2boKSJmjo= + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" + integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== dependencies: tslib "^1.9.0" "safer-buffer@>= 2.1.2 < 3": version "2.1.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo= - -"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.7.0: - version "5.7.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha1-qVT5Ma66UI0we78Gnv8MAclhFvc= + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== semver@4.3.2: version "4.3.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= +semver@^5.5.0, semver@^5.7.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + semver@^6.1.2: version "6.3.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha1-7gpkyK9ejO6mdoexM3YeG+y9HT0= + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== set-blocking@^2.0.0: version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= shebang-command@^1.2.0: version "1.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= signal-exit@^3.0.2: version "3.0.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= slice-ansi@^2.1.0: version "2.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha1-ys12k0YaY3pXiNkqfdT7oGjoFjY= + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== dependencies: ansi-styles "^3.2.0" astral-regex "^1.0.0" is-fullwidth-code-point "^2.0.0" -spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha1-+4PlBERSaPFUsHTiGMh8ADzTHfQ= - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha1-LqRQrudPKom/uUUZwH/Nb0EyKXc= - -spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha1-meEZt6XaAOBUkcn6M4t5BII7QdA= - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha1-NpS1gEVnpFjTyARYQqY1hjL2JlQ= - split@^1.0.0: version "1.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - integrity sha1-YFvZvjA6pZ+zX5Ip++oN3snqB9k= + resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" + integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== dependencies: through "2" sprintf-js@~1.0.2: version "1.0.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= "string-width@^1.0.2 || 2", string-width@^2.1.0: version "2.1.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4= + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" string-width@^3.0.0, string-width@^3.1.0: version "3.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha1-InZ74htirxCBV0MG9prFG2IgOWE= + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== dependencies: emoji-regex "^7.0.1" is-fullwidth-code-point "^2.0.0" @@ -1344,67 +1106,62 @@ string-width@^3.0.0, string-width@^3.1.0: string.prototype.trimleft@^2.1.0: version "2.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" - integrity sha1-bMR/DX641isPNwFhFxWjlUWR1jQ= + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" + integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== dependencies: define-properties "^1.1.3" function-bind "^1.1.1" string.prototype.trimright@^2.1.0: version "2.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" - integrity sha1-Zp0WS+nfm291WfqOiZRbFopabFg= + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" + integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== dependencies: define-properties "^1.1.3" function-bind "^1.1.1" strip-ansi@^4.0.0: version "4.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= dependencies: ansi-regex "^3.0.0" strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: version "5.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha1-jJpTb+tq/JYr36WxBKUJHBrZwK4= + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== dependencies: ansi-regex "^4.1.0" -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= - strip-json-comments@2.0.1: version "2.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= strip-json-comments@^3.0.1: version "3.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" - integrity sha1-hXE5dakfuHvxswXMp3OV5A0qZKc= + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== supports-color@6.0.0: version "6.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" - integrity sha1-ds/nQs8fQbubHCmtAwaMBbTA5Ao= + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== dependencies: has-flag "^3.0.0" supports-color@^5.3.0: version "5.5.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha1-4uaaRKyHcveKHsCzW2id9lMO/I8= + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" table@^5.2.3: version "5.4.6" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha1-EpLRlQDOP4YFOwXw6Ofko7shB54= + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== dependencies: ajv "^6.10.2" lodash "^4.17.14" @@ -1413,81 +1170,73 @@ table@^5.2.3: text-table@^0.2.0: version "0.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= through@2, through@^2.3.6: version "2.3.8" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= tmp@^0.0.33: version "0.0.33" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha1-bTQzWIl2jSGyvNoKonfO07G/rfk= + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== dependencies: os-tmpdir "~1.0.2" tslib@^1.9.0: version "1.10.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" - integrity sha1-w8GflZc/sKYpc/sJ2Q2WHuQ+XIo= + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== type-check@~0.3.2: version "0.3.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= dependencies: prelude-ls "~1.1.2" uri-js@^4.2.2: version "4.2.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha1-lMVA4f93KVbiKZUHwBCupsiDjrA= + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== dependencies: punycode "^2.1.0" v8-compile-cache@^2.0.3: version "2.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" - integrity sha1-4U3jezGm0ZT1aQ1n78Tn9vxqsw4= - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - integrity sha1-/JH2uce6FchX9MssXe/uw51PQQo= - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" + integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== which-module@^2.0.0: version "2.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= which@1.3.1, which@^1.2.9: version "1.3.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha1-pFBD1U9YBTFtqNYvn1CRjT2nCwo= + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" wide-align@1.1.3: version "1.1.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha1-rgdOa9wMFKQx6ATmJFScYzsABFc= + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: string-width "^1.0.2 || 2" wordwrap@~1.0.0: version "1.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= wrap-ansi@^5.1.0: version "5.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha1-H9H2cjXVttD+54EFYAG/tpTAOwk= + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== dependencies: ansi-styles "^3.2.0" string-width "^3.0.0" @@ -1495,38 +1244,38 @@ wrap-ansi@^5.1.0: wrappy@1: version "1.0.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= write@1.0.3: version "1.0.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha1-CADhRSO5I6OH5BUSPIZWFqrg9cM= + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== dependencies: mkdirp "^0.5.1" xtend@^4.0.0: version "4.0.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha1-u3J3n1+kZRhrH0OPZ0+jR/2121Q= + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== y18n@^4.0.0: version "4.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha1-le+U+F7MgdAHwmThkKEg8KPIVms= + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== yargs-parser@13.1.1, yargs-parser@^13.1.1: version "13.1.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha1-0mBYUyqgbTZf4JH2ofwGsvfl7KA= + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" yargs-unparser@1.6.0: version "1.6.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" - integrity sha1-7yXCx2n/a9CeSw+dfGBfsnhG6p8= + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== dependencies: flat "^4.1.0" lodash "^4.17.15" @@ -1534,8 +1283,8 @@ yargs-unparser@1.6.0: yargs@13.3.0, yargs@^13.3.0: version "13.3.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha1-TGV6VeB+Xyz5R/ijZlZ8BKDe3IM= + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== dependencies: cliui "^5.0.0" find-up "^3.0.0" From be0321299bc53542f41754275f6ea2164f5435f5 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 25 Oct 2019 18:11:53 -0500 Subject: [PATCH 0497/1037] Update lint, fix for pg@7.x --- index.js | 4 +--- package.json | 4 ++-- test/index.js | 4 ++-- yarn.lock | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/index.js b/index.js index 202cd9b6a..8136c389c 100644 --- a/index.js +++ b/index.js @@ -15,7 +15,7 @@ function Cursor(text, values, config) { this.connection = null this._queue = [] this.state = 'initialized' - this._result = new Result(this._conf.rowMode) + this._result = new Result(this._conf.rowMode, this._conf.types) this._cb = null this._rows = null this._portal = null @@ -155,7 +155,6 @@ Cursor.prototype._getRows = function(rows, cb) { } Cursor.prototype.end = function(cb) { - console.log(this.state) if (this.state !== 'initialized') { this.connection.sync() } @@ -178,7 +177,6 @@ Cursor.prototype.close = function(cb) { } Cursor.prototype.read = function(rows, cb) { - console.log('state', this.state) if (this.state === 'idle') { return this._getRows(rows, cb) } diff --git a/package.json b/package.json index 233f3e1a3..e35309723 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pg-cursor", "version": "2.0.0", - "description": "", + "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { "test": "test" @@ -20,7 +20,7 @@ "eslint-config-prettier": "^6.4.0", "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "^7.12.1", + "pg": "7.x", "prettier": "^1.18.2" }, "prettier": { diff --git a/test/index.js b/test/index.js index 81c3703f5..0f41f882a 100644 --- a/test/index.js +++ b/test/index.js @@ -27,12 +27,12 @@ describe('cursor', function() { }) }) - it.only('end before reading to end', function(done) { + it('end before reading to end', function(done) { const cursor = this.pgCursor(text) cursor.read(3, function(err, res) { assert.ifError(err) assert.equal(res.length, 3) - cursor.end(done) + done() }) }) diff --git a/yarn.lock b/yarn.lock index 63b1a42b2..51b9a87f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -906,7 +906,7 @@ pg-types@^2.1.0: postgres-date "~1.0.4" postgres-interval "^1.1.0" -pg@^7.12.1: +pg@7.x: version "7.12.1" resolved "https://registry.yarnpkg.com/pg/-/pg-7.12.1.tgz#880636d46d2efbe0968e64e9fe0eeece8ef72a7e" integrity sha512-l1UuyfEvoswYfcUe6k+JaxiN+5vkOgYcVSbSuw3FvdLqDbaoa2RJo1zfJKfPsSYPFVERd4GHvX3s2PjG1asSDA== From d3aee3dfc8b698358eaf76587fd95f1f745494a0 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 28 Oct 2019 11:45:20 -0500 Subject: [PATCH 0498/1037] Add additional pool test & deprecate .end There are no tests covering cursor.end(). It's also a weird method to have on the cursor as it terminates the connection to postgres internally. I don't recall why I added this method in the first place but its not correct to close a connection to postgres by calling .end on a cursor...seems like a pretty big footgun. If you have a pooled client and you call `cursor.end` it'll close the client internally and likely confuse the pool. Plus it's just weird to be able to close a connection by calling .end on a query or cursor. So...I'm deprecating that method. --- index.js | 6 ++++-- test/pool.js | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 8136c389c..a69600810 100644 --- a/index.js +++ b/index.js @@ -154,13 +154,15 @@ Cursor.prototype._getRows = function(rows, cb) { this.connection.flush() } -Cursor.prototype.end = function(cb) { +// users really shouldn't be calling 'end' here and terminating a connection to postgres +// via the low level connection.end api +Cursor.prototype.end = util.deprecate(function(cb) { if (this.state !== 'initialized') { this.connection.sync() } this.connection.once('end', cb) this.connection.end() -} +}, 'Cursor.end is deprecated. Call end on the client itself to end a connection to the database.') Cursor.prototype.close = function(cb) { if (this.state === 'done') { diff --git a/test/pool.js b/test/pool.js index bd487807b..80e0ddc15 100644 --- a/test/pool.js +++ b/test/pool.js @@ -83,4 +83,24 @@ describe('pool', function() { done() }) }) + + it('can close multiple times on a pool', async function() { + const pool = new pg.Pool({ max: 1 }) + const run = () => + new Promise(async resolve => { + const cursor = new Cursor(text) + const client = await pool.connect() + client.query(cursor) + cursor.read(25, function(err) { + assert.ifError(err) + cursor.close(function(err) { + assert.ifError(err) + client.release() + resolve() + }) + }) + }) + await Promise.all([run(), run(), run()]) + await pool.end() + }) }) From c95a650a737a74e8a275e8a3dd92b0acbb88df59 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 28 Oct 2019 11:58:35 -0500 Subject: [PATCH 0499/1037] Upgrade dependencies (#59) * Upgrade dependencies - There was a security vuln with mocha, so upgraded mocha. - Upgraded versions of node we're going to check in travis - Switched to yarn from npm - Removed --no-exit as that's standard mocha behavior now * Enable postgres on newer version of travis --- .travis.yml | 12 +- package-lock.json | 1920 --------------------------------------------- package.json | 2 +- test/mocha.opts | 1 - yarn.lock | 616 +++++++++++---- 5 files changed, 487 insertions(+), 2064 deletions(-) delete mode 100644 package-lock.json diff --git a/.travis.yml b/.travis.yml index b3f8a825e..177e9511b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,14 @@ language: node_js +dist: trusty node_js: - - "4" - - "6" - "8" - "10" + - "12" env: - - PGUSER=postgres PGDATABASE=postgres + - PGUSER=postgres +services: + - postgresql +addons: + postgresql: "9.6" +before_script: + - psql -c 'create database travis;' -U postgres | true diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index 85cda9c3a..000000000 --- a/package-lock.json +++ /dev/null @@ -1,1920 +0,0 @@ -{ - "name": "pg-query-stream", - "version": "2.0.0", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "JSONStream": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.7.4.tgz", - "integrity": "sha1-c0KQ5BUR7qfCz+FR+/mlY6l7l4Y=", - "dev": true, - "requires": { - "jsonparse": "0.0.5", - "through": ">=2.2.7 <3" - } - }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "^3.0.4" - }, - "dependencies": { - "acorn": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - } - } - }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" - } - }, - "ajv-keywords": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.1.tgz", - "integrity": "sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I=", - "dev": true - }, - "ansi-escapes": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", - "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "assertions": { - "version": "2.3.4", - "resolved": "https://registry.npmjs.org/assertions/-/assertions-2.3.4.tgz", - "integrity": "sha1-qUM87R/OV8yZmvCWXRAI6WwnluY=", - "dev": true, - "requires": { - "fomatto": "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6", - "render": "0.1", - "traverser": "1" - } - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base64-js": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-0.0.2.tgz", - "integrity": "sha1-Ak8Pcq+iW3X5wO5zzU9V7Bvtl4Q=", - "dev": true - }, - "bops": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/bops/-/bops-0.0.6.tgz", - "integrity": "sha1-CC0dVfoB5g29wuvC26N/ZZVUzzo=", - "dev": true, - "requires": { - "base64-js": "0.0.2", - "to-utf8": "0.0.1" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "browser-stdout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", - "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } - }, - "callsites": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "chardet": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz", - "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=", - "dev": true - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, - "cli-cursor": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", - "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", - "dev": true, - "requires": { - "restore-cursor": "^2.0.0" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "commander": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", - "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", - "dev": true, - "requires": { - "graceful-readlink": ">= 1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.0.1.tgz", - "integrity": "sha1-AYsYvBx9BzotyCqkhEI0GixN158=", - "dev": true, - "requires": { - "bops": "0.0.6" - } - }, - "contains-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", - "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "cross-spawn": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", - "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", - "dev": true, - "requires": { - "lru-cache": "^4.0.1", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - } - }, - "curry": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/curry/-/curry-0.0.4.tgz", - "integrity": "sha1-F1DVGNkZxE89N/9E7caT3h8NX8s=", - "dev": true - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "diff": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", - "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", - "dev": true - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "eslint": { - "version": "4.19.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.19.1.tgz", - "integrity": "sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ==", - "dev": true, - "requires": { - "ajv": "^5.3.0", - "babel-code-frame": "^6.22.0", - "chalk": "^2.1.0", - "concat-stream": "^1.6.0", - "cross-spawn": "^5.1.0", - "debug": "^3.1.0", - "doctrine": "^2.1.0", - "eslint-scope": "^3.7.1", - "eslint-visitor-keys": "^1.0.0", - "espree": "^3.5.4", - "esquery": "^1.0.0", - "esutils": "^2.0.2", - "file-entry-cache": "^2.0.0", - "functional-red-black-tree": "^1.0.1", - "glob": "^7.1.2", - "globals": "^11.0.1", - "ignore": "^3.3.3", - "imurmurhash": "^0.1.4", - "inquirer": "^3.0.6", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.9.1", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.3.0", - "lodash": "^4.17.4", - "minimatch": "^3.0.2", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "optionator": "^0.8.2", - "path-is-inside": "^1.0.2", - "pluralize": "^7.0.0", - "progress": "^2.0.0", - "regexpp": "^1.0.1", - "require-uncached": "^1.0.3", - "semver": "^5.3.0", - "strip-ansi": "^4.0.0", - "strip-json-comments": "~2.0.1", - "table": "4.0.2", - "text-table": "~0.2.0" - }, - "dependencies": { - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - } - } - }, - "eslint-config-standard": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz", - "integrity": "sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE=", - "dev": true - }, - "eslint-import-resolver-node": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz", - "integrity": "sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q==", - "dev": true, - "requires": { - "debug": "^2.6.9", - "resolve": "^1.5.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-module-utils": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.2.0.tgz", - "integrity": "sha1-snA2LNiLGkitMIl2zn+lTphBF0Y=", - "dev": true, - "requires": { - "debug": "^2.6.8", - "pkg-dir": "^1.0.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-plugin-import": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.14.0.tgz", - "integrity": "sha512-FpuRtniD/AY6sXByma2Wr0TXvXJ4nA/2/04VPlfpmUDPOpOY264x+ILiwnrk/k4RINgDAyFZByxqPUbSQ5YE7g==", - "dev": true, - "requires": { - "contains-path": "^0.1.0", - "debug": "^2.6.8", - "doctrine": "1.5.0", - "eslint-import-resolver-node": "^0.3.1", - "eslint-module-utils": "^2.2.0", - "has": "^1.0.1", - "lodash": "^4.17.4", - "minimatch": "^3.0.3", - "read-pkg-up": "^2.0.0", - "resolve": "^1.6.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "eslint-plugin-node": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz", - "integrity": "sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g==", - "dev": true, - "requires": { - "ignore": "^3.3.6", - "minimatch": "^3.0.4", - "resolve": "^1.3.3", - "semver": "5.3.0" - }, - "dependencies": { - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "dev": true - } - } - }, - "eslint-plugin-promise": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz", - "integrity": "sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ==", - "dev": true - }, - "eslint-plugin-standard": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz", - "integrity": "sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w==", - "dev": true - }, - "eslint-scope": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.3.tgz", - "integrity": "sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA==", - "dev": true, - "requires": { - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "eslint-visitor-keys": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", - "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", - "dev": true - }, - "espree": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", - "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", - "dev": true, - "requires": { - "acorn": "^5.5.0", - "acorn-jsx": "^3.0.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esquery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", - "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", - "dev": true, - "requires": { - "estraverse": "^4.0.0" - } - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "external-editor": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.2.0.tgz", - "integrity": "sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A==", - "dev": true, - "requires": { - "chardet": "^0.4.0", - "iconv-lite": "^0.4.17", - "tmp": "^0.0.33" - } - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "figures": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", - "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5" - } - }, - "file-entry-cache": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", - "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", - "dev": true, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "flat-cache": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", - "dev": true, - "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" - } - }, - "fomatto": { - "version": "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6", - "from": "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6", - "dev": true - }, - "from": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/from/-/from-0.0.2.tgz", - "integrity": "sha1-f/+sZHovmbINV7jig3lFXLtBidA=", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "globals": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.9.0.tgz", - "integrity": "sha512-5cJVtyXWH8PiJPVLZzzoIizXx944O4OmRro5MWKx5fT4MgcN7OfaMutPeaTdJCCURwbWdhhcCWcKIffPnmTzBg==", - "dev": true - }, - "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", - "dev": true - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "growl": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", - "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "inquirer": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", - "dev": true, - "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", - "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.1.tgz", - "integrity": "sha512-um46hB9wNOKlwkHgiuyEVAybXBjwFUV0Z/RaHJblRd9DXltue9FTYvzCr9ErQrK9Adz5MU4gHWVaNUfdmrC8qA==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "json3": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", - "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", - "dev": true - }, - "jsonparse": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", - "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - } - }, - "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", - "dev": true, - "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "dependencies": { - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - } - } - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basecreate": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", - "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", - "dev": true - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash.create": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", - "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", - "dev": true, - "requires": { - "lodash._baseassign": "^3.0.0", - "lodash._basecreate": "^3.0.0", - "lodash._isiterateecall": "^3.0.0" - } - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "lru-cache": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", - "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", - "dev": true, - "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" - } - }, - "macgyver": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/macgyver/-/macgyver-1.10.1.tgz", - "integrity": "sha1-sJ0VmdizbtWxb1lYlRXZ0UvC/Yg=", - "dev": true - }, - "mimic-fn": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", - "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", - "dev": true - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "mocha": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.5.3.tgz", - "integrity": "sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg==", - "dev": true, - "requires": { - "browser-stdout": "1.3.0", - "commander": "2.9.0", - "debug": "2.6.8", - "diff": "3.2.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.1", - "growl": "1.9.2", - "he": "1.1.1", - "json3": "3.3.2", - "lodash.create": "3.1.1", - "mkdirp": "0.5.1", - "supports-color": "3.1.2" - }, - "dependencies": { - "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "glob": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", - "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.2", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "supports-color": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", - "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - } - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "mute-stream": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", - "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", - "dev": true - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", - "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", - "dev": true, - "requires": { - "mimic-fn": "^1.0.0" - } - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true - }, - "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "requires": { - "p-try": "^1.0.0" - } - }, - "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", - "dev": true, - "requires": { - "p-limit": "^1.1.0" - } - }, - "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", - "dev": true - }, - "packet-reader": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", - "integrity": "sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc=", - "dev": true - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", - "dev": true, - "requires": { - "pify": "^2.0.0" - } - }, - "pg": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-7.7.1.tgz", - "integrity": "sha512-p3I0mXOmUvCoVlCMFW6iYSrnguPol6q8He15NGgSIdM3sPGjFc+8JGCeKclw8ZR4ETd+Jxy2KNiaPUcocHZeMw==", - "dev": true, - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "0.3.1", - "pg-connection-string": "0.1.3", - "pg-pool": "^2.0.4", - "pg-types": "~1.12.1", - "pgpass": "1.x", - "semver": "4.3.2" - }, - "dependencies": { - "semver": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", - "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=", - "dev": true - } - } - }, - "pg-connection-string": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", - "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=", - "dev": true - }, - "pg-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pg-cursor/-/pg-cursor-2.0.0.tgz", - "integrity": "sha512-/gYHadqLurektHk6HXiL0hSrn+RZfowkLr+ftC0lLoLBlIm8JIdk9f9g71EEjK63XxqhFqcykHuxQLFzSeyzdQ==" - }, - "pg-pool": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.6.tgz", - "integrity": "sha512-hod2zYQxM8Gt482q+qONGTYcg/qVcV32VHVPtktbBJs0us3Dj7xibISw0BAAXVMCzt8A/jhfJvpZaxUlqtqs0g==", - "dev": true - }, - "pg-types": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.12.1.tgz", - "integrity": "sha1-1kCH45A7WP+q0nnnWVxSIIoUw9I=", - "dev": true, - "requires": { - "postgres-array": "~1.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.0", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "dev": true, - "requires": { - "split": "^1.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "pkg-dir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz", - "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q=", - "dev": true, - "requires": { - "find-up": "^1.0.0" - } - }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", - "dev": true - }, - "postgres-array": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.3.tgz", - "integrity": "sha512-5wClXrAP0+78mcsNX3/ithQ5exKvCyK5lr5NEEEeGwwM6NJdQgzIJBVxLvRW+huFpX92F2QnZ5CcokH0VhK2qQ==", - "dev": true - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", - "dev": true - }, - "postgres-date": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.3.tgz", - "integrity": "sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g=", - "dev": true - }, - "postgres-interval": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.1.2.tgz", - "integrity": "sha512-fC3xNHeTskCxL1dC8KOtxXt7YeFmlbTYtn7ul8MkVERuTmf7pI4DrkAxcw3kh1fQ9uz4wQmd03a1mRiXUZChfQ==", - "dev": true, - "requires": { - "xtend": "^4.0.0" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", - "dev": true, - "requires": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - } - }, - "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", - "dev": true, - "requires": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "^2.0.0" - } - } - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "regexpp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-1.1.0.tgz", - "integrity": "sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw==", - "dev": true - }, - "render": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/render/-/render-0.1.4.tgz", - "integrity": "sha1-z7M6NOJgaFkdQYRp4j2Mxc4c7/U=", - "dev": true, - "requires": { - "traverser": "0.0.x" - }, - "dependencies": { - "traverser": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/traverser/-/traverser-0.0.5.tgz", - "integrity": "sha1-xm84xFagwhqIAUsSI1gMfr4GMes=", - "dev": true, - "requires": { - "curry": "0.0.x" - } - } - } - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - } - }, - "resolve": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.9.0.tgz", - "integrity": "sha512-TZNye00tI67lwYvzxCxHGjwTNlUV70io54/Ed4j6PscB8xVfuBJpRenI/o6dVk0cY0PYTY27AgCoGGxRnYuItQ==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - }, - "restore-cursor": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", - "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", - "dev": true, - "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" - } - }, - "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "run-async": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", - "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", - "dev": true, - "requires": { - "is-promise": "^2.1.0" - } - }, - "rx-lite": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", - "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", - "dev": true - }, - "rx-lite-aggregates": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", - "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", - "dev": true, - "requires": { - "rx-lite": "*" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true - }, - "shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", - "dev": true, - "requires": { - "shebang-regex": "^1.0.0" - } - }, - "shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", - "dev": true - }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true - }, - "slice-ansi": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", - "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0" - } - }, - "spdx-correct": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", - "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz", - "integrity": "sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g==", - "dev": true - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "requires": { - "through": "2" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "stream-spec": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/stream-spec/-/stream-spec-0.3.6.tgz", - "integrity": "sha1-L92sSge/Pp+JY8Z3prWmzCEVJV4=", - "dev": true, - "requires": { - "macgyver": "~1.10" - } - }, - "stream-tester": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stream-tester/-/stream-tester-0.0.5.tgz", - "integrity": "sha1-T4byUxFJra9t1LP/Ji7fZK6aFxo=", - "dev": true, - "requires": { - "assertions": "~2.3.0", - "from": "~0.0.2", - "through": "~0.0.3" - }, - "dependencies": { - "through": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/through/-/through-0.0.4.tgz", - "integrity": "sha1-C/Lw//r6rEusvFM2Z+mKrQC1iMg=", - "dev": true - } - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - } - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "table": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", - "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", - "dev": true, - "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", - "slice-ansi": "1.0.0", - "string-width": "^2.1.1" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-utf8": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/to-utf8/-/to-utf8-0.0.1.tgz", - "integrity": "sha1-0Xrqcv8vujm55DYBvns/9y4ImFI=", - "dev": true - }, - "traverser": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/traverser/-/traverser-1.0.0.tgz", - "integrity": "sha1-b1nlgTdZruqzZGuPRRP9SmLk/iA=", - "dev": true, - "requires": { - "curry": "0.0.x" - } - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "yallist": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", - "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", - "dev": true - } - } -} diff --git a/package.json b/package.json index da5122926..0be7b9536 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "eslint-plugin-node": "^5.1.1", "eslint-plugin-promise": "^3.5.0", "eslint-plugin-standard": "^3.0.1", - "mocha": "^3.5.0", + "mocha": "^6.2.2", "pg": "^7.5.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", diff --git a/test/mocha.opts b/test/mocha.opts index 46e8e69d9..8640eeef9 100644 --- a/test/mocha.opts +++ b/test/mocha.opts @@ -1,2 +1 @@ ---no-exit --bail diff --git a/yarn.lock b/yarn.lock index 938fda8ee..684fe8521 100644 --- a/yarn.lock +++ b/yarn.lock @@ -43,6 +43,11 @@ ajv@^5.2.0: json-schema-traverse "^0.3.0" json-stable-stringify "^1.0.1" +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== + ansi-escapes@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" @@ -55,6 +60,11 @@ ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" @@ -65,9 +75,12 @@ ansi-styles@^3.1.0: dependencies: color-convert "^1.9.0" -ap@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ap/-/ap-0.2.0.tgz#ae0942600b29912f0d2b14ec60c45e8f330b6110" +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" argparse@^1.0.7: version "1.0.9" @@ -127,13 +140,15 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -buffer-writer@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-1.0.1.tgz#22a936901e3029afcd7547eb4487ceb697a3bf08" +buffer-writer@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" + integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" @@ -149,6 +164,11 @@ callsites@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" @@ -167,6 +187,15 @@ chalk@^2.0.0: escape-string-regexp "^1.0.5" supports-color "^4.0.0" +chalk@^2.0.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + circular-json@^0.3.1: version "0.3.3" resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" @@ -181,6 +210,15 @@ cli-width@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -195,12 +233,6 @@ color-name@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" -commander@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - dependencies: - graceful-readlink ">= 1.0.0" - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -239,16 +271,35 @@ curry@0.0.x: version "0.0.4" resolved "https://registry.yarnpkg.com/curry/-/curry-0.0.4.tgz#1750d518d919c44f3d37ff44edc693de1f0d5fcb" -debug@2.6.8, debug@^2.6.8: +debug@3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@^2.6.8: version "2.6.8" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" dependencies: ms "2.0.0" +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + del@^2.0.2: version "2.2.2" resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" @@ -261,9 +312,10 @@ del@^2.0.2: pinkie-promise "^2.0.0" rimraf "^2.2.8" -diff@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" +diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== doctrine@1.5.0: version "1.5.0" @@ -279,12 +331,42 @@ doctrine@^2.0.0: esutils "^2.0.2" isarray "^1.0.0" +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + error-ex@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" dependencies: is-arrayish "^0.2.1" +es-abstract@^1.5.1: + version "1.16.0" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" + integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== + dependencies: + es-to-primitive "^1.2.0" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.0" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-inspect "^1.6.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.1.0" + string.prototype.trimright "^2.1.0" + +es-to-primitive@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" + integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" @@ -448,6 +530,13 @@ file-entry-cache@^2.0.0: flat-cache "^1.2.1" object-assign "^4.0.1" +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -470,6 +559,13 @@ flat-cache@^1.2.1: graceful-fs "^4.1.2" write "^0.2.1" +flat@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" + integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== + dependencies: + is-buffer "~2.0.3" + "fomatto@git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6": version "0.6.0" resolved "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6" @@ -486,22 +582,29 @@ function-bind@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" -generic-pool@2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/generic-pool/-/generic-pool-2.4.3.tgz#780c36f69dfad05a5a045dd37be7adca11a4f6ff" +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -glob@7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" +glob@7.1.3: + version "7.1.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.2" + minimatch "^3.0.4" once "^1.3.0" path-is-absolute "^1.0.0" @@ -535,13 +638,10 @@ graceful-fs@^4.1.2: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - -growl@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== has-ansi@^2.0.0: version "2.0.0" @@ -549,20 +649,38 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" -has-flag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" - has-flag@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" + integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= + has@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" dependencies: function-bind "^1.0.2" +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +he@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + hosted-git-info@^2.1.4: version "2.5.0" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" @@ -613,12 +731,27 @@ is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" +is-buffer@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== + is-builtin-module@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" dependencies: builtin-modules "^1.0.0" +is-callable@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" @@ -643,12 +776,26 @@ is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" + is-resolvable@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" dependencies: tryit "^1.0.1" +is-symbol@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" + integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== + dependencies: + has-symbols "^1.0.0" + isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" @@ -661,6 +808,14 @@ js-tokens@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" +js-yaml@3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + js-yaml@^3.9.1: version "3.9.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0" @@ -682,10 +837,6 @@ json-stable-stringify@^1.0.1: dependencies: jsonify "~0.0.0" -json3@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" - jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -717,61 +868,34 @@ locate-path@^2.0.0: p-locate "^2.0.0" path-exists "^3.0.0" -lodash._baseassign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== dependencies: - lodash._basecopy "^3.0.0" - lodash.keys "^3.0.0" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - -lodash._basecreate@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + p-locate "^3.0.0" + path-exists "^3.0.0" lodash.cond@^4.3.0: version "4.5.2" resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" -lodash.create@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" - dependencies: - lodash._baseassign "^3.0.0" - lodash._basecreate "^3.0.0" - lodash._isiterateecall "^3.0.0" - -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - lodash@^4.0.0, lodash@^4.17.4, lodash@^4.3.0: version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" +lodash@^4.17.15: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +log-symbols@2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== + dependencies: + chalk "^2.0.1" + lru-cache@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" @@ -787,7 +911,7 @@ mimic-fn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" -minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: @@ -803,26 +927,49 @@ mkdirp@0.5.1, mkdirp@^0.5.1: dependencies: minimist "0.0.8" -mocha@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.0.tgz#1328567d2717f997030f8006234bce9b8cd72465" +mocha@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" + integrity sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A== dependencies: - browser-stdout "1.3.0" - commander "2.9.0" - debug "2.6.8" - diff "3.2.0" + ansi-colors "3.2.3" + browser-stdout "1.3.1" + debug "3.2.6" + diff "3.5.0" escape-string-regexp "1.0.5" - glob "7.1.1" - growl "1.9.2" - json3 "3.3.2" - lodash.create "3.1.1" + find-up "3.0.0" + glob "7.1.3" + growl "1.10.5" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "2.2.0" + minimatch "3.0.4" mkdirp "0.5.1" - supports-color "3.1.2" + ms "2.1.1" + node-environment-flags "1.0.5" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.0" + yargs-parser "13.1.1" + yargs-unparser "1.6.0" ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" @@ -831,6 +978,14 @@ natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" +node-environment-flags@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + normalize-package-data@^2.3.2: version "2.4.0" resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" @@ -840,10 +995,38 @@ normalize-package-data@^2.3.2: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -object-assign@4.1.0, object-assign@^4.0.1: +object-assign@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" +object-inspect@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" + integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -875,15 +1058,35 @@ p-limit@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" +p-limit@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + dependencies: + p-try "^2.0.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" dependencies: p-limit "^1.1.0" -packet-reader@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-0.3.1.tgz#cd62e60af8d7fea8a705ec4ff990871c46871f27" +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +packet-reader@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" + integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== parse-json@^2.2.0: version "2.2.0" @@ -923,42 +1126,49 @@ pg-connection-string@0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" -pg-cursor@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/pg-cursor/-/pg-cursor-1.3.0.tgz#b220f1908976b7b40daa373c7ada5fca823ab0d9" +pg-cursor@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pg-cursor/-/pg-cursor-2.0.0.tgz#1e11532613d2d4c61057a5705a1536b1052d1698" + integrity sha512-/gYHadqLurektHk6HXiL0hSrn+RZfowkLr+ftC0lLoLBlIm8JIdk9f9g71EEjK63XxqhFqcykHuxQLFzSeyzdQ== -pg-pool@1.*: - version "1.8.0" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-1.8.0.tgz#f7ec73824c37a03f076f51bfdf70e340147c4f37" - dependencies: - generic-pool "2.4.3" - object-assign "4.1.0" +pg-int8@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" + integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== + +pg-pool@^2.0.4: + version "2.0.7" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.7.tgz#f14ecab83507941062c313df23f6adcd9fd0ce54" + integrity sha512-UiJyO5B9zZpu32GSlP0tXy8J2NsJ9EFGFfz5v6PSbdz/1hBLX1rNiiy5+mAm5iJJYwfCv4A0EBcQLGWwjbpzZw== -pg-types@1.*: - version "1.12.0" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-1.12.0.tgz#8ad3b7b897e3fd463e62de241ad5fc640b4a66f0" +pg-types@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" + integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== dependencies: - ap "~0.2.0" - postgres-array "~1.0.0" + pg-int8 "1.0.1" + postgres-array "~2.0.0" postgres-bytea "~1.0.0" - postgres-date "~1.0.0" + postgres-date "~1.0.4" postgres-interval "^1.1.0" -pg@6.x: - version "6.4.1" - resolved "https://registry.yarnpkg.com/pg/-/pg-6.4.1.tgz#3eabd8ca056814437c769f17ff7a0c36ac7023c5" +pg@^7.5.0: + version "7.12.1" + resolved "https://registry.yarnpkg.com/pg/-/pg-7.12.1.tgz#880636d46d2efbe0968e64e9fe0eeece8ef72a7e" + integrity sha512-l1UuyfEvoswYfcUe6k+JaxiN+5vkOgYcVSbSuw3FvdLqDbaoa2RJo1zfJKfPsSYPFVERd4GHvX3s2PjG1asSDA== dependencies: - buffer-writer "1.0.1" - packet-reader "0.3.1" + buffer-writer "2.0.0" + packet-reader "1.0.0" pg-connection-string "0.1.3" - pg-pool "1.*" - pg-types "1.*" - pgpass "1.*" + pg-pool "^2.0.4" + pg-types "^2.1.0" + pgpass "1.x" semver "4.3.2" -pgpass@1.*: +pgpass@1.x: version "1.0.2" resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" + integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY= dependencies: split "^1.0.0" @@ -986,17 +1196,19 @@ pluralize@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762" -postgres-array@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-1.0.2.tgz#8e0b32eb03bf77a5c0a7851e0441c169a256a238" +postgres-array@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" + integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== postgres-bytea@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" -postgres-date@~1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.3.tgz#e2d89702efdb258ff9d9cee0fe91bd06975257a8" +postgres-date@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.4.tgz#1c2728d62ef1bff49abdd35c1f86d4bdf118a728" + integrity sha512-bESRvKVuTrjoBluEcpv2346+6kgB7UlnqWZsnbnCccTNq/pqfj1j6oBaN5+b/NrDXepYUT/HKadqv3iS9lJuVA== postgres-interval@^1.1.0: version "1.1.1" @@ -1053,6 +1265,16 @@ render@0.1: dependencies: traverser "0.0.x" +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + require-uncached@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" @@ -1111,6 +1333,16 @@ semver@4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" +semver@^5.7.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" @@ -1167,13 +1399,38 @@ stream-tester@0.0.5: from "~0.0.2" through "~0.0.3" -string-width@^2.0.0, string-width@^2.1.0: +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" dependencies: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string.prototype.trimleft@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" + integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" + integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + string_decoder@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" @@ -1192,19 +1449,27 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" -strip-json-comments@~2.0.1: +strip-json-comments@2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" -supports-color@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" +supports-color@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== dependencies: - has-flag "^1.0.0" + has-flag "^3.0.0" supports-color@^2.0.0: version "2.0.0" @@ -1216,6 +1481,13 @@ supports-color@^4.0.0: dependencies: has-flag "^2.0.0" +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + table@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/table/-/table-4.0.1.tgz#a8116c133fac2c61f4a420ab6cdf5c4d61f0e435" @@ -1286,16 +1558,44 @@ validate-npm-package-license@^3.0.1: spdx-correct "~1.0.0" spdx-expression-parse "~1.0.0" +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + which@^1.2.9: version "1.3.0" resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" dependencies: isexe "^2.0.0" +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + wordwrap@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -1310,6 +1610,44 @@ xtend@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + +yargs-parser@13.1.1, yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + +yargs@13.3.0, yargs@^13.3.0: + version "13.3.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1" From e153e3f5fd436561fa6587296372d45a643694a0 Mon Sep 17 00:00:00 2001 From: Mandy Real Date: Tue, 29 Oct 2019 01:00:09 +0800 Subject: [PATCH 0500/1037] fixed typo `cumbersom` (#49) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 49e03749c..d00550aec 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ pg.connect((err, client, done) => { The stream uses a cursor on the server so it efficiently keeps only a low number of rows in memory. -This is especially useful when doing [ETL](http://en.wikipedia.org/wiki/Extract,_transform,_load) on a huge table. Using manual `limit` and `offset` queries to fake out async itteration through your data is cumbersom, and _way way way_ slower than using a cursor. +This is especially useful when doing [ETL](http://en.wikipedia.org/wiki/Extract,_transform,_load) on a huge table. Using manual `limit` and `offset` queries to fake out async itteration through your data is cumbersome, and _way way way_ slower than using a cursor. _note: this module only works with the JavaScript client, and does not work with the native bindings. libpq doesn't expose the protocol at a level where a cursor can be manipulated directly_ From fb52c52304e372c30948de9672ef8e70c3a9461e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2019 12:02:44 -0500 Subject: [PATCH 0501/1037] Bump js-yaml from 3.9.1 to 3.13.1 (#60) Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.9.1 to 3.13.1. - [Release notes](https://github.com/nodeca/js-yaml/releases) - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/3.9.1...3.13.1) Signed-off-by: dependabot[bot] --- yarn.lock | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/yarn.lock b/yarn.lock index 684fe8521..991ae399d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -83,8 +83,9 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: color-convert "^1.9.0" argparse@^1.0.7: - version "1.0.9" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== dependencies: sprintf-js "~1.0.2" @@ -477,8 +478,9 @@ espree@^3.5.0: acorn-jsx "^3.0.0" esprima@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.0.0: version "1.0.0" @@ -808,7 +810,7 @@ js-tokens@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" -js-yaml@3.13.1: +js-yaml@3.13.1, js-yaml@^3.9.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -816,13 +818,6 @@ js-yaml@3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^3.9.1: - version "3.9.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.9.1.tgz#08775cebdfdd359209f0d2acd383c8f86a6904a0" - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - jschardet@^1.4.2: version "1.5.0" resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.5.0.tgz#a61f310306a5a71188e1b1acd08add3cfbb08b1e" @@ -1384,6 +1379,7 @@ split@^1.0.0: sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= stream-spec@~0.3.5: version "0.3.6" From a756ee30e40328245cf8487287751159cb825850 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2019 12:10:49 -0500 Subject: [PATCH 0502/1037] Bump debug from 2.6.8 to 2.6.9 (#61) Bumps [debug](https://github.com/visionmedia/debug) from 2.6.8 to 2.6.9. - [Release notes](https://github.com/visionmedia/debug/releases) - [Changelog](https://github.com/visionmedia/debug/blob/2.6.9/CHANGELOG.md) - [Commits](https://github.com/visionmedia/debug/compare/2.6.8...2.6.9) Signed-off-by: dependabot[bot] --- yarn.lock | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index 991ae399d..0c7662d26 100644 --- a/yarn.lock +++ b/yarn.lock @@ -280,8 +280,9 @@ debug@3.2.6: ms "^2.1.1" debug@^2.6.8: - version "2.6.8" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" @@ -954,6 +955,7 @@ mocha@^6.2.2: ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@2.1.1: version "2.1.1" From a84db5ffd74387dbaea38f0bad2e67b6d536d135 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 28 Oct 2019 12:46:49 -0500 Subject: [PATCH 0503/1037] Add async iterator tests (#62) --- package.json | 7 +++++ test/async-iterator.es6 | 57 +++++++++++++++++++++++++++++++++++++++++ test/async-iterator.js | 4 +++ yarn.lock | 5 ++++ 4 files changed, 73 insertions(+) create mode 100644 test/async-iterator.es6 create mode 100644 test/async-iterator.js diff --git a/package.json b/package.json index 0be7b9536..9675d0641 100644 --- a/package.json +++ b/package.json @@ -32,10 +32,17 @@ "eslint-plugin-standard": "^3.0.1", "mocha": "^6.2.2", "pg": "^7.5.0", + "prettier": "^1.18.2", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, + "prettier": { + "semi": false, + "printWidth": 120, + "trailingComma": "es5", + "singleQuote": true + }, "dependencies": { "pg-cursor": "2.0.0" } diff --git a/test/async-iterator.es6 b/test/async-iterator.es6 new file mode 100644 index 000000000..e84089b6c --- /dev/null +++ b/test/async-iterator.es6 @@ -0,0 +1,57 @@ +const QueryStream = require('../') +const pg = require('pg') +const assert = require('assert') + +const queryText = 'SELECT * FROM generate_series(0, 200) num' +describe('Async iterator', () => { + it('works', async () => { + const stream = new QueryStream(queryText, []) + const client = new pg.Client() + await client.connect() + const query = client.query(stream) + const rows = [] + for await (const row of query) { + rows.push(row) + } + assert.equal(rows.length, 201) + await client.end() + }) + + it('can async iterate and then do a query afterwards', async () => { + const stream = new QueryStream(queryText, []) + const client = new pg.Client() + await client.connect() + const query = client.query(stream) + const iteratorRows = [] + for await (const row of query) { + iteratorRows.push(row) + } + assert.equal(iteratorRows.length, 201) + const { rows } = await client.query('SELECT NOW()') + assert.equal(rows.length, 1) + await client.end() + }) + + it('can async iterate multiple times with a pool', async () => { + const pool = new pg.Pool({ max: 1 }) + + const allRows = [] + const run = async () => { + // get the client + const client = await pool.connect() + // stream some rows + const stream = new QueryStream(queryText, []) + const iteratorRows = [] + client.query(stream) + for await (const row of stream) { + iteratorRows.push(row) + allRows.push(row) + } + assert.equal(iteratorRows.length, 201) + client.release() + } + await Promise.all([run(), run(), run()]) + assert.equal(allRows.length, 603) + await pool.end() + }) +}) diff --git a/test/async-iterator.js b/test/async-iterator.js new file mode 100644 index 000000000..19718fe3b --- /dev/null +++ b/test/async-iterator.js @@ -0,0 +1,4 @@ +// only newer versions of node support async iterator +if (!process.version.startsWith('v8')) { + require('./async-iterator.es6') +} diff --git a/yarn.lock b/yarn.lock index 0c7662d26..bc9baae93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1217,6 +1217,11 @@ prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" +prettier@^1.18.2: + version "1.18.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" + integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== + process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" From 389d5d8c144b252efa20d422fd94adfb559474f8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 30 Oct 2019 11:33:52 -0500 Subject: [PATCH 0504/1037] Fix named portal being left open When code was added to use a random named portal instead of the empty portal to support redshift we didn't update the close messages approprately. This could result in postgres keeping locks on tables for modification if streaming and table modification was both done within a transaction. This update fixes the issue by always issuing a close command on the named portal when query is finished. fixes #56 --- .eslintrc | 3 +++ .travis.yml | 8 ++++---- index.js | 16 ++++++++++++---- test/transactions.js | 30 ++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 test/transactions.js diff --git a/.eslintrc b/.eslintrc index 5ce7148ea..aa7df694d 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,5 +1,8 @@ { "extends": ["eslint:recommended"], + "parserOptions": { + "ecmaVersion": 2017 + }, "plugins": ["prettier"], "rules": { "prettier/prettier": "error", diff --git a/.travis.yml b/.travis.yml index b2ef3881c..aea6a149e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,14 +2,14 @@ language: node_js dist: trusty sudo: false node_js: - - "8" - - "10" - - "12" + - '8' + - '10' + - '12' env: - PGUSER=postgres services: - postgresql addons: - postgresql: "9.6" + postgresql: '9.6' before_script: - psql -c 'create database travis;' -U postgres | true diff --git a/index.js b/index.js index 8136c389c..ce8b503be 100644 --- a/index.js +++ b/index.js @@ -75,6 +75,15 @@ Cursor.prototype._shiftQueue = function() { } } +Cursor.prototype._closePortal = function() { + // because we opened a named portal to stream results + // we need to close the same named portal. Leaving a named portal + // open can lock tables for modification if inside a transaction. + // see https://github.com/brianc/node-pg-cursor/issues/56 + this.connection.close({ type: 'P', name: this._portal }) + this.connection.sync() +} + Cursor.prototype.handleRowDescription = function(msg) { this._result.addFields(msg.fields) this.state = 'idle' @@ -105,7 +114,7 @@ Cursor.prototype._sendRows = function() { Cursor.prototype.handleCommandComplete = function(msg) { this._result.addCommandComplete(msg) - this.connection.sync() + this._closePortal() } Cursor.prototype.handlePortalSuspended = function() { @@ -114,8 +123,8 @@ Cursor.prototype.handlePortalSuspended = function() { Cursor.prototype.handleReadyForQuery = function() { this._sendRows() - this.emit('end', this._result) this.state = 'done' + this.emit('end', this._result) } Cursor.prototype.handleEmptyQuery = function() { @@ -166,8 +175,7 @@ Cursor.prototype.close = function(cb) { if (this.state === 'done') { return setImmediate(cb) } - this.connection.close({ type: 'P' }) - this.connection.sync() + this._closePortal() this.state = 'done' if (cb) { this.connection.once('closeComplete', function() { diff --git a/test/transactions.js b/test/transactions.js new file mode 100644 index 000000000..75d32a4ad --- /dev/null +++ b/test/transactions.js @@ -0,0 +1,30 @@ +const assert = require('assert') +const Cursor = require('../') +const pg = require('pg') + +describe('transactions', () => { + it('can execute multiple statements in a transaction', async () => { + const client = new pg.Client() + await client.connect() + await client.query('begin') + await client.query('CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)') + const cursor = client.query(new Cursor('SELECT * FROM foobar')) + const rows = await new Promise((resolve, reject) => { + cursor.read(10, (err, rows) => (err ? reject(err) : resolve(rows))) + }) + assert.equal(rows.length, 0) + await client.query('ALTER TABLE foobar ADD COLUMN name TEXT') + await client.end() + }) + + it('can execute multiple statements in a transaction if ending cursor early', async () => { + const client = new pg.Client() + await client.connect() + await client.query('begin') + await client.query('CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)') + const cursor = client.query(new Cursor('SELECT * FROM foobar')) + await new Promise(resolve => cursor.close(resolve)) + await client.query('ALTER TABLE foobar ADD COLUMN name TEXT') + await client.end() + }) +}) From bd86514c722e803321f4036d1e67139a695cf1bd Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 30 Oct 2019 11:43:17 -0500 Subject: [PATCH 0505/1037] Add another test --- test/transactions.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/transactions.js b/test/transactions.js index 75d32a4ad..37af28c42 100644 --- a/test/transactions.js +++ b/test/transactions.js @@ -27,4 +27,17 @@ describe('transactions', () => { await client.query('ALTER TABLE foobar ADD COLUMN name TEXT') await client.end() }) + + it.only('can execute multiple statements in a transaction if no data', async () => { + const client = new pg.Client() + await client.connect() + await client.query('begin') + // create a cursor that has no data response + const createText = 'CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)' + const cursor = client.query(new Cursor(createText)) + const err = await new Promise(resolve => cursor.read(100, resolve)) + assert.ifError(err) + await client.query('ALTER TABLE foobar ADD COLUMN name TEXT') + await client.end() + }) }) From cedce4bded8cf4970de6ad95e62c411d639cd51e Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 30 Oct 2019 12:52:06 -0500 Subject: [PATCH 0506/1037] Fix lint & enable all tests --- test/pool.js | 11 ++++++----- test/transactions.js | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/test/pool.js b/test/pool.js index 80e0ddc15..61f5e2795 100644 --- a/test/pool.js +++ b/test/pool.js @@ -86,11 +86,11 @@ describe('pool', function() { it('can close multiple times on a pool', async function() { const pool = new pg.Pool({ max: 1 }) - const run = () => - new Promise(async resolve => { - const cursor = new Cursor(text) - const client = await pool.connect() - client.query(cursor) + const run = async () => { + const cursor = new Cursor(text) + const client = await pool.connect() + client.query(cursor) + new Promise(resolve => { cursor.read(25, function(err) { assert.ifError(err) cursor.close(function(err) { @@ -100,6 +100,7 @@ describe('pool', function() { }) }) }) + } await Promise.all([run(), run(), run()]) await pool.end() }) diff --git a/test/transactions.js b/test/transactions.js index 37af28c42..f83cc1d77 100644 --- a/test/transactions.js +++ b/test/transactions.js @@ -28,7 +28,7 @@ describe('transactions', () => { await client.end() }) - it.only('can execute multiple statements in a transaction if no data', async () => { + it('can execute multiple statements in a transaction if no data', async () => { const client = new pg.Client() await client.connect() await client.query('begin') From 37906091e129e33de5466fcf46a5bced8cc295be Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 30 Oct 2019 12:55:38 -0500 Subject: [PATCH 0507/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e35309723..14b34ee9c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.0.0", + "version": "2.0.1", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { From 3e59f28df459ceb23f8c0eef548f94af015b134a Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 30 Oct 2019 13:03:09 -0500 Subject: [PATCH 0508/1037] Bump version of pg-cursor (#64) This includes fixes in pg-cursor@2.0.1. I've relaxed semver a touch so I don't have to release a new version here just for patch changes to pg-cursor. --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 9675d0641..35d5b5a30 100644 --- a/package.json +++ b/package.json @@ -44,6 +44,6 @@ "singleQuote": true }, "dependencies": { - "pg-cursor": "2.0.0" + "pg-cursor": "^2.0.1" } } diff --git a/yarn.lock b/yarn.lock index bc9baae93..57fe7f9d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1123,10 +1123,10 @@ pg-connection-string@0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" -pg-cursor@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pg-cursor/-/pg-cursor-2.0.0.tgz#1e11532613d2d4c61057a5705a1536b1052d1698" - integrity sha512-/gYHadqLurektHk6HXiL0hSrn+RZfowkLr+ftC0lLoLBlIm8JIdk9f9g71EEjK63XxqhFqcykHuxQLFzSeyzdQ== +pg-cursor@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pg-cursor/-/pg-cursor-2.0.1.tgz#f3bcb3d40b29d86d50014daa0a58f1f0fb71a7f9" + integrity sha512-AfPaRh6N32HrXB8/D0JXfJWdLCn8U+Z4LEf8C954aSFTjhZqt7QbyAYyN5k1E4cv0HQjwW70G1xywQ5ZECzPPg== pg-int8@1.0.1: version "1.0.1" From 05b4c573d2c122f20d52a72d234ea2ce4fe6ee03 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 30 Oct 2019 13:03:26 -0500 Subject: [PATCH 0509/1037] Bump eslint from 4.4.0 to 4.18.2 (#63) Bumps [eslint](https://github.com/eslint/eslint) from 4.4.0 to 4.18.2. - [Release notes](https://github.com/eslint/eslint/releases) - [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md) - [Commits](https://github.com/eslint/eslint/compare/v4.4.0...v4.18.2) Signed-off-by: dependabot[bot] --- yarn.lock | 205 +++++++++++++++++++++++------------------------------- 1 file changed, 88 insertions(+), 117 deletions(-) diff --git a/yarn.lock b/yarn.lock index 57fe7f9d8..3f1706479 100644 --- a/yarn.lock +++ b/yarn.lock @@ -19,29 +19,25 @@ acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" -acorn@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.1.1.tgz#53fe161111f912ab999ee887a90a0bc52822fd75" - -ajv-keywords@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" +acorn@^5.5.0: + version "5.7.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" + integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== -ajv@^4.7.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" +ajv-keywords@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" + integrity sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I= -ajv@^5.2.0: - version "5.2.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.2.2.tgz#47c68d69e86f5d953103b0074a9430dc63da5e39" +ajv@^5.2.3, ajv@^5.3.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= dependencies: co "^4.6.0" fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.3.0" - json-stable-stringify "^1.0.1" ansi-colors@3.2.3: version "3.2.3" @@ -69,12 +65,6 @@ ansi-styles@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" -ansi-styles@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" - dependencies: - color-convert "^1.9.0" - ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -170,7 +160,7 @@ camelcase@^5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: +chalk@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: @@ -180,15 +170,7 @@ chalk@^1.1.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.0.1.tgz#dbec49436d2ae15f536114e76d14656cdbc0f44d" - dependencies: - ansi-styles "^3.1.0" - escape-string-regexp "^1.0.5" - supports-color "^4.0.0" - -chalk@^2.0.1: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -272,7 +254,7 @@ curry@0.0.x: version "0.0.4" resolved "https://registry.yarnpkg.com/curry/-/curry-0.0.4.tgz#1750d518d919c44f3d37ff44edc693de1f0d5fcb" -debug@3.2.6: +debug@3.2.6, debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== @@ -326,12 +308,12 @@ doctrine@1.5.0: esutils "^2.0.2" isarray "^1.0.0" -doctrine@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.0.0.tgz#c73d8d2909d22291e1a007a395804da8b665fe63" +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== dependencies: esutils "^2.0.2" - isarray "^1.0.0" emoji-regex@^7.0.1: version "7.0.3" @@ -430,32 +412,38 @@ eslint-scope@^3.7.1: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-visitor-keys@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== + eslint@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.4.0.tgz#a3e153e704b64f78290ef03592494eaba228d3bc" + version "4.18.2" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.18.2.tgz#0f81267ad1012e7d2051e186a9004cc2267b8d45" + integrity sha512-qy4i3wODqKMYfz9LUI8N2qYDkHkoieTbiHpMrYUI/WbjhXJQr7lI4VngixTgaG+yHX+NBCv7nW4hA0ShbvaNKw== dependencies: - ajv "^5.2.0" + ajv "^5.3.0" babel-code-frame "^6.22.0" - chalk "^1.1.3" + chalk "^2.1.0" concat-stream "^1.6.0" cross-spawn "^5.1.0" - debug "^2.6.8" - doctrine "^2.0.0" + debug "^3.1.0" + doctrine "^2.1.0" eslint-scope "^3.7.1" - espree "^3.5.0" + eslint-visitor-keys "^1.0.0" + espree "^3.5.2" esquery "^1.0.0" - estraverse "^4.2.0" esutils "^2.0.2" file-entry-cache "^2.0.0" functional-red-black-tree "^1.0.1" glob "^7.1.2" - globals "^9.17.0" + globals "^11.0.1" ignore "^3.3.3" imurmurhash "^0.1.4" inquirer "^3.0.6" is-resolvable "^1.0.0" js-yaml "^3.9.1" - json-stable-stringify "^1.0.1" + json-stable-stringify-without-jsonify "^1.0.1" levn "^0.3.0" lodash "^4.17.4" minimatch "^3.0.2" @@ -463,19 +451,21 @@ eslint@^4.4.0: natural-compare "^1.4.0" optionator "^0.8.2" path-is-inside "^1.0.2" - pluralize "^4.0.0" + pluralize "^7.0.0" progress "^2.0.0" require-uncached "^1.0.3" semver "^5.3.0" + strip-ansi "^4.0.0" strip-json-comments "~2.0.1" - table "^4.0.1" + table "4.0.2" text-table "~0.2.0" -espree@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.0.tgz#98358625bdd055861ea27e2867ea729faf463d8d" +espree@^3.5.2: + version "3.5.4" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" + integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== dependencies: - acorn "^5.1.1" + acorn "^5.5.0" acorn-jsx "^3.0.0" esprima@^4.0.0: @@ -496,7 +486,7 @@ esrecurse@^4.1.0: estraverse "^4.1.0" object-assign "^4.0.1" -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: version "4.2.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" @@ -516,6 +506,11 @@ fast-deep-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + fast-levenshtein@~2.0.4: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" @@ -599,7 +594,7 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -glob@7.1.3: +glob@7.1.3, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== @@ -611,20 +606,10 @@ glob@7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^9.17.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" +globals@^11.0.1: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== globby@^5.0.0: version "5.0.0" @@ -652,10 +637,6 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" -has-flag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -827,15 +808,10 @@ json-schema-traverse@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" -json-stable-stringify@^1.0.1: +json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - dependencies: - jsonify "~0.0.0" - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= jsonparse@0.0.5: version "0.0.5" @@ -876,11 +852,7 @@ lodash.cond@^4.3.0: version "4.5.2" resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" -lodash@^4.0.0, lodash@^4.17.4, lodash@^4.3.0: - version "4.17.4" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" - -lodash@^4.17.15: +lodash@^4.17.15, lodash@^4.17.4, lodash@^4.3.0: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -1189,9 +1161,10 @@ pkg-dir@^1.0.0: dependencies: find-up "^1.0.0" -pluralize@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-4.0.0.tgz#59b708c1c0190a2f692f1c7618c446b052fd1762" +pluralize@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" + integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== postgres-array@~2.0.0: version "2.0.0" @@ -1327,18 +1300,18 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" -"semver@2 || 3 || 4 || 5", semver@5.3.0, semver@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" +"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.7.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== semver@4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" -semver@^5.7.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== +semver@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" set-blocking@^2.0.0: version "2.0.0" @@ -1359,9 +1332,12 @@ signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" +slice-ansi@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== + dependencies: + is-fullwidth-code-point "^2.0.0" spdx-correct@~1.0.0: version "1.0.2" @@ -1402,7 +1378,7 @@ stream-tester@0.0.5: from "~0.0.2" through "~0.0.3" -"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0: +"string-width@^1.0.2 || 2", string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" dependencies: @@ -1478,12 +1454,6 @@ supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" -supports-color@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.2.1.tgz#65a4bb2631e90e02420dba5554c375a4754bb836" - dependencies: - has-flag "^2.0.0" - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -1491,16 +1461,17 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -table@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/table/-/table-4.0.1.tgz#a8116c133fac2c61f4a420ab6cdf5c4d61f0e435" - dependencies: - ajv "^4.7.0" - ajv-keywords "^1.0.0" - chalk "^1.1.1" - lodash "^4.0.0" - slice-ansi "0.0.4" - string-width "^2.0.0" +table@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" + integrity sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA== + dependencies: + ajv "^5.2.3" + ajv-keywords "^2.1.0" + chalk "^2.1.0" + lodash "^4.17.4" + slice-ansi "1.0.0" + string-width "^2.1.1" text-table@~0.2.0: version "0.2.0" From 08072a90b8620d8dc70881e96afcb61f661e0735 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 30 Oct 2019 14:08:11 -0500 Subject: [PATCH 0510/1037] Pass options to cursor (#65) * Bump version of pg-cursor This includes fixes in pg-cursor@2.0.1. I've relaxed semver a touch so I don't have to release a new version here just for patch changes to pg-cursor. * Pass options to pg-cursor fixes #55 --- index.js | 2 +- test/passing-options.js | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 test/passing-options.js diff --git a/index.js b/index.js index ddfc66f12..9c34207ec 100644 --- a/index.js +++ b/index.js @@ -5,7 +5,7 @@ var Readable = require('stream').Readable class PgQueryStream extends Readable { constructor (text, values, options) { super(Object.assign({ objectMode: true }, options)) - this.cursor = new Cursor(text, values) + this.cursor = new Cursor(text, values, options) this._reading = false this._closed = false this.batchSize = (options || {}).batchSize || 100 diff --git a/test/passing-options.js b/test/passing-options.js new file mode 100644 index 000000000..e2ddd1857 --- /dev/null +++ b/test/passing-options.js @@ -0,0 +1,38 @@ +var assert = require('assert') +var helper = require('./helper') +var QueryStream = require('../') + +helper('passing options', function(client) { + it('passes row mode array', function(done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { rowMode: 'array' }) + var query = client.query(stream) + var result = [] + query.on('data', datum => { + result.push(datum) + }) + query.on('end', () => { + const expected = new Array(11).fill(0).map((_, i) => [i]) + assert.deepEqual(result, expected) + done() + }) + }) + + it('passes custom types', function(done) { + const types = { + getTypeParser: () => string => string, + } + var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { types }) + var query = client.query(stream) + var result = [] + query.on('data', datum => { + result.push(datum) + }) + query.on('end', () => { + const expected = new Array(11).fill(0).map((_, i) => ({ + num: i.toString(), + })) + assert.deepEqual(result, expected) + done() + }) + }) +}) From 9ced05e8aab65f3fdf1a67add87bfc9035e487e8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 30 Oct 2019 14:08:45 -0500 Subject: [PATCH 0511/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 35d5b5a30..4bc8b1b24 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "2.0.0", + "version": "2.0.1", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { From caa65179990fc524026c895aebe712d05ec4dc0e Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Mon, 11 Nov 2019 10:10:19 -0800 Subject: [PATCH 0512/1037] Fix disconnection tests for pg-pool 2.0.7 (#1946) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Require latest pg-pool ^2.0.7 to limit variability of next pg’s installations. * Ignore EPIPE when writing termination message I don’t know why this wasn’t necessary for tests to pass before… * Fix disconnection tests for pg-pool 2.0.7 In pg-pool 2.0.7, checked-out clients became responsible for their own 'error' events. brianc/node-pg-pool#123 --- lib/connection.js | 5 ++- package.json | 2 +- .../connection-pool/error-tests.js | 32 +++++++++---------- test/integration/gh-issues/130-tests.js | 14 ++++---- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 48d65d25f..489a5afd9 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -64,9 +64,8 @@ Connection.prototype.connect = function (port, host) { }) const reportStreamError = function (error) { - // don't raise ECONNRESET errors - they can & should be ignored - // during disconnect - if (self._ending && error.code === 'ECONNRESET') { + // errors about disconnections should be ignored during disconnect + if (self._ending && (error.code === 'ECONNRESET' || error.code === 'EPIPE')) { return } self.emit('error', error) diff --git a/package.json b/package.json index 9eaf4c256..66e399bc1 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "0.1.3", - "pg-pool": "^2.0.4", + "pg-pool": "^2.0.7", "pg-types": "^2.1.0", "pgpass": "1.x", "semver": "4.3.2" diff --git a/test/integration/connection-pool/error-tests.js b/test/integration/connection-pool/error-tests.js index cadffe3db..597c29b38 100644 --- a/test/integration/connection-pool/error-tests.js +++ b/test/integration/connection-pool/error-tests.js @@ -8,15 +8,13 @@ suite.test('connecting to invalid port', (cb) => { pool.connect().catch(e => cb()) }) -suite.test('errors emitted on pool', (cb) => { +suite.test('errors emitted on checked-out clients', (cb) => { // make pool hold 2 clients const pool = new pg.Pool({ max: 2 }) // get first client pool.connect(assert.success(function (client, done) { - client.id = 1 client.query('SELECT NOW()', function () { pool.connect(assert.success(function (client2, done2) { - client2.id = 2 var pidColName = 'procpid' helper.versionGTE(client2, 90200, assert.success(function (isGreater) { var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1' @@ -26,10 +24,9 @@ suite.test('errors emitted on pool', (cb) => { params = ['%IDLE%'] } - pool.once('error', (err, brokenClient) => { - assert.ok(err) - assert.ok(brokenClient) - assert.equal(client.id, brokenClient.id) + client.once('error', (err) => { + client.on('error', (err) => {}) + done(err) cb() }) @@ -57,18 +54,18 @@ suite.test('connection-level errors cause queued queries to fail', (cb) => { } })) - pool.once('error', assert.calls((err, brokenClient) => { - assert.equal(client, brokenClient) + client.once('error', assert.calls((err) => { + client.on('error', (err) => {}) })) client.query('SELECT 1', assert.calls((err) => { if (helper.args.native) { - assert.ok(err) + assert.equal(err.message, 'terminating connection due to administrator command') } else { assert.equal(err.message, 'Connection terminated unexpectedly') } - done() + done(err) pool.end() cb() })) @@ -86,13 +83,16 @@ suite.test('connection-level errors cause future queries to fail', (cb) => { } })) - pool.once('error', assert.calls((err, brokenClient) => { - assert.equal(client, brokenClient) - + client.once('error', assert.calls((err) => { + client.on('error', (err) => {}) client.query('SELECT 1', assert.calls((err) => { - assert.equal(err.message, 'Client has encountered a connection error and is not queryable') + if (helper.args.native) { + assert.equal(err.message, 'terminating connection due to administrator command') + } else { + assert.equal(err.message, 'Client has encountered a connection error and is not queryable') + } - done() + done(err) pool.end() cb() })) diff --git a/test/integration/gh-issues/130-tests.js b/test/integration/gh-issues/130-tests.js index b3e2a2252..db3aeacd5 100644 --- a/test/integration/gh-issues/130-tests.js +++ b/test/integration/gh-issues/130-tests.js @@ -5,19 +5,21 @@ var exec = require('child_process').exec helper.pg.defaults.poolIdleTimeout = 1000 const pool = new helper.pg.Pool() -pool.connect(function (err, client) { +pool.connect(function (err, client, done) { + assert.ifError(err) + client.once('error', function (err) { + client.on('error', (err) => {}) + done(err) + }) client.query('SELECT pg_backend_pid()', function (err, result) { + assert.ifError(err) var pid = result.rows[0].pg_backend_pid var psql = 'psql' if (helper.args.host) psql = psql + ' -h ' + helper.args.host if (helper.args.port) psql = psql + ' -p ' + helper.args.port if (helper.args.user) psql = psql + ' -U ' + helper.args.user exec(psql + ' -c "select pg_terminate_backend(' + pid + ')" template1', assert.calls(function (error, stdout, stderr) { - assert.isNull(error) + assert.ifError(error) })) }) }) - -pool.on('error', function (err, client) { - // swallow errors -}) From cd66c0b2611f01141832c9d0849db687b674bdf7 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Mon, 11 Nov 2019 13:11:24 -0500 Subject: [PATCH 0513/1037] Add explicit files list to package.json (#1951) --- .npmignore | 10 ---------- package.json | 4 ++++ 2 files changed, 4 insertions(+), 10 deletions(-) delete mode 100644 .npmignore diff --git a/.npmignore b/.npmignore deleted file mode 100644 index 6223e474b..000000000 --- a/.npmignore +++ /dev/null @@ -1,10 +0,0 @@ -*~ -build/ -.lock-wscript -*.log -node_modules/ -script/ -*.swp -test/ -.travis.yml -ci_scripts/ diff --git a/package.json b/package.json index 66e399bc1..4f7a2fa11 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,10 @@ "scripts": { "test": "make test-all" }, + "files": [ + "lib", + "SPONSORS.md" + ], "license": "MIT", "engines": { "node": ">= 4.5.0" From 06fbe19923432b2e841d0db7e76fa6ad746940d4 Mon Sep 17 00:00:00 2001 From: Justin Merz Date: Mon, 11 Nov 2019 10:18:52 -0800 Subject: [PATCH 0514/1037] Skip TLS SNI if host is IP address (#1890) * skip TLS SNI if host is IP address (do not set servername option in tls.connect) * Format code --- lib/connection.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 489a5afd9..5ca746a79 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -91,9 +91,8 @@ Connection.prototype.connect = function (port, host) { return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') - self.stream = tls.connect({ + const options = { socket: self.stream, - servername: host, checkServerIdentity: self.ssl.checkServerIdentity || tls.checkServerIdentity, rejectUnauthorized: self.ssl.rejectUnauthorized, ca: self.ssl.ca, @@ -103,7 +102,11 @@ Connection.prototype.connect = function (port, host) { cert: self.ssl.cert, secureOptions: self.ssl.secureOptions, NPNProtocols: self.ssl.NPNProtocols - }) + } + if (net.isIP(host) === 0) { + options.servername = host + } + self.stream = tls.connect(options) self.attachListeners(self.stream) self.stream.on('error', reportStreamError) From c8c41c5b6557c8919d53a9cf7d33d4ca6287e1c9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2019 10:02:08 -0600 Subject: [PATCH 0515/1037] Bump lodash from 4.17.11 to 4.17.13 (#136) Bumps [lodash](https://github.com/lodash/lodash) from 4.17.11 to 4.17.13. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.11...4.17.13) Signed-off-by: dependabot[bot] --- package-lock.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4099fbfd7..08410f56b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -553,7 +553,7 @@ "dependencies": { "debug": { "version": "0.7.4", - "resolved": "http://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=", "dev": true }, @@ -619,7 +619,7 @@ "dependencies": { "babylon": { "version": "6.14.1", - "resolved": "http://registry.npmjs.org/babylon/-/babylon-6.14.1.tgz", + "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.14.1.tgz", "integrity": "sha1-lWJ1+rcnU62bNDXXr+WPi/CimBU=", "dev": true } @@ -1172,9 +1172,9 @@ } }, "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", + "version": "4.17.13", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.13.tgz", + "integrity": "sha512-vm3/XWXfWtRua0FkUyEHBZy8kCPjErNBT9fJx8Zvs+U6zjqPbTUOpkaoum3O5uiA8sm+yNMHXfYkTUHFoMxFNA==", "dev": true }, "loose-envify": { @@ -1756,7 +1756,7 @@ }, "semver": { "version": "4.3.2", - "resolved": "http://registry.npmjs.org/semver/-/semver-4.3.2.tgz", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=", "dev": true }, @@ -1920,7 +1920,7 @@ }, "strip-ansi": { "version": "3.0.1", - "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { From ced31dd9115d594b62a7376032f853be115f3972 Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 19 Nov 2019 10:10:09 -0600 Subject: [PATCH 0516/1037] Update SPONSORS.md --- SPONSORS.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/SPONSORS.md b/SPONSORS.md index 29aae9e02..6e3ba707e 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -5,6 +5,7 @@ node-postgres is made possible by the helpful contributors from the community we - [MadKudu](https://www.madkudu.com) - [@madkudu](https://twitter.com/madkudu) - [Third Iron](https://thirdiron.com/) - [Timescale](https://timescale.com) +- [Nafundi](https://nafundi.com) # Supporters @@ -23,3 +24,8 @@ node-postgres is made possible by the helpful contributors from the community we - Franklin Davenport - [Eventbot](https://geteventbot.com/) - Chuck T +- Paul Cothenet +- Pelle Wessman +- Raul Murray +- Simple Analytics +- Trevor Linton From bf029c827049ca16add0a862d40f4e60dfd9e602 Mon Sep 17 00:00:00 2001 From: Jim Geurts Date: Tue, 19 Nov 2019 10:10:19 -0600 Subject: [PATCH 0517/1037] Support additional tls.connect() options (#1996) * Support additional tls.connect() options * Pass-through all ssl options to tls.connect() * Fix lint error * Remove tls.checkServerIdentity explicit option --- lib/connection.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 5ca746a79..cdcb0cbb3 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -91,18 +91,9 @@ Connection.prototype.connect = function (port, host) { return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') - const options = { - socket: self.stream, - checkServerIdentity: self.ssl.checkServerIdentity || tls.checkServerIdentity, - rejectUnauthorized: self.ssl.rejectUnauthorized, - ca: self.ssl.ca, - pfx: self.ssl.pfx, - key: self.ssl.key, - passphrase: self.ssl.passphrase, - cert: self.ssl.cert, - secureOptions: self.ssl.secureOptions, - NPNProtocols: self.ssl.NPNProtocols - } + const options = Object.assign({ + socket: self.stream + }, self.ssl) if (net.isIP(host) === 0) { options.servername = host } From eac3e4dcaf1eea4350f682cf2e32763c2d102bf3 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 19 Nov 2019 10:44:23 -0600 Subject: [PATCH 0518/1037] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7792612f9..6d447437a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.13.0 + +- Add support for [all tls.connect()](https://github.com/brianc/node-postgres/pull/1996) options. + ### 7.12.0 - Add support for [async password lookup](https://github.com/brianc/node-postgres/pull/1926). From c10a96c54d5895ebdc1c7e3e4eb582a637660b9f Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 19 Nov 2019 10:44:31 -0600 Subject: [PATCH 0519/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4f7a2fa11..ce1b09783 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.12.1", + "version": "7.13.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 510a273ce45fb73d0355cf384e97ea695c8a5bcc Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 20 Nov 2019 10:12:02 -0600 Subject: [PATCH 0520/1037] Revert "Support additional tls.connect() options (#1996)" (#2010) This reverts commit bf029c827049ca16add0a862d40f4e60dfd9e602. --- lib/connection.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index cdcb0cbb3..5ca746a79 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -91,9 +91,18 @@ Connection.prototype.connect = function (port, host) { return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') - const options = Object.assign({ - socket: self.stream - }, self.ssl) + const options = { + socket: self.stream, + checkServerIdentity: self.ssl.checkServerIdentity || tls.checkServerIdentity, + rejectUnauthorized: self.ssl.rejectUnauthorized, + ca: self.ssl.ca, + pfx: self.ssl.pfx, + key: self.ssl.key, + passphrase: self.ssl.passphrase, + cert: self.ssl.cert, + secureOptions: self.ssl.secureOptions, + NPNProtocols: self.ssl.NPNProtocols + } if (net.isIP(host) === 0) { options.servername = host } From b05ea526b80d85a80e2efdcc616810a73bb59b35 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 20 Nov 2019 10:14:04 -0600 Subject: [PATCH 0521/1037] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d447437a..59a692b7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.14.0 + +- Reverts 7.13.0 as it contained [an accidental breaking change](https://github.com/brianc/node-postgres/pull/2010) for self-signed SSL cert verification. 7.14.0 is identical to 7.12.1. + ### 7.13.0 - Add support for [all tls.connect()](https://github.com/brianc/node-postgres/pull/1996) options. From 30f67bb246cabfc6a9d4cd026e6abedbcd0e2239 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 20 Nov 2019 10:14:48 -0600 Subject: [PATCH 0522/1037] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ce1b09783..5d0653724 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.13.0", + "version": "7.14.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 8f56b8c2fd97119f23215af543eec90bbcee959b Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 20 Nov 2019 15:38:40 -0800 Subject: [PATCH 0523/1037] Add PostgreSQL 10 to CI (#1947) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Exit with error code when create-test-tables fails * Add PostgreSQL 10 to CI and change to Ubuntu 18.04 so building OpenSSL isn’t necessary, and move old PostgreSQL version tests to the latest Node LTS. * Add Node 13 to CI * Preserve create-test-tables’s compatibility with PostgreSQL <9.4 --- .travis.yml | 64 +++++++++++++++++++---------------- ci_scripts/build.sh | 9 ----- ci_scripts/install_libpq.sh | 38 --------------------- ci_scripts/install_openssl.sh | 35 ------------------- script/create-test-tables.js | 42 +++++++++++++++++------ 5 files changed, 66 insertions(+), 122 deletions(-) delete mode 100644 ci_scripts/build.sh delete mode 100644 ci_scripts/install_libpq.sh delete mode 100644 ci_scripts/install_openssl.sh diff --git a/.travis.yml b/.travis.yml index ee95ab265..94b3da4e7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,50 +1,56 @@ language: node_js -sudo: true -dist: trusty +dist: bionic before_script: - node script/create-test-tables.js pg://postgres@127.0.0.1:5432/postgres - -before_install: - - if [ $TRAVIS_OS_NAME == "linux" ]; then - if [[ $(node -v) =~ v[1-9][0-9] ]]; then - source ./ci_scripts/build.sh; - fi - fi - + env: - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres +node_js: + - lts/dubnium + - lts/erbium + - 13 + +addons: + postgresql: "10" + matrix: include: - - node_js: "lts/boron" - addons: - postgresql: "9.6" - - node_js: "lts/argon" - addons: - postgresql: "9.6" - - node_js: "10" + # different Node versions on PostgreSQL 9.5 that require precise + - node_js: lts/argon addons: - postgresql: "9.6" - - node_js: "12" - addons: - postgresql: "9.6" - - node_js: "lts/carbon" + postgresql: "9.5" + dist: precise + - node_js: lts/boron addons: - postgresql: "9.1" + postgresql: "9.5" dist: precise - - node_js: "lts/carbon" + - node_js: lts/carbon addons: - postgresql: "9.2" - - node_js: "lts/carbon" + postgresql: "9.5" + dist: precise + + # different PostgreSQL versions on Node LTS + - node_js: lts/erbium addons: postgresql: "9.3" - - node_js: "lts/carbon" + - node_js: lts/erbium addons: postgresql: "9.4" - - node_js: "lts/carbon" + - node_js: lts/erbium addons: postgresql: "9.5" - - node_js: "lts/carbon" + - node_js: lts/erbium addons: postgresql: "9.6" + + # PostgreSQL 9.1 and 9.2 only work on precise + - node_js: lts/carbon + addons: + postgresql: "9.1" + dist: precise + - node_js: lts/carbon + addons: + postgresql: "9.2" + dist: precise diff --git a/ci_scripts/build.sh b/ci_scripts/build.sh deleted file mode 100644 index 707bf4d55..000000000 --- a/ci_scripts/build.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -BUILD_DIR="$(pwd)" -source ./ci_scripts/install_openssl.sh 1.1.1b -sudo updatedb -source ./ci_scripts/install_libpq.sh -sudo updatedb -sudo ldconfig -cd $BUILD_DIR diff --git a/ci_scripts/install_libpq.sh b/ci_scripts/install_libpq.sh deleted file mode 100644 index 936c7d645..000000000 --- a/ci_scripts/install_libpq.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -set -e - -OPENSSL_DIR="$(pwd)/openssl-1.1.1b" -POSTGRES_VERSION="11.3" -POSTGRES_DIR="$(pwd)/postgres-${POSTGRES_VERSION}" -TMP_DIR="/tmp/postgres" -JOBS="-j$(nproc || echo 1)" - -if [ -d "${TMP_DIR}" ]; then - rm -rf "${TMP_DIR}" -fi - -mkdir -p "${TMP_DIR}" - -curl https://ftp.postgresql.org/pub/source/v${POSTGRES_VERSION}/postgresql-${POSTGRES_VERSION}.tar.gz | \ - tar -C "${TMP_DIR}" -xzf - - -cd "${TMP_DIR}/postgresql-${POSTGRES_VERSION}" - -if [ -d "${POSTGRES_DIR}" ]; then - rm -rf "${POSTGRES_DIR}" -fi -mkdir -p $POSTGRES_DIR - -./configure --prefix=$POSTGRES_DIR --with-openssl --with-includes=${OPENSSL_DIR}/include --with-libraries=${OPENSSL_DIR}/lib --without-readline - -cd src/interfaces/libpq; make; make install; cd - -cd src/bin/pg_config; make install; cd - -cd src/backend; make generated-headers; cd - -cd src/include; make install; cd - - -export PATH="${POSTGRES_DIR}/bin:${PATH}" -export CFLAGS="-I${POSTGRES_DIR}/include" -export LDFLAGS="-L${POSTGRES_DIR}/lib" -export LD_LIBRARY_PATH="${POSTGRES_DIR}/lib:$LD_LIBRARY_PATH" -export PKG_CONFIG_PATH="${POSTGRES_DIR}/lib/pkgconfig:$PKG_CONFIG_PATH" diff --git a/ci_scripts/install_openssl.sh b/ci_scripts/install_openssl.sh deleted file mode 100644 index 24c0d3a5a..000000000 --- a/ci_scripts/install_openssl.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/bin/sh - -if [ ${#} -lt 1 ]; then - echo "OpenSSL version required." 1>&2 - exit 1 -fi - -OPENSSL_VERSION="${1}" -OPENSSL_DIR="$(pwd)/openssl-${OPENSSL_VERSION}" -TMP_DIR="/tmp/openssl" -JOBS="-j$(nproc)" - -if [ -d "${TMP_DIR}" ]; then - rm -rf "${TMP_DIR}" -fi -mkdir -p "${TMP_DIR}" -curl -s https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz | \ - tar -C "${TMP_DIR}" -xzf - -pushd "${TMP_DIR}/openssl-${OPENSSL_VERSION}" -if [ -d "${OPENSSL_DIR}" ]; then - rm -rf "${OPENSSL_DIR}" -fi -./Configure \ - --prefix=${OPENSSL_DIR} \ - enable-crypto-mdebug enable-crypto-mdebug-backtrace \ - linux-x86_64 -make -s $JOBS -make install_sw -popd - -export PATH="${OPENSSL_DIR}/bin:${PATH}" -export CFLAGS="-I${OPENSSL_DIR}/include" -export LDFLAGS="-L${OPENSSL_DIR}/lib" -export LD_LIBRARY_PATH="${OPENSSL_DIR}/lib:$LD_LIBRARY_PATH" -export PKG_CONFIG_PATH="${OPENSSL_DIR}/lib/pkgconfig:$PKG_CONFIG_PATH" diff --git a/script/create-test-tables.js b/script/create-test-tables.js index c887629ec..e2110313a 100644 --- a/script/create-test-tables.js +++ b/script/create-test-tables.js @@ -38,15 +38,35 @@ var con = new pg.Client({ password: args.password, database: args.database }) -con.connect() -var query = con.query('drop table if exists person') -con.query('create table person(id serial, name varchar(10), age integer)', (err, res) => { - console.log('Created table person') - console.log('Filling it with people') -}) -people.map(function (person) { - return con.query(new pg.Query("insert into person(name, age) values('" + person.name + "', '" + person.age + "')")) -}).pop().on('end', function () { - console.log('Inserted 26 people') - con.end() + +con.connect((err) => { + if (err) { + throw err + } + + con.query( + 'DROP TABLE IF EXISTS person;' + + ' CREATE TABLE person (id serial, name varchar(10), age integer)', + (err) => { + if (err) { + throw err + } + + console.log('Created table person') + console.log('Filling it with people') + + con.query( + 'INSERT INTO person (name, age) VALUES' + + people + .map((person) => ` ('${person.name}', ${person.age})`) + .join(','), + (err, result) => { + if (err) { + throw err + } + + console.log(`Inserted ${result.rowCount} people`) + con.end() + }) + }) }) From b03a3bd76d78963efc93119b5f583bbc22b9caa6 Mon Sep 17 00:00:00 2001 From: Adam Nielsen Date: Fri, 13 Dec 2019 02:15:19 +1000 Subject: [PATCH 0524/1037] Clear connection timeout on error (#2015) Cancel the connection timeout upon stream error, to avoid getting a stream error followed later by a connection error. --- lib/client.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/client.js b/lib/client.js index cca5e66e8..370630a02 100644 --- a/lib/client.js +++ b/lib/client.js @@ -251,6 +251,7 @@ Client.prototype._connect = function (callback) { ? new Error('Connection terminated') : new Error('Connection terminated unexpectedly') + clearTimeout(connectionTimeoutHandle) this._errorAllQueries(error) if (!this._ending) { From c1f954b7a63f619c9c1085546119c4bfcf464b0d Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Thu, 12 Dec 2019 08:15:53 -0800 Subject: [PATCH 0525/1037] Remove unreachable branch in `parseE` (#2020) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The message is created with a fixed name. 56b7c4168d5aa084b2821279ee88d437a2b7636d, released in pg 2.4.0, was when this became applicable and the type of a `notice` event’s argument changed to an Error. --- lib/connection.js | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/lib/connection.js b/lib/connection.js index 5ca746a79..4fae92083 100644 --- a/lib/connection.js +++ b/lib/connection.js @@ -594,27 +594,19 @@ Connection.prototype._readValue = function (buffer) { // parses error Connection.prototype.parseE = function (buffer, length) { var fields = {} - var msg, item - var input = new Message('error', length) var fieldType = this.readString(buffer, 1) while (fieldType !== '\0') { fields[fieldType] = this.parseCString(buffer) fieldType = this.readString(buffer, 1) } - if (input.name === 'error') { - // the msg is an Error instance - msg = new Error(fields.M) - for (item in input) { - // copy input properties to the error - if (Object.prototype.hasOwnProperty.call(input, item)) { - msg[item] = input[item] - } - } - } else { - // the msg is an object literal - msg = input - msg.message = fields.M - } + + // the msg is an Error instance + var msg = new Error(fields.M) + + // for compatibility with Message + msg.name = 'error' + msg.length = length + msg.severity = fields.S msg.code = fields.C msg.detail = fields.D From 124c89b173ca0d6faa9a9509b0b029aa4e864fe0 Mon Sep 17 00:00:00 2001 From: Hetul Patel Date: Fri, 13 Dec 2019 15:30:40 -0800 Subject: [PATCH 0526/1037] fix lint issues --- test/close.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/close.js b/test/close.js index b1557a6ac..23fb7f9de 100644 --- a/test/close.js +++ b/test/close.js @@ -14,13 +14,12 @@ describe('close', function() { const cursor = new Cursor(text) this.client.query(cursor) this.client.query('SELECT NOW()', done) - cursor.read(100, function (err, res) { + cursor.read(100, function(err) { assert.ifError(err) cursor.close() }) }) - it('closes cursor early', function(done) { const cursor = new Cursor(text) this.client.query(cursor) From 2b59209cf3ca816ac3271c8592143c06263873c3 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 17 Dec 2019 08:02:38 -0800 Subject: [PATCH 0527/1037] Warn when functions intended as constructors are called without new (#2021) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Warn when pg.Pool() isn’t called as a constructor in preparation for #1541. `eval` is a bit awkward, but it’s more accurate than an `instanceof` check and will work on platforms new enough to support pg 8 (i.e. only not Node 4). * Warn when Query() isn’t called as a constructor --- lib/compat/check-constructor.js | 22 ++++++++++++++++++++++ lib/compat/warn-deprecation.js | 19 +++++++++++++++++++ lib/index.js | 4 ++++ lib/query.js | 5 ++++- 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 lib/compat/check-constructor.js create mode 100644 lib/compat/warn-deprecation.js diff --git a/lib/compat/check-constructor.js b/lib/compat/check-constructor.js new file mode 100644 index 000000000..5920633a0 --- /dev/null +++ b/lib/compat/check-constructor.js @@ -0,0 +1,22 @@ +'use strict' + +const warnDeprecation = require('./warn-deprecation') + +// Node 4 doesn’t support new.target. +let hasNewTarget + +try { + // eslint-disable-next-line no-eval + eval('(function () { new.target })') + hasNewTarget = true +} catch (error) { + hasNewTarget = false +} + +const checkConstructor = (name, code, getNewTarget) => { + if (hasNewTarget && getNewTarget() === undefined) { + warnDeprecation(`Constructing a ${name} without new is deprecated and will stop working in pg 8.`, code) + } +} + +module.exports = checkConstructor diff --git a/lib/compat/warn-deprecation.js b/lib/compat/warn-deprecation.js new file mode 100644 index 000000000..362183558 --- /dev/null +++ b/lib/compat/warn-deprecation.js @@ -0,0 +1,19 @@ +'use strict' + +const util = require('util') + +const dummyFunctions = new Map() + +// Node 4 doesn’t support process.emitWarning(message, 'DeprecationWarning', code). +const emitDeprecationWarning = (message, code) => { + let dummy = dummyFunctions.get(code) + + if (dummy === undefined) { + dummy = util.deprecate(() => {}, message) + dummyFunctions.set(code, dummy) + } + + dummy() +} + +module.exports = emitDeprecationWarning diff --git a/lib/index.js b/lib/index.js index 8e000a378..de33c086d 100644 --- a/lib/index.js +++ b/lib/index.js @@ -12,9 +12,13 @@ var Client = require('./client') var defaults = require('./defaults') var Connection = require('./connection') var Pool = require('pg-pool') +const checkConstructor = require('./compat/check-constructor') const poolFactory = (Client) => { var BoundPool = function (options) { + // eslint-disable-next-line no-eval + checkConstructor('pg.Pool', 'PG-POOL-NEW', () => eval('new.target')) + var config = Object.assign({ Client: Client }, options) return new Pool(config) } diff --git a/lib/query.js b/lib/query.js index 250e8950d..548380fe1 100644 --- a/lib/query.js +++ b/lib/query.js @@ -9,12 +9,15 @@ var EventEmitter = require('events').EventEmitter var util = require('util') +const checkConstructor = require('./compat/check-constructor') var Result = require('./result') var utils = require('./utils') var Query = function (config, values, callback) { - // use of "new" optional + // use of "new" optional in pg 7 + // eslint-disable-next-line no-eval + checkConstructor('Query', 'PG-QUERY-NEW', () => eval('new.target')) if (!(this instanceof Query)) { return new Query(config, values, callback) } config = utils.normalizeQueryConfig(config, values, callback) From 1b5f3e33c45bb6d2e2084b00840fbe58035f6db7 Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 17 Dec 2019 08:32:08 -0800 Subject: [PATCH 0528/1037] Monorepo (#2014) * First crack at monorepo * Update test command * Update path to script * Remove node 6 from CI --- .travis.yml | 11 +- lerna.json | 8 + package.json | 60 +- Makefile => packages/pg/Makefile | 0 {lib => packages/pg/lib}/client.js | 0 .../pg/lib}/compat/check-constructor.js | 0 .../pg/lib}/compat/warn-deprecation.js | 0 .../pg/lib}/connection-parameters.js | 0 {lib => packages/pg/lib}/connection.js | 0 {lib => packages/pg/lib}/defaults.js | 0 {lib => packages/pg/lib}/index.js | 0 {lib => packages/pg/lib}/native/client.js | 0 {lib => packages/pg/lib}/native/index.js | 0 {lib => packages/pg/lib}/native/query.js | 0 {lib => packages/pg/lib}/query.js | 0 {lib => packages/pg/lib}/result.js | 0 {lib => packages/pg/lib}/sasl.js | 0 {lib => packages/pg/lib}/type-overrides.js | 0 {lib => packages/pg/lib}/utils.js | 0 packages/pg/package.json | 54 + .../pg/script}/create-test-tables.js | 0 .../pg/script}/dump-db-types.js | 0 .../pg/script}/list-db-types.js | 0 {test => packages/pg/test}/buffer-list.js | 0 {test => packages/pg/test}/cli.js | 0 .../pg/test}/integration/client/api-tests.js | 0 .../test}/integration/client/appname-tests.js | 0 .../test}/integration/client/array-tests.js | 0 .../client/big-simple-query-tests.js | 0 .../integration/client/configuration-tests.js | 0 .../client/connection-timeout-tests.js | 0 .../integration/client/custom-types-tests.js | 0 .../integration/client/empty-query-tests.js | 0 .../client/error-handling-tests.js | 0 .../client/field-name-escape-tests.js | 0 .../integration/client/huge-numeric-tests.js | 0 .../client/json-type-parsing-tests.js | 0 .../client/multiple-results-tests.js | 0 .../client/network-partition-tests.js | 0 .../test}/integration/client/no-data-tests.js | 0 .../integration/client/no-row-result-tests.js | 0 .../test}/integration/client/notice-tests.js | 0 .../integration/client/parse-int-8-tests.js | 0 .../client/prepared-statement-tests.js | 0 .../integration/client/promise-api-tests.js | 0 .../client/query-as-promise-tests.js | 0 .../client/query-column-names-tests.js | 0 ...error-handling-prepared-statement-tests.js | 0 .../client/query-error-handling-tests.js | 0 .../client/quick-disconnect-tests.js | 0 .../client/result-metadata-tests.js | 0 .../client/results-as-array-tests.js | 0 .../row-description-on-results-tests.js | 0 .../integration/client/sasl-scram-tests.js | 0 .../integration/client/simple-query-tests.js | 0 .../pg/test}/integration/client/ssl-tests.js | 0 .../client/statement_timeout-tests.js | 0 .../test}/integration/client/test-helper.js | 0 .../integration/client/timezone-tests.js | 0 .../integration/client/transaction-tests.js | 0 .../integration/client/type-coercion-tests.js | 0 .../client/type-parser-override-tests.js | 0 .../connection-pool-size-tests.js | 0 .../connection-pool/error-tests.js | 0 .../connection-pool/idle-timeout-tests.js | 0 .../connection-pool/native-instance-tests.js | 0 .../connection-pool/test-helper.js | 0 .../connection-pool/yield-support-tests.js | 0 .../connection/bound-command-tests.js | 0 .../integration/connection/copy-tests.js | 0 .../connection/dynamic-password.js | 0 .../connection/notification-tests.js | 0 .../integration/connection/query-tests.js | 0 .../integration/connection/test-helper.js | 0 .../pg/test}/integration/domain-tests.js | 0 .../test}/integration/gh-issues/130-tests.js | 0 .../test}/integration/gh-issues/131-tests.js | 0 .../test}/integration/gh-issues/1382-tests.js | 0 .../test}/integration/gh-issues/1854-tests.js | 0 .../test}/integration/gh-issues/199-tests.js | 0 .../test}/integration/gh-issues/507-tests.js | 0 .../test}/integration/gh-issues/600-tests.js | 0 .../test}/integration/gh-issues/675-tests.js | 0 .../test}/integration/gh-issues/699-tests.js | 0 .../test}/integration/gh-issues/787-tests.js | 0 .../test}/integration/gh-issues/882-tests.js | 0 .../test}/integration/gh-issues/981-tests.js | 0 .../pg/test}/integration/test-helper.js | 0 .../pg/test}/native/callback-api-tests.js | 0 .../pg/test}/native/evented-api-tests.js | 0 .../pg/test}/native/missing-native.js | 0 .../test}/native/native-vs-js-error-tests.js | 0 .../pg/test}/native/stress-tests.js | 0 {test => packages/pg/test}/suite.js | 0 {test => packages/pg/test}/test-buffers.js | 0 {test => packages/pg/test}/test-helper.js | 0 .../unit/client/cleartext-password-tests.js | 0 .../test}/unit/client/configuration-tests.js | 0 .../unit/client/early-disconnect-tests.js | 0 .../pg/test}/unit/client/escape-tests.js | 0 .../test}/unit/client/md5-password-tests.js | 0 .../test}/unit/client/notification-tests.js | 0 .../unit/client/prepared-statement-tests.js | 0 .../pg/test}/unit/client/query-queue-tests.js | 0 .../unit/client/result-metadata-tests.js | 0 .../pg/test}/unit/client/sasl-scram-tests.js | 0 .../pg/test}/unit/client/set-keepalives.js | 0 .../test}/unit/client/simple-query-tests.js | 0 ...tream-and-query-error-interaction-tests.js | 0 .../pg/test}/unit/client/test-helper.js | 0 .../unit/client/throw-in-type-parser-tests.js | 0 .../connection-parameters/creation-tests.js | 0 .../environment-variable-tests.js | 0 .../pg/test}/unit/connection/error-tests.js | 0 .../unit/connection/inbound-parser-tests.js | 0 .../unit/connection/outbound-sending-tests.js | 0 .../pg/test}/unit/connection/startup-tests.js | 0 .../pg/test}/unit/connection/test-helper.js | 0 .../pg/test}/unit/test-helper.js | 0 .../pg/test}/unit/utils-tests.js | 0 yarn.lock | 5464 +++++++++++++++++ 121 files changed, 5539 insertions(+), 58 deletions(-) create mode 100644 lerna.json rename Makefile => packages/pg/Makefile (100%) rename {lib => packages/pg/lib}/client.js (100%) rename {lib => packages/pg/lib}/compat/check-constructor.js (100%) rename {lib => packages/pg/lib}/compat/warn-deprecation.js (100%) rename {lib => packages/pg/lib}/connection-parameters.js (100%) rename {lib => packages/pg/lib}/connection.js (100%) rename {lib => packages/pg/lib}/defaults.js (100%) rename {lib => packages/pg/lib}/index.js (100%) rename {lib => packages/pg/lib}/native/client.js (100%) rename {lib => packages/pg/lib}/native/index.js (100%) rename {lib => packages/pg/lib}/native/query.js (100%) rename {lib => packages/pg/lib}/query.js (100%) rename {lib => packages/pg/lib}/result.js (100%) rename {lib => packages/pg/lib}/sasl.js (100%) rename {lib => packages/pg/lib}/type-overrides.js (100%) rename {lib => packages/pg/lib}/utils.js (100%) create mode 100644 packages/pg/package.json rename {script => packages/pg/script}/create-test-tables.js (100%) rename {script => packages/pg/script}/dump-db-types.js (100%) rename {script => packages/pg/script}/list-db-types.js (100%) rename {test => packages/pg/test}/buffer-list.js (100%) rename {test => packages/pg/test}/cli.js (100%) rename {test => packages/pg/test}/integration/client/api-tests.js (100%) rename {test => packages/pg/test}/integration/client/appname-tests.js (100%) rename {test => packages/pg/test}/integration/client/array-tests.js (100%) rename {test => packages/pg/test}/integration/client/big-simple-query-tests.js (100%) rename {test => packages/pg/test}/integration/client/configuration-tests.js (100%) rename {test => packages/pg/test}/integration/client/connection-timeout-tests.js (100%) rename {test => packages/pg/test}/integration/client/custom-types-tests.js (100%) rename {test => packages/pg/test}/integration/client/empty-query-tests.js (100%) rename {test => packages/pg/test}/integration/client/error-handling-tests.js (100%) rename {test => packages/pg/test}/integration/client/field-name-escape-tests.js (100%) rename {test => packages/pg/test}/integration/client/huge-numeric-tests.js (100%) rename {test => packages/pg/test}/integration/client/json-type-parsing-tests.js (100%) rename {test => packages/pg/test}/integration/client/multiple-results-tests.js (100%) rename {test => packages/pg/test}/integration/client/network-partition-tests.js (100%) rename {test => packages/pg/test}/integration/client/no-data-tests.js (100%) rename {test => packages/pg/test}/integration/client/no-row-result-tests.js (100%) rename {test => packages/pg/test}/integration/client/notice-tests.js (100%) rename {test => packages/pg/test}/integration/client/parse-int-8-tests.js (100%) rename {test => packages/pg/test}/integration/client/prepared-statement-tests.js (100%) rename {test => packages/pg/test}/integration/client/promise-api-tests.js (100%) rename {test => packages/pg/test}/integration/client/query-as-promise-tests.js (100%) rename {test => packages/pg/test}/integration/client/query-column-names-tests.js (100%) rename {test => packages/pg/test}/integration/client/query-error-handling-prepared-statement-tests.js (100%) rename {test => packages/pg/test}/integration/client/query-error-handling-tests.js (100%) rename {test => packages/pg/test}/integration/client/quick-disconnect-tests.js (100%) rename {test => packages/pg/test}/integration/client/result-metadata-tests.js (100%) rename {test => packages/pg/test}/integration/client/results-as-array-tests.js (100%) rename {test => packages/pg/test}/integration/client/row-description-on-results-tests.js (100%) rename {test => packages/pg/test}/integration/client/sasl-scram-tests.js (100%) rename {test => packages/pg/test}/integration/client/simple-query-tests.js (100%) rename {test => packages/pg/test}/integration/client/ssl-tests.js (100%) rename {test => packages/pg/test}/integration/client/statement_timeout-tests.js (100%) rename {test => packages/pg/test}/integration/client/test-helper.js (100%) rename {test => packages/pg/test}/integration/client/timezone-tests.js (100%) rename {test => packages/pg/test}/integration/client/transaction-tests.js (100%) rename {test => packages/pg/test}/integration/client/type-coercion-tests.js (100%) rename {test => packages/pg/test}/integration/client/type-parser-override-tests.js (100%) rename {test => packages/pg/test}/integration/connection-pool/connection-pool-size-tests.js (100%) rename {test => packages/pg/test}/integration/connection-pool/error-tests.js (100%) rename {test => packages/pg/test}/integration/connection-pool/idle-timeout-tests.js (100%) rename {test => packages/pg/test}/integration/connection-pool/native-instance-tests.js (100%) rename {test => packages/pg/test}/integration/connection-pool/test-helper.js (100%) rename {test => packages/pg/test}/integration/connection-pool/yield-support-tests.js (100%) rename {test => packages/pg/test}/integration/connection/bound-command-tests.js (100%) rename {test => packages/pg/test}/integration/connection/copy-tests.js (100%) rename {test => packages/pg/test}/integration/connection/dynamic-password.js (100%) rename {test => packages/pg/test}/integration/connection/notification-tests.js (100%) rename {test => packages/pg/test}/integration/connection/query-tests.js (100%) rename {test => packages/pg/test}/integration/connection/test-helper.js (100%) rename {test => packages/pg/test}/integration/domain-tests.js (100%) rename {test => packages/pg/test}/integration/gh-issues/130-tests.js (100%) rename {test => packages/pg/test}/integration/gh-issues/131-tests.js (100%) rename {test => packages/pg/test}/integration/gh-issues/1382-tests.js (100%) rename {test => packages/pg/test}/integration/gh-issues/1854-tests.js (100%) rename {test => packages/pg/test}/integration/gh-issues/199-tests.js (100%) rename {test => packages/pg/test}/integration/gh-issues/507-tests.js (100%) rename {test => packages/pg/test}/integration/gh-issues/600-tests.js (100%) rename {test => packages/pg/test}/integration/gh-issues/675-tests.js (100%) rename {test => packages/pg/test}/integration/gh-issues/699-tests.js (100%) rename {test => packages/pg/test}/integration/gh-issues/787-tests.js (100%) rename {test => packages/pg/test}/integration/gh-issues/882-tests.js (100%) rename {test => packages/pg/test}/integration/gh-issues/981-tests.js (100%) rename {test => packages/pg/test}/integration/test-helper.js (100%) rename {test => packages/pg/test}/native/callback-api-tests.js (100%) rename {test => packages/pg/test}/native/evented-api-tests.js (100%) rename {test => packages/pg/test}/native/missing-native.js (100%) rename {test => packages/pg/test}/native/native-vs-js-error-tests.js (100%) rename {test => packages/pg/test}/native/stress-tests.js (100%) rename {test => packages/pg/test}/suite.js (100%) rename {test => packages/pg/test}/test-buffers.js (100%) rename {test => packages/pg/test}/test-helper.js (100%) rename {test => packages/pg/test}/unit/client/cleartext-password-tests.js (100%) rename {test => packages/pg/test}/unit/client/configuration-tests.js (100%) rename {test => packages/pg/test}/unit/client/early-disconnect-tests.js (100%) rename {test => packages/pg/test}/unit/client/escape-tests.js (100%) rename {test => packages/pg/test}/unit/client/md5-password-tests.js (100%) rename {test => packages/pg/test}/unit/client/notification-tests.js (100%) rename {test => packages/pg/test}/unit/client/prepared-statement-tests.js (100%) rename {test => packages/pg/test}/unit/client/query-queue-tests.js (100%) rename {test => packages/pg/test}/unit/client/result-metadata-tests.js (100%) rename {test => packages/pg/test}/unit/client/sasl-scram-tests.js (100%) rename {test => packages/pg/test}/unit/client/set-keepalives.js (100%) rename {test => packages/pg/test}/unit/client/simple-query-tests.js (100%) rename {test => packages/pg/test}/unit/client/stream-and-query-error-interaction-tests.js (100%) rename {test => packages/pg/test}/unit/client/test-helper.js (100%) rename {test => packages/pg/test}/unit/client/throw-in-type-parser-tests.js (100%) rename {test => packages/pg/test}/unit/connection-parameters/creation-tests.js (100%) rename {test => packages/pg/test}/unit/connection-parameters/environment-variable-tests.js (100%) rename {test => packages/pg/test}/unit/connection/error-tests.js (100%) rename {test => packages/pg/test}/unit/connection/inbound-parser-tests.js (100%) rename {test => packages/pg/test}/unit/connection/outbound-sending-tests.js (100%) rename {test => packages/pg/test}/unit/connection/startup-tests.js (100%) rename {test => packages/pg/test}/unit/connection/test-helper.js (100%) rename {test => packages/pg/test}/unit/test-helper.js (100%) rename {test => packages/pg/test}/unit/utils-tests.js (100%) create mode 100644 yarn.lock diff --git a/.travis.yml b/.travis.yml index 94b3da4e7..5b65d51b5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: node_js dist: bionic before_script: - - node script/create-test-tables.js pg://postgres@127.0.0.1:5432/postgres + - node packages/pg/script/create-test-tables.js pg://postgres@127.0.0.1:5432/postgres env: - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres @@ -17,15 +17,6 @@ addons: matrix: include: - # different Node versions on PostgreSQL 9.5 that require precise - - node_js: lts/argon - addons: - postgresql: "9.5" - dist: precise - - node_js: lts/boron - addons: - postgresql: "9.5" - dist: precise - node_js: lts/carbon addons: postgresql: "9.5" diff --git a/lerna.json b/lerna.json new file mode 100644 index 000000000..3a60d401d --- /dev/null +++ b/lerna.json @@ -0,0 +1,8 @@ +{ + "packages": [ + "packages/*" + ], + "npmClient": "yarn", + "useWorkspaces": true, + "version": "independent" +} diff --git a/package.json b/package.json index 5d0653724..5dd581b2e 100644 --- a/package.json +++ b/package.json @@ -1,54 +1,18 @@ { - "name": "pg", - "version": "7.14.0", - "description": "PostgreSQL client - pure javascript & libpq with the same API", - "keywords": [ - "database", - "libpq", - "pg", - "postgre", - "postgres", - "postgresql", - "rdbms" + "name": "node-postgres", + "description": "node postgres monorepo", + "main": "index.js", + "private": true, + "repository": "git@github.com:brianc/node-postgres.git", + "author": "Brian M. Carlson ", + "license": "MIT", + "workspaces": [ + "packages/*" ], - "homepage": "http://github.com/brianc/node-postgres", - "repository": { - "type": "git", - "url": "git://github.com/brianc/node-postgres.git" - }, - "author": "Brian Carlson ", - "main": "./lib", - "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "0.1.3", - "pg-pool": "^2.0.7", - "pg-types": "^2.1.0", - "pgpass": "1.x", - "semver": "4.3.2" - }, - "devDependencies": { - "async": "0.9.0", - "bluebird": "3.5.2", - "co": "4.6.0", - "eslint": "^6.0.1", - "eslint-config-standard": "^13.0.1", - "eslint-plugin-import": "^2.18.1", - "eslint-plugin-node": "^9.1.0", - "eslint-plugin-promise": "^4.2.1", - "eslint-plugin-standard": "^4.0.0", - "pg-copy-streams": "0.3.0" - }, - "minNativeVersion": "2.0.0", "scripts": { - "test": "make test-all" + "test": "yarn lerna exec --parallel yarn test" }, - "files": [ - "lib", - "SPONSORS.md" - ], - "license": "MIT", - "engines": { - "node": ">= 4.5.0" + "devDependencies": { + "lerna": "^3.19.0" } } diff --git a/Makefile b/packages/pg/Makefile similarity index 100% rename from Makefile rename to packages/pg/Makefile diff --git a/lib/client.js b/packages/pg/lib/client.js similarity index 100% rename from lib/client.js rename to packages/pg/lib/client.js diff --git a/lib/compat/check-constructor.js b/packages/pg/lib/compat/check-constructor.js similarity index 100% rename from lib/compat/check-constructor.js rename to packages/pg/lib/compat/check-constructor.js diff --git a/lib/compat/warn-deprecation.js b/packages/pg/lib/compat/warn-deprecation.js similarity index 100% rename from lib/compat/warn-deprecation.js rename to packages/pg/lib/compat/warn-deprecation.js diff --git a/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js similarity index 100% rename from lib/connection-parameters.js rename to packages/pg/lib/connection-parameters.js diff --git a/lib/connection.js b/packages/pg/lib/connection.js similarity index 100% rename from lib/connection.js rename to packages/pg/lib/connection.js diff --git a/lib/defaults.js b/packages/pg/lib/defaults.js similarity index 100% rename from lib/defaults.js rename to packages/pg/lib/defaults.js diff --git a/lib/index.js b/packages/pg/lib/index.js similarity index 100% rename from lib/index.js rename to packages/pg/lib/index.js diff --git a/lib/native/client.js b/packages/pg/lib/native/client.js similarity index 100% rename from lib/native/client.js rename to packages/pg/lib/native/client.js diff --git a/lib/native/index.js b/packages/pg/lib/native/index.js similarity index 100% rename from lib/native/index.js rename to packages/pg/lib/native/index.js diff --git a/lib/native/query.js b/packages/pg/lib/native/query.js similarity index 100% rename from lib/native/query.js rename to packages/pg/lib/native/query.js diff --git a/lib/query.js b/packages/pg/lib/query.js similarity index 100% rename from lib/query.js rename to packages/pg/lib/query.js diff --git a/lib/result.js b/packages/pg/lib/result.js similarity index 100% rename from lib/result.js rename to packages/pg/lib/result.js diff --git a/lib/sasl.js b/packages/pg/lib/sasl.js similarity index 100% rename from lib/sasl.js rename to packages/pg/lib/sasl.js diff --git a/lib/type-overrides.js b/packages/pg/lib/type-overrides.js similarity index 100% rename from lib/type-overrides.js rename to packages/pg/lib/type-overrides.js diff --git a/lib/utils.js b/packages/pg/lib/utils.js similarity index 100% rename from lib/utils.js rename to packages/pg/lib/utils.js diff --git a/packages/pg/package.json b/packages/pg/package.json new file mode 100644 index 000000000..5d0653724 --- /dev/null +++ b/packages/pg/package.json @@ -0,0 +1,54 @@ +{ + "name": "pg", + "version": "7.14.0", + "description": "PostgreSQL client - pure javascript & libpq with the same API", + "keywords": [ + "database", + "libpq", + "pg", + "postgre", + "postgres", + "postgresql", + "rdbms" + ], + "homepage": "http://github.com/brianc/node-postgres", + "repository": { + "type": "git", + "url": "git://github.com/brianc/node-postgres.git" + }, + "author": "Brian Carlson ", + "main": "./lib", + "dependencies": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "0.1.3", + "pg-pool": "^2.0.7", + "pg-types": "^2.1.0", + "pgpass": "1.x", + "semver": "4.3.2" + }, + "devDependencies": { + "async": "0.9.0", + "bluebird": "3.5.2", + "co": "4.6.0", + "eslint": "^6.0.1", + "eslint-config-standard": "^13.0.1", + "eslint-plugin-import": "^2.18.1", + "eslint-plugin-node": "^9.1.0", + "eslint-plugin-promise": "^4.2.1", + "eslint-plugin-standard": "^4.0.0", + "pg-copy-streams": "0.3.0" + }, + "minNativeVersion": "2.0.0", + "scripts": { + "test": "make test-all" + }, + "files": [ + "lib", + "SPONSORS.md" + ], + "license": "MIT", + "engines": { + "node": ">= 4.5.0" + } +} diff --git a/script/create-test-tables.js b/packages/pg/script/create-test-tables.js similarity index 100% rename from script/create-test-tables.js rename to packages/pg/script/create-test-tables.js diff --git a/script/dump-db-types.js b/packages/pg/script/dump-db-types.js similarity index 100% rename from script/dump-db-types.js rename to packages/pg/script/dump-db-types.js diff --git a/script/list-db-types.js b/packages/pg/script/list-db-types.js similarity index 100% rename from script/list-db-types.js rename to packages/pg/script/list-db-types.js diff --git a/test/buffer-list.js b/packages/pg/test/buffer-list.js similarity index 100% rename from test/buffer-list.js rename to packages/pg/test/buffer-list.js diff --git a/test/cli.js b/packages/pg/test/cli.js similarity index 100% rename from test/cli.js rename to packages/pg/test/cli.js diff --git a/test/integration/client/api-tests.js b/packages/pg/test/integration/client/api-tests.js similarity index 100% rename from test/integration/client/api-tests.js rename to packages/pg/test/integration/client/api-tests.js diff --git a/test/integration/client/appname-tests.js b/packages/pg/test/integration/client/appname-tests.js similarity index 100% rename from test/integration/client/appname-tests.js rename to packages/pg/test/integration/client/appname-tests.js diff --git a/test/integration/client/array-tests.js b/packages/pg/test/integration/client/array-tests.js similarity index 100% rename from test/integration/client/array-tests.js rename to packages/pg/test/integration/client/array-tests.js diff --git a/test/integration/client/big-simple-query-tests.js b/packages/pg/test/integration/client/big-simple-query-tests.js similarity index 100% rename from test/integration/client/big-simple-query-tests.js rename to packages/pg/test/integration/client/big-simple-query-tests.js diff --git a/test/integration/client/configuration-tests.js b/packages/pg/test/integration/client/configuration-tests.js similarity index 100% rename from test/integration/client/configuration-tests.js rename to packages/pg/test/integration/client/configuration-tests.js diff --git a/test/integration/client/connection-timeout-tests.js b/packages/pg/test/integration/client/connection-timeout-tests.js similarity index 100% rename from test/integration/client/connection-timeout-tests.js rename to packages/pg/test/integration/client/connection-timeout-tests.js diff --git a/test/integration/client/custom-types-tests.js b/packages/pg/test/integration/client/custom-types-tests.js similarity index 100% rename from test/integration/client/custom-types-tests.js rename to packages/pg/test/integration/client/custom-types-tests.js diff --git a/test/integration/client/empty-query-tests.js b/packages/pg/test/integration/client/empty-query-tests.js similarity index 100% rename from test/integration/client/empty-query-tests.js rename to packages/pg/test/integration/client/empty-query-tests.js diff --git a/test/integration/client/error-handling-tests.js b/packages/pg/test/integration/client/error-handling-tests.js similarity index 100% rename from test/integration/client/error-handling-tests.js rename to packages/pg/test/integration/client/error-handling-tests.js diff --git a/test/integration/client/field-name-escape-tests.js b/packages/pg/test/integration/client/field-name-escape-tests.js similarity index 100% rename from test/integration/client/field-name-escape-tests.js rename to packages/pg/test/integration/client/field-name-escape-tests.js diff --git a/test/integration/client/huge-numeric-tests.js b/packages/pg/test/integration/client/huge-numeric-tests.js similarity index 100% rename from test/integration/client/huge-numeric-tests.js rename to packages/pg/test/integration/client/huge-numeric-tests.js diff --git a/test/integration/client/json-type-parsing-tests.js b/packages/pg/test/integration/client/json-type-parsing-tests.js similarity index 100% rename from test/integration/client/json-type-parsing-tests.js rename to packages/pg/test/integration/client/json-type-parsing-tests.js diff --git a/test/integration/client/multiple-results-tests.js b/packages/pg/test/integration/client/multiple-results-tests.js similarity index 100% rename from test/integration/client/multiple-results-tests.js rename to packages/pg/test/integration/client/multiple-results-tests.js diff --git a/test/integration/client/network-partition-tests.js b/packages/pg/test/integration/client/network-partition-tests.js similarity index 100% rename from test/integration/client/network-partition-tests.js rename to packages/pg/test/integration/client/network-partition-tests.js diff --git a/test/integration/client/no-data-tests.js b/packages/pg/test/integration/client/no-data-tests.js similarity index 100% rename from test/integration/client/no-data-tests.js rename to packages/pg/test/integration/client/no-data-tests.js diff --git a/test/integration/client/no-row-result-tests.js b/packages/pg/test/integration/client/no-row-result-tests.js similarity index 100% rename from test/integration/client/no-row-result-tests.js rename to packages/pg/test/integration/client/no-row-result-tests.js diff --git a/test/integration/client/notice-tests.js b/packages/pg/test/integration/client/notice-tests.js similarity index 100% rename from test/integration/client/notice-tests.js rename to packages/pg/test/integration/client/notice-tests.js diff --git a/test/integration/client/parse-int-8-tests.js b/packages/pg/test/integration/client/parse-int-8-tests.js similarity index 100% rename from test/integration/client/parse-int-8-tests.js rename to packages/pg/test/integration/client/parse-int-8-tests.js diff --git a/test/integration/client/prepared-statement-tests.js b/packages/pg/test/integration/client/prepared-statement-tests.js similarity index 100% rename from test/integration/client/prepared-statement-tests.js rename to packages/pg/test/integration/client/prepared-statement-tests.js diff --git a/test/integration/client/promise-api-tests.js b/packages/pg/test/integration/client/promise-api-tests.js similarity index 100% rename from test/integration/client/promise-api-tests.js rename to packages/pg/test/integration/client/promise-api-tests.js diff --git a/test/integration/client/query-as-promise-tests.js b/packages/pg/test/integration/client/query-as-promise-tests.js similarity index 100% rename from test/integration/client/query-as-promise-tests.js rename to packages/pg/test/integration/client/query-as-promise-tests.js diff --git a/test/integration/client/query-column-names-tests.js b/packages/pg/test/integration/client/query-column-names-tests.js similarity index 100% rename from test/integration/client/query-column-names-tests.js rename to packages/pg/test/integration/client/query-column-names-tests.js diff --git a/test/integration/client/query-error-handling-prepared-statement-tests.js b/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js similarity index 100% rename from test/integration/client/query-error-handling-prepared-statement-tests.js rename to packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js diff --git a/test/integration/client/query-error-handling-tests.js b/packages/pg/test/integration/client/query-error-handling-tests.js similarity index 100% rename from test/integration/client/query-error-handling-tests.js rename to packages/pg/test/integration/client/query-error-handling-tests.js diff --git a/test/integration/client/quick-disconnect-tests.js b/packages/pg/test/integration/client/quick-disconnect-tests.js similarity index 100% rename from test/integration/client/quick-disconnect-tests.js rename to packages/pg/test/integration/client/quick-disconnect-tests.js diff --git a/test/integration/client/result-metadata-tests.js b/packages/pg/test/integration/client/result-metadata-tests.js similarity index 100% rename from test/integration/client/result-metadata-tests.js rename to packages/pg/test/integration/client/result-metadata-tests.js diff --git a/test/integration/client/results-as-array-tests.js b/packages/pg/test/integration/client/results-as-array-tests.js similarity index 100% rename from test/integration/client/results-as-array-tests.js rename to packages/pg/test/integration/client/results-as-array-tests.js diff --git a/test/integration/client/row-description-on-results-tests.js b/packages/pg/test/integration/client/row-description-on-results-tests.js similarity index 100% rename from test/integration/client/row-description-on-results-tests.js rename to packages/pg/test/integration/client/row-description-on-results-tests.js diff --git a/test/integration/client/sasl-scram-tests.js b/packages/pg/test/integration/client/sasl-scram-tests.js similarity index 100% rename from test/integration/client/sasl-scram-tests.js rename to packages/pg/test/integration/client/sasl-scram-tests.js diff --git a/test/integration/client/simple-query-tests.js b/packages/pg/test/integration/client/simple-query-tests.js similarity index 100% rename from test/integration/client/simple-query-tests.js rename to packages/pg/test/integration/client/simple-query-tests.js diff --git a/test/integration/client/ssl-tests.js b/packages/pg/test/integration/client/ssl-tests.js similarity index 100% rename from test/integration/client/ssl-tests.js rename to packages/pg/test/integration/client/ssl-tests.js diff --git a/test/integration/client/statement_timeout-tests.js b/packages/pg/test/integration/client/statement_timeout-tests.js similarity index 100% rename from test/integration/client/statement_timeout-tests.js rename to packages/pg/test/integration/client/statement_timeout-tests.js diff --git a/test/integration/client/test-helper.js b/packages/pg/test/integration/client/test-helper.js similarity index 100% rename from test/integration/client/test-helper.js rename to packages/pg/test/integration/client/test-helper.js diff --git a/test/integration/client/timezone-tests.js b/packages/pg/test/integration/client/timezone-tests.js similarity index 100% rename from test/integration/client/timezone-tests.js rename to packages/pg/test/integration/client/timezone-tests.js diff --git a/test/integration/client/transaction-tests.js b/packages/pg/test/integration/client/transaction-tests.js similarity index 100% rename from test/integration/client/transaction-tests.js rename to packages/pg/test/integration/client/transaction-tests.js diff --git a/test/integration/client/type-coercion-tests.js b/packages/pg/test/integration/client/type-coercion-tests.js similarity index 100% rename from test/integration/client/type-coercion-tests.js rename to packages/pg/test/integration/client/type-coercion-tests.js diff --git a/test/integration/client/type-parser-override-tests.js b/packages/pg/test/integration/client/type-parser-override-tests.js similarity index 100% rename from test/integration/client/type-parser-override-tests.js rename to packages/pg/test/integration/client/type-parser-override-tests.js diff --git a/test/integration/connection-pool/connection-pool-size-tests.js b/packages/pg/test/integration/connection-pool/connection-pool-size-tests.js similarity index 100% rename from test/integration/connection-pool/connection-pool-size-tests.js rename to packages/pg/test/integration/connection-pool/connection-pool-size-tests.js diff --git a/test/integration/connection-pool/error-tests.js b/packages/pg/test/integration/connection-pool/error-tests.js similarity index 100% rename from test/integration/connection-pool/error-tests.js rename to packages/pg/test/integration/connection-pool/error-tests.js diff --git a/test/integration/connection-pool/idle-timeout-tests.js b/packages/pg/test/integration/connection-pool/idle-timeout-tests.js similarity index 100% rename from test/integration/connection-pool/idle-timeout-tests.js rename to packages/pg/test/integration/connection-pool/idle-timeout-tests.js diff --git a/test/integration/connection-pool/native-instance-tests.js b/packages/pg/test/integration/connection-pool/native-instance-tests.js similarity index 100% rename from test/integration/connection-pool/native-instance-tests.js rename to packages/pg/test/integration/connection-pool/native-instance-tests.js diff --git a/test/integration/connection-pool/test-helper.js b/packages/pg/test/integration/connection-pool/test-helper.js similarity index 100% rename from test/integration/connection-pool/test-helper.js rename to packages/pg/test/integration/connection-pool/test-helper.js diff --git a/test/integration/connection-pool/yield-support-tests.js b/packages/pg/test/integration/connection-pool/yield-support-tests.js similarity index 100% rename from test/integration/connection-pool/yield-support-tests.js rename to packages/pg/test/integration/connection-pool/yield-support-tests.js diff --git a/test/integration/connection/bound-command-tests.js b/packages/pg/test/integration/connection/bound-command-tests.js similarity index 100% rename from test/integration/connection/bound-command-tests.js rename to packages/pg/test/integration/connection/bound-command-tests.js diff --git a/test/integration/connection/copy-tests.js b/packages/pg/test/integration/connection/copy-tests.js similarity index 100% rename from test/integration/connection/copy-tests.js rename to packages/pg/test/integration/connection/copy-tests.js diff --git a/test/integration/connection/dynamic-password.js b/packages/pg/test/integration/connection/dynamic-password.js similarity index 100% rename from test/integration/connection/dynamic-password.js rename to packages/pg/test/integration/connection/dynamic-password.js diff --git a/test/integration/connection/notification-tests.js b/packages/pg/test/integration/connection/notification-tests.js similarity index 100% rename from test/integration/connection/notification-tests.js rename to packages/pg/test/integration/connection/notification-tests.js diff --git a/test/integration/connection/query-tests.js b/packages/pg/test/integration/connection/query-tests.js similarity index 100% rename from test/integration/connection/query-tests.js rename to packages/pg/test/integration/connection/query-tests.js diff --git a/test/integration/connection/test-helper.js b/packages/pg/test/integration/connection/test-helper.js similarity index 100% rename from test/integration/connection/test-helper.js rename to packages/pg/test/integration/connection/test-helper.js diff --git a/test/integration/domain-tests.js b/packages/pg/test/integration/domain-tests.js similarity index 100% rename from test/integration/domain-tests.js rename to packages/pg/test/integration/domain-tests.js diff --git a/test/integration/gh-issues/130-tests.js b/packages/pg/test/integration/gh-issues/130-tests.js similarity index 100% rename from test/integration/gh-issues/130-tests.js rename to packages/pg/test/integration/gh-issues/130-tests.js diff --git a/test/integration/gh-issues/131-tests.js b/packages/pg/test/integration/gh-issues/131-tests.js similarity index 100% rename from test/integration/gh-issues/131-tests.js rename to packages/pg/test/integration/gh-issues/131-tests.js diff --git a/test/integration/gh-issues/1382-tests.js b/packages/pg/test/integration/gh-issues/1382-tests.js similarity index 100% rename from test/integration/gh-issues/1382-tests.js rename to packages/pg/test/integration/gh-issues/1382-tests.js diff --git a/test/integration/gh-issues/1854-tests.js b/packages/pg/test/integration/gh-issues/1854-tests.js similarity index 100% rename from test/integration/gh-issues/1854-tests.js rename to packages/pg/test/integration/gh-issues/1854-tests.js diff --git a/test/integration/gh-issues/199-tests.js b/packages/pg/test/integration/gh-issues/199-tests.js similarity index 100% rename from test/integration/gh-issues/199-tests.js rename to packages/pg/test/integration/gh-issues/199-tests.js diff --git a/test/integration/gh-issues/507-tests.js b/packages/pg/test/integration/gh-issues/507-tests.js similarity index 100% rename from test/integration/gh-issues/507-tests.js rename to packages/pg/test/integration/gh-issues/507-tests.js diff --git a/test/integration/gh-issues/600-tests.js b/packages/pg/test/integration/gh-issues/600-tests.js similarity index 100% rename from test/integration/gh-issues/600-tests.js rename to packages/pg/test/integration/gh-issues/600-tests.js diff --git a/test/integration/gh-issues/675-tests.js b/packages/pg/test/integration/gh-issues/675-tests.js similarity index 100% rename from test/integration/gh-issues/675-tests.js rename to packages/pg/test/integration/gh-issues/675-tests.js diff --git a/test/integration/gh-issues/699-tests.js b/packages/pg/test/integration/gh-issues/699-tests.js similarity index 100% rename from test/integration/gh-issues/699-tests.js rename to packages/pg/test/integration/gh-issues/699-tests.js diff --git a/test/integration/gh-issues/787-tests.js b/packages/pg/test/integration/gh-issues/787-tests.js similarity index 100% rename from test/integration/gh-issues/787-tests.js rename to packages/pg/test/integration/gh-issues/787-tests.js diff --git a/test/integration/gh-issues/882-tests.js b/packages/pg/test/integration/gh-issues/882-tests.js similarity index 100% rename from test/integration/gh-issues/882-tests.js rename to packages/pg/test/integration/gh-issues/882-tests.js diff --git a/test/integration/gh-issues/981-tests.js b/packages/pg/test/integration/gh-issues/981-tests.js similarity index 100% rename from test/integration/gh-issues/981-tests.js rename to packages/pg/test/integration/gh-issues/981-tests.js diff --git a/test/integration/test-helper.js b/packages/pg/test/integration/test-helper.js similarity index 100% rename from test/integration/test-helper.js rename to packages/pg/test/integration/test-helper.js diff --git a/test/native/callback-api-tests.js b/packages/pg/test/native/callback-api-tests.js similarity index 100% rename from test/native/callback-api-tests.js rename to packages/pg/test/native/callback-api-tests.js diff --git a/test/native/evented-api-tests.js b/packages/pg/test/native/evented-api-tests.js similarity index 100% rename from test/native/evented-api-tests.js rename to packages/pg/test/native/evented-api-tests.js diff --git a/test/native/missing-native.js b/packages/pg/test/native/missing-native.js similarity index 100% rename from test/native/missing-native.js rename to packages/pg/test/native/missing-native.js diff --git a/test/native/native-vs-js-error-tests.js b/packages/pg/test/native/native-vs-js-error-tests.js similarity index 100% rename from test/native/native-vs-js-error-tests.js rename to packages/pg/test/native/native-vs-js-error-tests.js diff --git a/test/native/stress-tests.js b/packages/pg/test/native/stress-tests.js similarity index 100% rename from test/native/stress-tests.js rename to packages/pg/test/native/stress-tests.js diff --git a/test/suite.js b/packages/pg/test/suite.js similarity index 100% rename from test/suite.js rename to packages/pg/test/suite.js diff --git a/test/test-buffers.js b/packages/pg/test/test-buffers.js similarity index 100% rename from test/test-buffers.js rename to packages/pg/test/test-buffers.js diff --git a/test/test-helper.js b/packages/pg/test/test-helper.js similarity index 100% rename from test/test-helper.js rename to packages/pg/test/test-helper.js diff --git a/test/unit/client/cleartext-password-tests.js b/packages/pg/test/unit/client/cleartext-password-tests.js similarity index 100% rename from test/unit/client/cleartext-password-tests.js rename to packages/pg/test/unit/client/cleartext-password-tests.js diff --git a/test/unit/client/configuration-tests.js b/packages/pg/test/unit/client/configuration-tests.js similarity index 100% rename from test/unit/client/configuration-tests.js rename to packages/pg/test/unit/client/configuration-tests.js diff --git a/test/unit/client/early-disconnect-tests.js b/packages/pg/test/unit/client/early-disconnect-tests.js similarity index 100% rename from test/unit/client/early-disconnect-tests.js rename to packages/pg/test/unit/client/early-disconnect-tests.js diff --git a/test/unit/client/escape-tests.js b/packages/pg/test/unit/client/escape-tests.js similarity index 100% rename from test/unit/client/escape-tests.js rename to packages/pg/test/unit/client/escape-tests.js diff --git a/test/unit/client/md5-password-tests.js b/packages/pg/test/unit/client/md5-password-tests.js similarity index 100% rename from test/unit/client/md5-password-tests.js rename to packages/pg/test/unit/client/md5-password-tests.js diff --git a/test/unit/client/notification-tests.js b/packages/pg/test/unit/client/notification-tests.js similarity index 100% rename from test/unit/client/notification-tests.js rename to packages/pg/test/unit/client/notification-tests.js diff --git a/test/unit/client/prepared-statement-tests.js b/packages/pg/test/unit/client/prepared-statement-tests.js similarity index 100% rename from test/unit/client/prepared-statement-tests.js rename to packages/pg/test/unit/client/prepared-statement-tests.js diff --git a/test/unit/client/query-queue-tests.js b/packages/pg/test/unit/client/query-queue-tests.js similarity index 100% rename from test/unit/client/query-queue-tests.js rename to packages/pg/test/unit/client/query-queue-tests.js diff --git a/test/unit/client/result-metadata-tests.js b/packages/pg/test/unit/client/result-metadata-tests.js similarity index 100% rename from test/unit/client/result-metadata-tests.js rename to packages/pg/test/unit/client/result-metadata-tests.js diff --git a/test/unit/client/sasl-scram-tests.js b/packages/pg/test/unit/client/sasl-scram-tests.js similarity index 100% rename from test/unit/client/sasl-scram-tests.js rename to packages/pg/test/unit/client/sasl-scram-tests.js diff --git a/test/unit/client/set-keepalives.js b/packages/pg/test/unit/client/set-keepalives.js similarity index 100% rename from test/unit/client/set-keepalives.js rename to packages/pg/test/unit/client/set-keepalives.js diff --git a/test/unit/client/simple-query-tests.js b/packages/pg/test/unit/client/simple-query-tests.js similarity index 100% rename from test/unit/client/simple-query-tests.js rename to packages/pg/test/unit/client/simple-query-tests.js diff --git a/test/unit/client/stream-and-query-error-interaction-tests.js b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js similarity index 100% rename from test/unit/client/stream-and-query-error-interaction-tests.js rename to packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js diff --git a/test/unit/client/test-helper.js b/packages/pg/test/unit/client/test-helper.js similarity index 100% rename from test/unit/client/test-helper.js rename to packages/pg/test/unit/client/test-helper.js diff --git a/test/unit/client/throw-in-type-parser-tests.js b/packages/pg/test/unit/client/throw-in-type-parser-tests.js similarity index 100% rename from test/unit/client/throw-in-type-parser-tests.js rename to packages/pg/test/unit/client/throw-in-type-parser-tests.js diff --git a/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js similarity index 100% rename from test/unit/connection-parameters/creation-tests.js rename to packages/pg/test/unit/connection-parameters/creation-tests.js diff --git a/test/unit/connection-parameters/environment-variable-tests.js b/packages/pg/test/unit/connection-parameters/environment-variable-tests.js similarity index 100% rename from test/unit/connection-parameters/environment-variable-tests.js rename to packages/pg/test/unit/connection-parameters/environment-variable-tests.js diff --git a/test/unit/connection/error-tests.js b/packages/pg/test/unit/connection/error-tests.js similarity index 100% rename from test/unit/connection/error-tests.js rename to packages/pg/test/unit/connection/error-tests.js diff --git a/test/unit/connection/inbound-parser-tests.js b/packages/pg/test/unit/connection/inbound-parser-tests.js similarity index 100% rename from test/unit/connection/inbound-parser-tests.js rename to packages/pg/test/unit/connection/inbound-parser-tests.js diff --git a/test/unit/connection/outbound-sending-tests.js b/packages/pg/test/unit/connection/outbound-sending-tests.js similarity index 100% rename from test/unit/connection/outbound-sending-tests.js rename to packages/pg/test/unit/connection/outbound-sending-tests.js diff --git a/test/unit/connection/startup-tests.js b/packages/pg/test/unit/connection/startup-tests.js similarity index 100% rename from test/unit/connection/startup-tests.js rename to packages/pg/test/unit/connection/startup-tests.js diff --git a/test/unit/connection/test-helper.js b/packages/pg/test/unit/connection/test-helper.js similarity index 100% rename from test/unit/connection/test-helper.js rename to packages/pg/test/unit/connection/test-helper.js diff --git a/test/unit/test-helper.js b/packages/pg/test/unit/test-helper.js similarity index 100% rename from test/unit/test-helper.js rename to packages/pg/test/unit/test-helper.js diff --git a/test/unit/utils-tests.js b/packages/pg/test/unit/utils-tests.js similarity index 100% rename from test/unit/utils-tests.js rename to packages/pg/test/unit/utils-tests.js diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..845ed02be --- /dev/null +++ b/yarn.lock @@ -0,0 +1,5464 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@^7.0.0": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/highlight@^7.0.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" + integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +"@evocateur/libnpmaccess@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz#ecf7f6ce6b004e9f942b098d92200be4a4b1c845" + integrity sha512-KSCAHwNWro0CF2ukxufCitT9K5LjL/KuMmNzSu8wuwN2rjyKHD8+cmOsiybK+W5hdnwc5M1SmRlVCaMHQo+3rg== + dependencies: + "@evocateur/npm-registry-fetch" "^4.0.0" + aproba "^2.0.0" + figgy-pudding "^3.5.1" + get-stream "^4.0.0" + npm-package-arg "^6.1.0" + +"@evocateur/libnpmpublish@^1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@evocateur/libnpmpublish/-/libnpmpublish-1.2.2.tgz#55df09d2dca136afba9c88c759ca272198db9f1a" + integrity sha512-MJrrk9ct1FeY9zRlyeoyMieBjGDG9ihyyD9/Ft6MMrTxql9NyoEx2hw9casTIP4CdqEVu+3nQ2nXxoJ8RCXyFg== + dependencies: + "@evocateur/npm-registry-fetch" "^4.0.0" + aproba "^2.0.0" + figgy-pudding "^3.5.1" + get-stream "^4.0.0" + lodash.clonedeep "^4.5.0" + normalize-package-data "^2.4.0" + npm-package-arg "^6.1.0" + semver "^5.5.1" + ssri "^6.0.1" + +"@evocateur/npm-registry-fetch@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@evocateur/npm-registry-fetch/-/npm-registry-fetch-4.0.0.tgz#8c4c38766d8d32d3200fcb0a83f064b57365ed66" + integrity sha512-k1WGfKRQyhJpIr+P17O5vLIo2ko1PFLKwoetatdduUSt/aQ4J2sJrJwwatdI5Z3SiYk/mRH9S3JpdmMFd/IK4g== + dependencies: + JSONStream "^1.3.4" + bluebird "^3.5.1" + figgy-pudding "^3.4.1" + lru-cache "^5.1.1" + make-fetch-happen "^5.0.0" + npm-package-arg "^6.1.0" + safe-buffer "^5.1.2" + +"@evocateur/pacote@^9.6.3": + version "9.6.5" + resolved "https://registry.yarnpkg.com/@evocateur/pacote/-/pacote-9.6.5.tgz#33de32ba210b6f17c20ebab4d497efc6755f4ae5" + integrity sha512-EI552lf0aG2nOV8NnZpTxNo2PcXKPmDbF9K8eCBFQdIZwHNGN/mi815fxtmUMa2wTa1yndotICIDt/V0vpEx2w== + dependencies: + "@evocateur/npm-registry-fetch" "^4.0.0" + bluebird "^3.5.3" + cacache "^12.0.3" + chownr "^1.1.2" + figgy-pudding "^3.5.1" + get-stream "^4.1.0" + glob "^7.1.4" + infer-owner "^1.0.4" + lru-cache "^5.1.1" + make-fetch-happen "^5.0.0" + minimatch "^3.0.4" + minipass "^2.3.5" + mississippi "^3.0.0" + mkdirp "^0.5.1" + normalize-package-data "^2.5.0" + npm-package-arg "^6.1.0" + npm-packlist "^1.4.4" + npm-pick-manifest "^3.0.0" + osenv "^0.1.5" + promise-inflight "^1.0.1" + promise-retry "^1.1.1" + protoduck "^5.0.1" + rimraf "^2.6.3" + safe-buffer "^5.2.0" + semver "^5.7.0" + ssri "^6.0.1" + tar "^4.4.10" + unique-filename "^1.1.1" + which "^1.3.1" + +"@lerna/add@3.19.0": + version "3.19.0" + resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.19.0.tgz#33b6251c669895f842c14f05961432d464166249" + integrity sha512-qzhxPyoczvvT1W0wwCK9I0iJ4B9WR+HzYsusmRuzM3mEhWjowhbuvKEl5BjGYuXc9AvEErM/S0Fm5K0RcuS39Q== + dependencies: + "@evocateur/pacote" "^9.6.3" + "@lerna/bootstrap" "3.18.5" + "@lerna/command" "3.18.5" + "@lerna/filter-options" "3.18.4" + "@lerna/npm-conf" "3.16.0" + "@lerna/validation-error" "3.13.0" + dedent "^0.7.0" + npm-package-arg "^6.1.0" + p-map "^2.1.0" + semver "^6.2.0" + +"@lerna/bootstrap@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-3.18.5.tgz#cc22a750d6b0402e136926e8b214148dfc2e1390" + integrity sha512-9vD/BfCz8YSF2Dx7sHaMVo6Cy33WjLEmoN1yrHgNkHjm7ykWbLHG5wru0f4Y4pvwa0s5Hf76rvT8aJWzGHk9IQ== + dependencies: + "@lerna/command" "3.18.5" + "@lerna/filter-options" "3.18.4" + "@lerna/has-npm-version" "3.16.5" + "@lerna/npm-install" "3.16.5" + "@lerna/package-graph" "3.18.5" + "@lerna/pulse-till-done" "3.13.0" + "@lerna/rimraf-dir" "3.16.5" + "@lerna/run-lifecycle" "3.16.2" + "@lerna/run-topologically" "3.18.5" + "@lerna/symlink-binary" "3.17.0" + "@lerna/symlink-dependencies" "3.17.0" + "@lerna/validation-error" "3.13.0" + dedent "^0.7.0" + get-port "^4.2.0" + multimatch "^3.0.0" + npm-package-arg "^6.1.0" + npmlog "^4.1.2" + p-finally "^1.0.0" + p-map "^2.1.0" + p-map-series "^1.0.0" + p-waterfall "^1.0.0" + read-package-tree "^5.1.6" + semver "^6.2.0" + +"@lerna/changed@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-3.18.5.tgz#ef2c460f5497b8b4cfac7e5165fe46d7181fcdf5" + integrity sha512-IXS7VZ5VDQUfCsgK56WYxd42luMBxL456cNUf1yBgQ1cy1U2FPVMitIdLN4AcP7bJizdPWeG8yDptf47jN/xVw== + dependencies: + "@lerna/collect-updates" "3.18.0" + "@lerna/command" "3.18.5" + "@lerna/listable" "3.18.5" + "@lerna/output" "3.13.0" + +"@lerna/check-working-tree@3.16.5": + version "3.16.5" + resolved "https://registry.yarnpkg.com/@lerna/check-working-tree/-/check-working-tree-3.16.5.tgz#b4f8ae61bb4523561dfb9f8f8d874dd46bb44baa" + integrity sha512-xWjVBcuhvB8+UmCSb5tKVLB5OuzSpw96WEhS2uz6hkWVa/Euh1A0/HJwn2cemyK47wUrCQXtczBUiqnq9yX5VQ== + dependencies: + "@lerna/collect-uncommitted" "3.16.5" + "@lerna/describe-ref" "3.16.5" + "@lerna/validation-error" "3.13.0" + +"@lerna/child-process@3.16.5": + version "3.16.5" + resolved "https://registry.yarnpkg.com/@lerna/child-process/-/child-process-3.16.5.tgz#38fa3c18064aa4ac0754ad80114776a7b36a69b2" + integrity sha512-vdcI7mzei9ERRV4oO8Y1LHBZ3A5+ampRKg1wq5nutLsUA4mEBN6H7JqjWOMY9xZemv6+kATm2ofjJ3lW5TszQg== + dependencies: + chalk "^2.3.1" + execa "^1.0.0" + strong-log-transformer "^2.0.0" + +"@lerna/clean@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-3.18.5.tgz#44b4a6db68ae369778f2921c85ec6961bdd86072" + integrity sha512-tHxOj9frTIhB/H2gtgMU3xpIc4IJEhXcUlReko6RJt8TTiDZGPDudCcgjg6i7n15v9jXMOc1y4F+y5/1089bfA== + dependencies: + "@lerna/command" "3.18.5" + "@lerna/filter-options" "3.18.4" + "@lerna/prompt" "3.18.5" + "@lerna/pulse-till-done" "3.13.0" + "@lerna/rimraf-dir" "3.16.5" + p-map "^2.1.0" + p-map-series "^1.0.0" + p-waterfall "^1.0.0" + +"@lerna/cli@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/cli/-/cli-3.18.5.tgz#c90c461542fcd35b6d5b015a290fb0dbfb41d242" + integrity sha512-erkbxkj9jfc89vVs/jBLY/fM0I80oLmJkFUV3Q3wk9J3miYhP14zgVEBsPZY68IZlEjT6T3Xlq2xO1AVaatHsA== + dependencies: + "@lerna/global-options" "3.13.0" + dedent "^0.7.0" + npmlog "^4.1.2" + yargs "^14.2.2" + +"@lerna/collect-uncommitted@3.16.5": + version "3.16.5" + resolved "https://registry.yarnpkg.com/@lerna/collect-uncommitted/-/collect-uncommitted-3.16.5.tgz#a494d61aac31cdc7aec4bbe52c96550274132e63" + integrity sha512-ZgqnGwpDZiWyzIQVZtQaj9tRizsL4dUOhuOStWgTAw1EMe47cvAY2kL709DzxFhjr6JpJSjXV5rZEAeU3VE0Hg== + dependencies: + "@lerna/child-process" "3.16.5" + chalk "^2.3.1" + figgy-pudding "^3.5.1" + npmlog "^4.1.2" + +"@lerna/collect-updates@3.18.0": + version "3.18.0" + resolved "https://registry.yarnpkg.com/@lerna/collect-updates/-/collect-updates-3.18.0.tgz#6086c64df3244993cc0a7f8fc0ddd6a0103008a6" + integrity sha512-LJMKgWsE/var1RSvpKDIxS8eJ7POADEc0HM3FQiTpEczhP6aZfv9x3wlDjaHpZm9MxJyQilqxZcasRANmRcNgw== + dependencies: + "@lerna/child-process" "3.16.5" + "@lerna/describe-ref" "3.16.5" + minimatch "^3.0.4" + npmlog "^4.1.2" + slash "^2.0.0" + +"@lerna/command@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/command/-/command-3.18.5.tgz#14c6d2454adbfd365f8027201523e6c289cd3cd9" + integrity sha512-36EnqR59yaTU4HrR1C9XDFti2jRx0BgpIUBeWn129LZZB8kAB3ov1/dJNa1KcNRKp91DncoKHLY99FZ6zTNpMQ== + dependencies: + "@lerna/child-process" "3.16.5" + "@lerna/package-graph" "3.18.5" + "@lerna/project" "3.18.0" + "@lerna/validation-error" "3.13.0" + "@lerna/write-log-file" "3.13.0" + clone-deep "^4.0.1" + dedent "^0.7.0" + execa "^1.0.0" + is-ci "^2.0.0" + npmlog "^4.1.2" + +"@lerna/conventional-commits@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/conventional-commits/-/conventional-commits-3.18.5.tgz#08efd2e5b45acfaf3f151a53a3ec7ecade58a7bc" + integrity sha512-qcvXIEJ3qSgalxXnQ7Yxp5H9Ta5TVyai6vEor6AAEHc20WiO7UIdbLDCxBtiiHMdGdpH85dTYlsoYUwsCJu3HQ== + dependencies: + "@lerna/validation-error" "3.13.0" + conventional-changelog-angular "^5.0.3" + conventional-changelog-core "^3.1.6" + conventional-recommended-bump "^5.0.0" + fs-extra "^8.1.0" + get-stream "^4.0.0" + lodash.template "^4.5.0" + npm-package-arg "^6.1.0" + npmlog "^4.1.2" + pify "^4.0.1" + semver "^6.2.0" + +"@lerna/create-symlink@3.16.2": + version "3.16.2" + resolved "https://registry.yarnpkg.com/@lerna/create-symlink/-/create-symlink-3.16.2.tgz#412cb8e59a72f5a7d9463e4e4721ad2070149967" + integrity sha512-pzXIJp6av15P325sgiIRpsPXLFmkisLhMBCy4764d+7yjf2bzrJ4gkWVMhsv4AdF0NN3OyZ5jjzzTtLNqfR+Jw== + dependencies: + "@zkochan/cmd-shim" "^3.1.0" + fs-extra "^8.1.0" + npmlog "^4.1.2" + +"@lerna/create@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/create/-/create-3.18.5.tgz#11ac539f069248eaf7bc4c42e237784330f4fc47" + integrity sha512-cHpjocbpKmLopCuZFI7cKEM3E/QY8y+yC7VtZ4FQRSaLU8D8i2xXtXmYaP1GOlVNavji0iwoXjuNpnRMInIr2g== + dependencies: + "@evocateur/pacote" "^9.6.3" + "@lerna/child-process" "3.16.5" + "@lerna/command" "3.18.5" + "@lerna/npm-conf" "3.16.0" + "@lerna/validation-error" "3.13.0" + camelcase "^5.0.0" + dedent "^0.7.0" + fs-extra "^8.1.0" + globby "^9.2.0" + init-package-json "^1.10.3" + npm-package-arg "^6.1.0" + p-reduce "^1.0.0" + pify "^4.0.1" + semver "^6.2.0" + slash "^2.0.0" + validate-npm-package-license "^3.0.3" + validate-npm-package-name "^3.0.0" + whatwg-url "^7.0.0" + +"@lerna/describe-ref@3.16.5": + version "3.16.5" + resolved "https://registry.yarnpkg.com/@lerna/describe-ref/-/describe-ref-3.16.5.tgz#a338c25aaed837d3dc70b8a72c447c5c66346ac0" + integrity sha512-c01+4gUF0saOOtDBzbLMFOTJDHTKbDFNErEY6q6i9QaXuzy9LNN62z+Hw4acAAZuJQhrVWncVathcmkkjvSVGw== + dependencies: + "@lerna/child-process" "3.16.5" + npmlog "^4.1.2" + +"@lerna/diff@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-3.18.5.tgz#e9e2cb882f84d5b84f0487c612137305f07accbc" + integrity sha512-u90lGs+B8DRA9Z/2xX4YaS3h9X6GbypmGV6ITzx9+1Ga12UWGTVlKaCXBgONMBjzJDzAQOK8qPTwLA57SeBLgA== + dependencies: + "@lerna/child-process" "3.16.5" + "@lerna/command" "3.18.5" + "@lerna/validation-error" "3.13.0" + npmlog "^4.1.2" + +"@lerna/exec@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-3.18.5.tgz#50f1bd6b8f88f2ec02c0768b8b1d9024feb1a96a" + integrity sha512-Q1nz95MeAxctS9bF+aG8FkjixzqEjRpg6ujtnDW84J42GgxedkPtNcJ2o/MBqLd/mxAlr+fW3UZ6CPC/zgoyCg== + dependencies: + "@lerna/child-process" "3.16.5" + "@lerna/command" "3.18.5" + "@lerna/filter-options" "3.18.4" + "@lerna/run-topologically" "3.18.5" + "@lerna/validation-error" "3.13.0" + p-map "^2.1.0" + +"@lerna/filter-options@3.18.4": + version "3.18.4" + resolved "https://registry.yarnpkg.com/@lerna/filter-options/-/filter-options-3.18.4.tgz#f5476a7ee2169abed27ad433222e92103f56f9f1" + integrity sha512-4giVQD6tauRwweO/322LP2gfVDOVrt/xN4khkXyfkJDfcsZziFXq+668otD9KSLL8Ps+To4Fah3XbK0MoNuEvA== + dependencies: + "@lerna/collect-updates" "3.18.0" + "@lerna/filter-packages" "3.18.0" + dedent "^0.7.0" + figgy-pudding "^3.5.1" + npmlog "^4.1.2" + +"@lerna/filter-packages@3.18.0": + version "3.18.0" + resolved "https://registry.yarnpkg.com/@lerna/filter-packages/-/filter-packages-3.18.0.tgz#6a7a376d285208db03a82958cfb8172e179b4e70" + integrity sha512-6/0pMM04bCHNATIOkouuYmPg6KH3VkPCIgTfQmdkPJTullERyEQfNUKikrefjxo1vHOoCACDpy65JYyKiAbdwQ== + dependencies: + "@lerna/validation-error" "3.13.0" + multimatch "^3.0.0" + npmlog "^4.1.2" + +"@lerna/get-npm-exec-opts@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@lerna/get-npm-exec-opts/-/get-npm-exec-opts-3.13.0.tgz#d1b552cb0088199fc3e7e126f914e39a08df9ea5" + integrity sha512-Y0xWL0rg3boVyJk6An/vurKzubyJKtrxYv2sj4bB8Mc5zZ3tqtv0ccbOkmkXKqbzvNNF7VeUt1OJ3DRgtC/QZw== + dependencies: + npmlog "^4.1.2" + +"@lerna/get-packed@3.16.0": + version "3.16.0" + resolved "https://registry.yarnpkg.com/@lerna/get-packed/-/get-packed-3.16.0.tgz#1b316b706dcee86c7baa55e50b087959447852ff" + integrity sha512-AjsFiaJzo1GCPnJUJZiTW6J1EihrPkc2y3nMu6m3uWFxoleklsSCyImumzVZJssxMi3CPpztj8LmADLedl9kXw== + dependencies: + fs-extra "^8.1.0" + ssri "^6.0.1" + tar "^4.4.8" + +"@lerna/github-client@3.16.5": + version "3.16.5" + resolved "https://registry.yarnpkg.com/@lerna/github-client/-/github-client-3.16.5.tgz#2eb0235c3bf7a7e5d92d73e09b3761ab21f35c2e" + integrity sha512-rHQdn8Dv/CJrO3VouOP66zAcJzrHsm+wFuZ4uGAai2At2NkgKH+tpNhQy2H1PSC0Ezj9LxvdaHYrUzULqVK5Hw== + dependencies: + "@lerna/child-process" "3.16.5" + "@octokit/plugin-enterprise-rest" "^3.6.1" + "@octokit/rest" "^16.28.4" + git-url-parse "^11.1.2" + npmlog "^4.1.2" + +"@lerna/gitlab-client@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@lerna/gitlab-client/-/gitlab-client-3.15.0.tgz#91f4ec8c697b5ac57f7f25bd50fe659d24aa96a6" + integrity sha512-OsBvRSejHXUBMgwWQqNoioB8sgzL/Pf1pOUhHKtkiMl6aAWjklaaq5HPMvTIsZPfS6DJ9L5OK2GGZuooP/5c8Q== + dependencies: + node-fetch "^2.5.0" + npmlog "^4.1.2" + whatwg-url "^7.0.0" + +"@lerna/global-options@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@lerna/global-options/-/global-options-3.13.0.tgz#217662290db06ad9cf2c49d8e3100ee28eaebae1" + integrity sha512-SlZvh1gVRRzYLVluz9fryY1nJpZ0FHDGB66U9tFfvnnxmueckRQxLopn3tXj3NU1kc3QANT2I5BsQkOqZ4TEFQ== + +"@lerna/has-npm-version@3.16.5": + version "3.16.5" + resolved "https://registry.yarnpkg.com/@lerna/has-npm-version/-/has-npm-version-3.16.5.tgz#ab83956f211d8923ea6afe9b979b38cc73b15326" + integrity sha512-WL7LycR9bkftyqbYop5rEGJ9sRFIV55tSGmbN1HLrF9idwOCD7CLrT64t235t3t4O5gehDnwKI5h2U3oxTrF8Q== + dependencies: + "@lerna/child-process" "3.16.5" + semver "^6.2.0" + +"@lerna/import@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/import/-/import-3.18.5.tgz#a9c7d8601870729851293c10abd18b3707f7ba5e" + integrity sha512-PH0WVLEgp+ORyNKbGGwUcrueW89K3Iuk/DDCz8mFyG2IG09l/jOF0vzckEyGyz6PO5CMcz4TI1al/qnp3FrahQ== + dependencies: + "@lerna/child-process" "3.16.5" + "@lerna/command" "3.18.5" + "@lerna/prompt" "3.18.5" + "@lerna/pulse-till-done" "3.13.0" + "@lerna/validation-error" "3.13.0" + dedent "^0.7.0" + fs-extra "^8.1.0" + p-map-series "^1.0.0" + +"@lerna/init@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/init/-/init-3.18.5.tgz#86dd0b2b3290755a96975069b5cb007f775df9f5" + integrity sha512-oCwipWrha98EcJAHm8AGd2YFFLNI7AW9AWi0/LbClj1+XY9ah+uifXIgYGfTk63LbgophDd8936ZEpHMxBsbAg== + dependencies: + "@lerna/child-process" "3.16.5" + "@lerna/command" "3.18.5" + fs-extra "^8.1.0" + p-map "^2.1.0" + write-json-file "^3.2.0" + +"@lerna/link@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/link/-/link-3.18.5.tgz#f24347e4f0b71d54575bd37cfa1794bc8ee91b18" + integrity sha512-xTN3vktJpkT7Nqc3QkZRtHO4bT5NvuLMtKNIBDkks0HpGxC9PRyyqwOoCoh1yOGbrWIuDezhfMg3Qow+6I69IQ== + dependencies: + "@lerna/command" "3.18.5" + "@lerna/package-graph" "3.18.5" + "@lerna/symlink-dependencies" "3.17.0" + p-map "^2.1.0" + slash "^2.0.0" + +"@lerna/list@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/list/-/list-3.18.5.tgz#58863f17c81e24e2c38018eb8619fc99d7cc5c82" + integrity sha512-qIeomm28C2OCM8TMjEe/chTnQf6XLN54wPVQ6kZy+axMYxANFNt/uhs6GZEmhem7GEVawzkyHSz5ZJPsfH3IFg== + dependencies: + "@lerna/command" "3.18.5" + "@lerna/filter-options" "3.18.4" + "@lerna/listable" "3.18.5" + "@lerna/output" "3.13.0" + +"@lerna/listable@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/listable/-/listable-3.18.5.tgz#e82798405b5ed8fc51843c8ef1e7a0e497388a1a" + integrity sha512-Sdr3pVyaEv5A7ZkGGYR7zN+tTl2iDcinryBPvtuv20VJrXBE8wYcOks1edBTcOWsPjCE/rMP4bo1pseyk3UTsg== + dependencies: + "@lerna/query-graph" "3.18.5" + chalk "^2.3.1" + columnify "^1.5.4" + +"@lerna/log-packed@3.16.0": + version "3.16.0" + resolved "https://registry.yarnpkg.com/@lerna/log-packed/-/log-packed-3.16.0.tgz#f83991041ee77b2495634e14470b42259fd2bc16" + integrity sha512-Fp+McSNBV/P2mnLUYTaSlG8GSmpXM7krKWcllqElGxvAqv6chk2K3c2k80MeVB4WvJ9tRjUUf+i7HUTiQ9/ckQ== + dependencies: + byte-size "^5.0.1" + columnify "^1.5.4" + has-unicode "^2.0.1" + npmlog "^4.1.2" + +"@lerna/npm-conf@3.16.0": + version "3.16.0" + resolved "https://registry.yarnpkg.com/@lerna/npm-conf/-/npm-conf-3.16.0.tgz#1c10a89ae2f6c2ee96962557738685300d376827" + integrity sha512-HbO3DUrTkCAn2iQ9+FF/eisDpWY5POQAOF1m7q//CZjdC2HSW3UYbKEGsSisFxSfaF9Z4jtrV+F/wX6qWs3CuA== + dependencies: + config-chain "^1.1.11" + pify "^4.0.1" + +"@lerna/npm-dist-tag@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/npm-dist-tag/-/npm-dist-tag-3.18.5.tgz#9ef9abb7c104077b31f6fab22cc73b314d54ac55" + integrity sha512-xw0HDoIG6HreVsJND9/dGls1c+lf6vhu7yJoo56Sz5bvncTloYGLUppIfDHQr4ZvmPCK8rsh0euCVh2giPxzKQ== + dependencies: + "@evocateur/npm-registry-fetch" "^4.0.0" + "@lerna/otplease" "3.18.5" + figgy-pudding "^3.5.1" + npm-package-arg "^6.1.0" + npmlog "^4.1.2" + +"@lerna/npm-install@3.16.5": + version "3.16.5" + resolved "https://registry.yarnpkg.com/@lerna/npm-install/-/npm-install-3.16.5.tgz#d6bfdc16f81285da66515ae47924d6e278d637d3" + integrity sha512-hfiKk8Eku6rB9uApqsalHHTHY+mOrrHeWEs+gtg7+meQZMTS3kzv4oVp5cBZigndQr3knTLjwthT/FX4KvseFg== + dependencies: + "@lerna/child-process" "3.16.5" + "@lerna/get-npm-exec-opts" "3.13.0" + fs-extra "^8.1.0" + npm-package-arg "^6.1.0" + npmlog "^4.1.2" + signal-exit "^3.0.2" + write-pkg "^3.1.0" + +"@lerna/npm-publish@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/npm-publish/-/npm-publish-3.18.5.tgz#240e4039959fd9816b49c5b07421e11b5cb000af" + integrity sha512-3etLT9+2L8JAx5F8uf7qp6iAtOLSMj+ZYWY6oUgozPi/uLqU0/gsMsEXh3F0+YVW33q0M61RpduBoAlOOZnaTg== + dependencies: + "@evocateur/libnpmpublish" "^1.2.2" + "@lerna/otplease" "3.18.5" + "@lerna/run-lifecycle" "3.16.2" + figgy-pudding "^3.5.1" + fs-extra "^8.1.0" + npm-package-arg "^6.1.0" + npmlog "^4.1.2" + pify "^4.0.1" + read-package-json "^2.0.13" + +"@lerna/npm-run-script@3.16.5": + version "3.16.5" + resolved "https://registry.yarnpkg.com/@lerna/npm-run-script/-/npm-run-script-3.16.5.tgz#9c2ec82453a26c0b46edc0bb7c15816c821f5c15" + integrity sha512-1asRi+LjmVn3pMjEdpqKJZFT/3ZNpb+VVeJMwrJaV/3DivdNg7XlPK9LTrORuKU4PSvhdEZvJmSlxCKyDpiXsQ== + dependencies: + "@lerna/child-process" "3.16.5" + "@lerna/get-npm-exec-opts" "3.13.0" + npmlog "^4.1.2" + +"@lerna/otplease@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/otplease/-/otplease-3.18.5.tgz#b77b8e760b40abad9f7658d988f3ea77d4fd0231" + integrity sha512-S+SldXAbcXTEDhzdxYLU0ZBKuYyURP/ND2/dK6IpKgLxQYh/z4ScljPDMyKymmEvgiEJmBsPZAAPfmNPEzxjog== + dependencies: + "@lerna/prompt" "3.18.5" + figgy-pudding "^3.5.1" + +"@lerna/output@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@lerna/output/-/output-3.13.0.tgz#3ded7cc908b27a9872228a630d950aedae7a4989" + integrity sha512-7ZnQ9nvUDu/WD+bNsypmPG5MwZBwu86iRoiW6C1WBuXXDxM5cnIAC1m2WxHeFnjyMrYlRXM9PzOQ9VDD+C15Rg== + dependencies: + npmlog "^4.1.2" + +"@lerna/pack-directory@3.16.4": + version "3.16.4" + resolved "https://registry.yarnpkg.com/@lerna/pack-directory/-/pack-directory-3.16.4.tgz#3eae5f91bdf5acfe0384510ed53faddc4c074693" + integrity sha512-uxSF0HZeGyKaaVHz5FroDY9A5NDDiCibrbYR6+khmrhZtY0Bgn6hWq8Gswl9iIlymA+VzCbshWIMX4o2O8C8ng== + dependencies: + "@lerna/get-packed" "3.16.0" + "@lerna/package" "3.16.0" + "@lerna/run-lifecycle" "3.16.2" + figgy-pudding "^3.5.1" + npm-packlist "^1.4.4" + npmlog "^4.1.2" + tar "^4.4.10" + temp-write "^3.4.0" + +"@lerna/package-graph@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/package-graph/-/package-graph-3.18.5.tgz#c740e2ea3578d059e551633e950690831b941f6b" + integrity sha512-8QDrR9T+dBegjeLr+n9WZTVxUYUhIUjUgZ0gvNxUBN8S1WB9r6H5Yk56/MVaB64tA3oGAN9IIxX6w0WvTfFudA== + dependencies: + "@lerna/prerelease-id-from-version" "3.16.0" + "@lerna/validation-error" "3.13.0" + npm-package-arg "^6.1.0" + npmlog "^4.1.2" + semver "^6.2.0" + +"@lerna/package@3.16.0": + version "3.16.0" + resolved "https://registry.yarnpkg.com/@lerna/package/-/package-3.16.0.tgz#7e0a46e4697ed8b8a9c14d59c7f890e0d38ba13c" + integrity sha512-2lHBWpaxcBoiNVbtyLtPUuTYEaB/Z+eEqRS9duxpZs6D+mTTZMNy6/5vpEVSCBmzvdYpyqhqaYjjSLvjjr5Riw== + dependencies: + load-json-file "^5.3.0" + npm-package-arg "^6.1.0" + write-pkg "^3.1.0" + +"@lerna/prerelease-id-from-version@3.16.0": + version "3.16.0" + resolved "https://registry.yarnpkg.com/@lerna/prerelease-id-from-version/-/prerelease-id-from-version-3.16.0.tgz#b24bfa789f5e1baab914d7b08baae9b7bd7d83a1" + integrity sha512-qZyeUyrE59uOK8rKdGn7jQz+9uOpAaF/3hbslJVFL1NqF9ELDTqjCPXivuejMX/lN4OgD6BugTO4cR7UTq/sZA== + dependencies: + semver "^6.2.0" + +"@lerna/project@3.18.0": + version "3.18.0" + resolved "https://registry.yarnpkg.com/@lerna/project/-/project-3.18.0.tgz#56feee01daeb42c03cbdf0ed8a2a10cbce32f670" + integrity sha512-+LDwvdAp0BurOAWmeHE3uuticsq9hNxBI0+FMHiIai8jrygpJGahaQrBYWpwbshbQyVLeQgx3+YJdW2TbEdFWA== + dependencies: + "@lerna/package" "3.16.0" + "@lerna/validation-error" "3.13.0" + cosmiconfig "^5.1.0" + dedent "^0.7.0" + dot-prop "^4.2.0" + glob-parent "^5.0.0" + globby "^9.2.0" + load-json-file "^5.3.0" + npmlog "^4.1.2" + p-map "^2.1.0" + resolve-from "^4.0.0" + write-json-file "^3.2.0" + +"@lerna/prompt@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/prompt/-/prompt-3.18.5.tgz#628cd545f225887d060491ab95df899cfc5218a1" + integrity sha512-rkKj4nm1twSbBEb69+Em/2jAERK8htUuV8/xSjN0NPC+6UjzAwY52/x9n5cfmpa9lyKf/uItp7chCI7eDmNTKQ== + dependencies: + inquirer "^6.2.0" + npmlog "^4.1.2" + +"@lerna/publish@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-3.18.5.tgz#8cc708d83a4cb7ab1c4cc020a02e7ebc4b6b0b0e" + integrity sha512-ifYqLX6mvw95T8vYRlhT68UC7Al0flQvnf5uF9lDgdrgR5Bs+BTwzk3D+0ctdqMtfooekrV6pqfW0R3gtwRffQ== + dependencies: + "@evocateur/libnpmaccess" "^3.1.2" + "@evocateur/npm-registry-fetch" "^4.0.0" + "@evocateur/pacote" "^9.6.3" + "@lerna/check-working-tree" "3.16.5" + "@lerna/child-process" "3.16.5" + "@lerna/collect-updates" "3.18.0" + "@lerna/command" "3.18.5" + "@lerna/describe-ref" "3.16.5" + "@lerna/log-packed" "3.16.0" + "@lerna/npm-conf" "3.16.0" + "@lerna/npm-dist-tag" "3.18.5" + "@lerna/npm-publish" "3.18.5" + "@lerna/otplease" "3.18.5" + "@lerna/output" "3.13.0" + "@lerna/pack-directory" "3.16.4" + "@lerna/prerelease-id-from-version" "3.16.0" + "@lerna/prompt" "3.18.5" + "@lerna/pulse-till-done" "3.13.0" + "@lerna/run-lifecycle" "3.16.2" + "@lerna/run-topologically" "3.18.5" + "@lerna/validation-error" "3.13.0" + "@lerna/version" "3.18.5" + figgy-pudding "^3.5.1" + fs-extra "^8.1.0" + npm-package-arg "^6.1.0" + npmlog "^4.1.2" + p-finally "^1.0.0" + p-map "^2.1.0" + p-pipe "^1.2.0" + semver "^6.2.0" + +"@lerna/pulse-till-done@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@lerna/pulse-till-done/-/pulse-till-done-3.13.0.tgz#c8e9ce5bafaf10d930a67d7ed0ccb5d958fe0110" + integrity sha512-1SOHpy7ZNTPulzIbargrgaJX387csN7cF1cLOGZiJQA6VqnS5eWs2CIrG8i8wmaUavj2QlQ5oEbRMVVXSsGrzA== + dependencies: + npmlog "^4.1.2" + +"@lerna/query-graph@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/query-graph/-/query-graph-3.18.5.tgz#df4830bb5155273003bf35e8dda1c32d0927bd86" + integrity sha512-50Lf4uuMpMWvJ306be3oQDHrWV42nai9gbIVByPBYJuVW8dT8O8pA3EzitNYBUdLL9/qEVbrR0ry1HD7EXwtRA== + dependencies: + "@lerna/package-graph" "3.18.5" + figgy-pudding "^3.5.1" + +"@lerna/resolve-symlink@3.16.0": + version "3.16.0" + resolved "https://registry.yarnpkg.com/@lerna/resolve-symlink/-/resolve-symlink-3.16.0.tgz#37fc7095fabdbcf317c26eb74e0d0bde8efd2386" + integrity sha512-Ibj5e7njVHNJ/NOqT4HlEgPFPtPLWsO7iu59AM5bJDcAJcR96mLZ7KGVIsS2tvaO7akMEJvt2P+ErwCdloG3jQ== + dependencies: + fs-extra "^8.1.0" + npmlog "^4.1.2" + read-cmd-shim "^1.0.1" + +"@lerna/rimraf-dir@3.16.5": + version "3.16.5" + resolved "https://registry.yarnpkg.com/@lerna/rimraf-dir/-/rimraf-dir-3.16.5.tgz#04316ab5ffd2909657aaf388ea502cb8c2f20a09" + integrity sha512-bQlKmO0pXUsXoF8lOLknhyQjOZsCc0bosQDoX4lujBXSWxHVTg1VxURtWf2lUjz/ACsJVDfvHZbDm8kyBk5okA== + dependencies: + "@lerna/child-process" "3.16.5" + npmlog "^4.1.2" + path-exists "^3.0.0" + rimraf "^2.6.2" + +"@lerna/run-lifecycle@3.16.2": + version "3.16.2" + resolved "https://registry.yarnpkg.com/@lerna/run-lifecycle/-/run-lifecycle-3.16.2.tgz#67b288f8ea964db9ea4fb1fbc7715d5bbb0bce00" + integrity sha512-RqFoznE8rDpyyF0rOJy3+KjZCeTkO8y/OB9orPauR7G2xQ7PTdCpgo7EO6ZNdz3Al+k1BydClZz/j78gNCmL2A== + dependencies: + "@lerna/npm-conf" "3.16.0" + figgy-pudding "^3.5.1" + npm-lifecycle "^3.1.2" + npmlog "^4.1.2" + +"@lerna/run-topologically@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/run-topologically/-/run-topologically-3.18.5.tgz#3cd639da20e967d7672cb88db0f756b92f2fdfc3" + integrity sha512-6N1I+6wf4hLOnPW+XDZqwufyIQ6gqoPfHZFkfWlvTQ+Ue7CuF8qIVQ1Eddw5HKQMkxqN10thKOFfq/9NQZ4NUg== + dependencies: + "@lerna/query-graph" "3.18.5" + figgy-pudding "^3.5.1" + p-queue "^4.0.0" + +"@lerna/run@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/run/-/run-3.18.5.tgz#09ae809b16445d3621249c24596cf4ae8e250d5d" + integrity sha512-1S0dZccNJO8+gT5ztYE4rHTEnbXVwThHOfDnlVt2KDxl9cbnBALk3xprGLW7lSzJsxegS849hxrAPUh0UorMgw== + dependencies: + "@lerna/command" "3.18.5" + "@lerna/filter-options" "3.18.4" + "@lerna/npm-run-script" "3.16.5" + "@lerna/output" "3.13.0" + "@lerna/run-topologically" "3.18.5" + "@lerna/timer" "3.13.0" + "@lerna/validation-error" "3.13.0" + p-map "^2.1.0" + +"@lerna/symlink-binary@3.17.0": + version "3.17.0" + resolved "https://registry.yarnpkg.com/@lerna/symlink-binary/-/symlink-binary-3.17.0.tgz#8f8031b309863814883d3f009877f82e38aef45a" + integrity sha512-RLpy9UY6+3nT5J+5jkM5MZyMmjNHxZIZvXLV+Q3MXrf7Eaa1hNqyynyj4RO95fxbS+EZc4XVSk25DGFQbcRNSQ== + dependencies: + "@lerna/create-symlink" "3.16.2" + "@lerna/package" "3.16.0" + fs-extra "^8.1.0" + p-map "^2.1.0" + +"@lerna/symlink-dependencies@3.17.0": + version "3.17.0" + resolved "https://registry.yarnpkg.com/@lerna/symlink-dependencies/-/symlink-dependencies-3.17.0.tgz#48d6360e985865a0e56cd8b51b308a526308784a" + integrity sha512-KmjU5YT1bpt6coOmdFueTJ7DFJL4H1w5eF8yAQ2zsGNTtZ+i5SGFBWpb9AQaw168dydc3s4eu0W0Sirda+F59Q== + dependencies: + "@lerna/create-symlink" "3.16.2" + "@lerna/resolve-symlink" "3.16.0" + "@lerna/symlink-binary" "3.17.0" + fs-extra "^8.1.0" + p-finally "^1.0.0" + p-map "^2.1.0" + p-map-series "^1.0.0" + +"@lerna/timer@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@lerna/timer/-/timer-3.13.0.tgz#bcd0904551db16e08364d6c18e5e2160fc870781" + integrity sha512-RHWrDl8U4XNPqY5MQHkToWS9jHPnkLZEt5VD+uunCKTfzlxGnRCr3/zVr8VGy/uENMYpVP3wJa4RKGY6M0vkRw== + +"@lerna/validation-error@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@lerna/validation-error/-/validation-error-3.13.0.tgz#c86b8f07c5ab9539f775bd8a54976e926f3759c3" + integrity sha512-SiJP75nwB8GhgwLKQfdkSnDufAaCbkZWJqEDlKOUPUvVOplRGnfL+BPQZH5nvq2BYSRXsksXWZ4UHVnQZI/HYA== + dependencies: + npmlog "^4.1.2" + +"@lerna/version@3.18.5": + version "3.18.5" + resolved "https://registry.yarnpkg.com/@lerna/version/-/version-3.18.5.tgz#0c4f0c2f8d23e9c95c2aa77ad9ce5c7ef025fac0" + integrity sha512-eSMxLIDuVxZIq0JZKNih50x1IZuMmViwF59uwOGMx0hHB84N3waE8HXOF9CJXDSjeP6sHB8tS+Y+X5fFpBop2Q== + dependencies: + "@lerna/check-working-tree" "3.16.5" + "@lerna/child-process" "3.16.5" + "@lerna/collect-updates" "3.18.0" + "@lerna/command" "3.18.5" + "@lerna/conventional-commits" "3.18.5" + "@lerna/github-client" "3.16.5" + "@lerna/gitlab-client" "3.15.0" + "@lerna/output" "3.13.0" + "@lerna/prerelease-id-from-version" "3.16.0" + "@lerna/prompt" "3.18.5" + "@lerna/run-lifecycle" "3.16.2" + "@lerna/run-topologically" "3.18.5" + "@lerna/validation-error" "3.13.0" + chalk "^2.3.1" + dedent "^0.7.0" + load-json-file "^5.3.0" + minimatch "^3.0.4" + npmlog "^4.1.2" + p-map "^2.1.0" + p-pipe "^1.2.0" + p-reduce "^1.0.0" + p-waterfall "^1.0.0" + semver "^6.2.0" + slash "^2.0.0" + temp-write "^3.4.0" + write-json-file "^3.2.0" + +"@lerna/write-log-file@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@lerna/write-log-file/-/write-log-file-3.13.0.tgz#b78d9e4cfc1349a8be64d91324c4c8199e822a26" + integrity sha512-RibeMnDPvlL8bFYW5C8cs4mbI3AHfQef73tnJCQ/SgrXZHehmHnsyWUiE7qDQCAo+B1RfTapvSyFF69iPj326A== + dependencies: + npmlog "^4.1.2" + write-file-atomic "^2.3.0" + +"@mrmlnc/readdir-enhanced@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" + integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== + dependencies: + call-me-maybe "^1.0.1" + glob-to-regexp "^0.3.0" + +"@nodelib/fs.stat@^1.1.2": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" + integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== + +"@octokit/endpoint@^5.5.0": + version "5.5.1" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-5.5.1.tgz#2eea81e110ca754ff2de11c79154ccab4ae16b3f" + integrity sha512-nBFhRUb5YzVTCX/iAK1MgQ4uWo89Gu0TH00qQHoYRCsE12dWcG1OiLd7v2EIo2+tpUKPMOQ62QFy9hy9Vg2ULg== + dependencies: + "@octokit/types" "^2.0.0" + is-plain-object "^3.0.0" + universal-user-agent "^4.0.0" + +"@octokit/plugin-enterprise-rest@^3.6.1": + version "3.6.2" + resolved "https://registry.yarnpkg.com/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-3.6.2.tgz#74de25bef21e0182b4fa03a8678cd00a4e67e561" + integrity sha512-3wF5eueS5OHQYuAEudkpN+xVeUsg8vYEMMenEzLphUZ7PRZ8OJtDcsreL3ad9zxXmBbaFWzLmFcdob5CLyZftA== + +"@octokit/request-error@^1.0.1", "@octokit/request-error@^1.0.2": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.2.0.tgz#a64d2a9d7a13555570cd79722de4a4d76371baaa" + integrity sha512-DNBhROBYjjV/I9n7A8kVkmQNkqFAMem90dSxqvPq57e2hBr7mNTX98y3R2zDpqMQHVRpBDjsvsfIGgBzy+4PAg== + dependencies: + "@octokit/types" "^2.0.0" + deprecation "^2.0.0" + once "^1.4.0" + +"@octokit/request@^5.2.0": + version "5.3.1" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.3.1.tgz#3a1ace45e6f88b1be4749c5da963b3a3b4a2f120" + integrity sha512-5/X0AL1ZgoU32fAepTfEoggFinO3rxsMLtzhlUX+RctLrusn/CApJuGFCd0v7GMFhF+8UiCsTTfsu7Fh1HnEJg== + dependencies: + "@octokit/endpoint" "^5.5.0" + "@octokit/request-error" "^1.0.1" + "@octokit/types" "^2.0.0" + deprecation "^2.0.0" + is-plain-object "^3.0.0" + node-fetch "^2.3.0" + once "^1.4.0" + universal-user-agent "^4.0.0" + +"@octokit/rest@^16.28.4": + version "16.35.0" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.35.0.tgz#7ccc1f802f407d5b8eb21768c6deca44e7b4c0d8" + integrity sha512-9ShFqYWo0CLoGYhA1FdtdykJuMzS/9H6vSbbQWDX4pWr4p9v+15MsH/wpd/3fIU+tSxylaNO48+PIHqOkBRx3w== + dependencies: + "@octokit/request" "^5.2.0" + "@octokit/request-error" "^1.0.2" + atob-lite "^2.0.0" + before-after-hook "^2.0.0" + btoa-lite "^1.0.0" + deprecation "^2.0.0" + lodash.get "^4.4.2" + lodash.set "^4.3.2" + lodash.uniq "^4.5.0" + octokit-pagination-methods "^1.1.0" + once "^1.4.0" + universal-user-agent "^4.0.0" + +"@octokit/types@^2.0.0": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.0.2.tgz#0888497f5a664e28b0449731d5e88e19b2a74f90" + integrity sha512-StASIL2lgT3TRjxv17z9pAqbnI7HGu9DrJlg3sEBFfCLaMEqp+O3IQPUF6EZtQ4xkAu2ml6kMBBCtGxjvmtmuQ== + dependencies: + "@types/node" ">= 8" + +"@types/events@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" + integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== + +"@types/glob@^7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" + integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== + dependencies: + "@types/events" "*" + "@types/minimatch" "*" + "@types/node" "*" + +"@types/minimatch@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== + +"@types/node@*", "@types/node@>= 8": + version "12.12.14" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.14.tgz#1c1d6e3c75dba466e0326948d56e8bd72a1903d2" + integrity sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA== + +"@zkochan/cmd-shim@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz#2ab8ed81f5bb5452a85f25758eb9b8681982fd2e" + integrity sha512-o8l0+x7C7sMZU3v9GuJIAU10qQLtwR1dtRQIOmlNMtyaqhmpXOzx1HWiYoWfmmf9HHZoAkXpc9TM9PQYF9d4Jg== + dependencies: + is-windows "^1.0.0" + mkdirp-promise "^5.0.1" + mz "^2.5.0" + +JSONStream@^1.0.4, JSONStream@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" + integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== + dependencies: + jsonparse "^1.2.0" + through ">=2.2.7 <3" + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +acorn-jsx@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" + integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== + +acorn@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" + integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== + +agent-base@4, agent-base@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.3.0.tgz#8165f01c436009bccad0b1d122f05ed770efc6ee" + integrity sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg== + dependencies: + es6-promisify "^5.0.0" + +agent-base@~4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-4.2.1.tgz#d89e5999f797875674c07d87f260fc41e83e8ca9" + integrity sha512-JVwXMr9nHYTUXsBFKUqhJwvlcYU/blreOEUkhNR2eXZIvwd+c+o5V4MgDPKWnMS/56awN3TRzIP+KoPn+roQtg== + dependencies: + es6-promisify "^5.0.0" + +agentkeepalive@^3.4.1: + version "3.5.2" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-3.5.2.tgz#a113924dd3fa24a0bc3b78108c450c2abee00f67" + integrity sha512-e0L/HNe6qkQ7H19kTlRRqUibEAwDK5AFk6y3PtMsuut2VAH6+Q4xZml1tNDJD7kSAyqmbG/K08K5WEJYtUrSlQ== + dependencies: + humanize-ms "^1.2.1" + +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: + version "6.10.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" + integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== + dependencies: + fast-deep-equal "^2.0.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + +ansi-escapes@^4.2.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" + integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== + dependencies: + type-fest "^0.8.1" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^3.2.0, ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +any-promise@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= + +aproba@^1.0.3, aproba@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +aproba@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-2.0.0.tgz#52520b8ae5b569215b354efc0caa3fe1e45a8adc" + integrity sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ== + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-differ@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-differ/-/array-differ-2.1.0.tgz#4b9c1c3f14b906757082925769e8ab904f4801b1" + integrity sha512-KbUpJgx909ZscOc/7CLATBFam7P1Z1QRQInvgT0UztM9Q72aGKCunKASAl7WNW0tnPmPyEMeMhdsfWhfmW037w== + +array-find-index@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-find-index/-/array-find-index-1.0.2.tgz#df010aa1287e164bbda6f9723b0a96a1ec4187a1" + integrity sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E= + +array-ify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" + integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= + +array-includes@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" + integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.7.0" + +array-union@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= + dependencies: + array-uniq "^1.0.1" + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + +asap@^2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" + integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + +async@0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/async/-/async-0.9.0.tgz#ac3613b1da9bed1b47510bb4651b8931e47146c7" + integrity sha1-rDYTsdqb7RtHUQu0ZRuJMeRxRsc= + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +atob-lite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/atob-lite/-/atob-lite-2.0.0.tgz#0fef5ad46f1bd7a8502c65727f0367d5ee43d696" + integrity sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY= + +atob@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c" + integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +before-after-hook@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635" + integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A== + +bluebird@3.5.2: + version "3.5.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" + integrity sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg== + +bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5: + version "3.7.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de" + integrity sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +btoa-lite@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" + integrity sha1-M3dm2hWAEhD92VbCLpxokaudAzc= + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +buffer-writer@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" + integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== + +builtins@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/builtins/-/builtins-1.0.3.tgz#cb94faeb61c8696451db36534e1422f94f0aee88" + integrity sha1-y5T662HIaWRR2zZTThQi+U8K7og= + +byline@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/byline/-/byline-5.0.0.tgz#741c5216468eadc457b03410118ad77de8c1ddb1" + integrity sha1-dBxSFkaOrcRXsDQQEYrXfejB3bE= + +byte-size@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/byte-size/-/byte-size-5.0.1.tgz#4b651039a5ecd96767e71a3d7ed380e48bed4191" + integrity sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw== + +cacache@^12.0.0, cacache@^12.0.3: + version "12.0.3" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" + integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== + dependencies: + bluebird "^3.5.5" + chownr "^1.1.1" + figgy-pudding "^3.5.1" + glob "^7.1.4" + graceful-fs "^4.1.15" + infer-owner "^1.0.3" + lru-cache "^5.1.1" + mississippi "^3.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.3" + ssri "^6.0.1" + unique-filename "^1.1.1" + y18n "^4.0.0" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +call-me-maybe@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" + integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camelcase-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-2.1.0.tgz#308beeaffdf28119051efa1d932213c91b8f92e7" + integrity sha1-MIvur/3ygRkFHvodkyITyRuPkuc= + dependencies: + camelcase "^2.0.0" + map-obj "^1.0.0" + +camelcase-keys@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-4.2.0.tgz#a2aa5fb1af688758259c32c141426d78923b9b77" + integrity sha1-oqpfsa9oh1glnDLBQUJteJI7m3c= + dependencies: + camelcase "^4.1.0" + map-obj "^2.0.0" + quick-lru "^1.0.0" + +camelcase@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" + integrity sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8= + +camelcase@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" + integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +chownr@^1.1.1, chownr@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" + integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== + +ci-info@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" + integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + +cli-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" + integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== + dependencies: + restore-cursor "^3.1.0" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +clone-deep@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" + integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== + dependencies: + is-plain-object "^2.0.4" + kind-of "^6.0.2" + shallow-clone "^3.0.0" + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + +co@4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +columnify@^1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" + integrity sha1-Rzfd8ce2mop8NAVweC6UfuyOeLs= + dependencies: + strip-ansi "^3.0.0" + wcwidth "^1.0.0" + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +commander@~2.20.3: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +compare-func@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.2.tgz#99dd0ba457e1f9bc722b12c08ec33eeab31fa648" + integrity sha1-md0LpFfh+bxyKxLAjsM+6rMfpkg= + dependencies: + array-ify "^1.0.0" + dot-prop "^3.0.0" + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.5.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +concat-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-2.0.0.tgz#414cf5af790a48c60ab9be4527d56d5e41133cb1" + integrity sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.0.2" + typedarray "^0.0.6" + +config-chain@^1.1.11: + version "1.1.12" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" + integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= + +conventional-changelog-angular@^5.0.3: + version "5.0.6" + resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.6.tgz#269540c624553aded809c29a3508fdc2b544c059" + integrity sha512-QDEmLa+7qdhVIv8sFZfVxU1VSyVvnXPsxq8Vam49mKUcO1Z8VTLEJk9uI21uiJUsnmm0I4Hrsdc9TgkOQo9WSA== + dependencies: + compare-func "^1.3.1" + q "^1.5.1" + +conventional-changelog-core@^3.1.6: + version "3.2.3" + resolved "https://registry.yarnpkg.com/conventional-changelog-core/-/conventional-changelog-core-3.2.3.tgz#b31410856f431c847086a7dcb4d2ca184a7d88fb" + integrity sha512-LMMX1JlxPIq/Ez5aYAYS5CpuwbOk6QFp8O4HLAcZxe3vxoCtABkhfjetk8IYdRB9CDQGwJFLR3Dr55Za6XKgUQ== + dependencies: + conventional-changelog-writer "^4.0.6" + conventional-commits-parser "^3.0.3" + dateformat "^3.0.0" + get-pkg-repo "^1.0.0" + git-raw-commits "2.0.0" + git-remote-origin-url "^2.0.0" + git-semver-tags "^2.0.3" + lodash "^4.2.1" + normalize-package-data "^2.3.5" + q "^1.5.1" + read-pkg "^3.0.0" + read-pkg-up "^3.0.0" + through2 "^3.0.0" + +conventional-changelog-preset-loader@^2.1.1: + version "2.3.0" + resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.0.tgz#580fa8ab02cef22c24294d25e52d7ccd247a9a6a" + integrity sha512-/rHb32J2EJnEXeK4NpDgMaAVTFZS3o1ExmjKMtYVgIC4MQn0vkNSbYpdGRotkfGGRWiqk3Ri3FBkiZGbAfIfOQ== + +conventional-changelog-writer@^4.0.6: + version "4.0.11" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.11.tgz#9f56d2122d20c96eb48baae0bf1deffaed1edba4" + integrity sha512-g81GQOR392I+57Cw3IyP1f+f42ME6aEkbR+L7v1FBBWolB0xkjKTeCWVguzRrp6UiT1O6gBpJbEy2eq7AnV1rw== + dependencies: + compare-func "^1.3.1" + conventional-commits-filter "^2.0.2" + dateformat "^3.0.0" + handlebars "^4.4.0" + json-stringify-safe "^5.0.1" + lodash "^4.17.15" + meow "^5.0.0" + semver "^6.0.0" + split "^1.0.0" + through2 "^3.0.0" + +conventional-commits-filter@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.2.tgz#f122f89fbcd5bb81e2af2fcac0254d062d1039c1" + integrity sha512-WpGKsMeXfs21m1zIw4s9H5sys2+9JccTzpN6toXtxhpw2VNF2JUXwIakthKBy+LN4DvJm+TzWhxOMWOs1OFCFQ== + dependencies: + lodash.ismatch "^4.4.0" + modify-values "^1.0.0" + +conventional-commits-parser@^3.0.3: + version "3.0.8" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.0.8.tgz#23310a9bda6c93c874224375e72b09fb275fe710" + integrity sha512-YcBSGkZbYp7d+Cr3NWUeXbPDFUN6g3SaSIzOybi8bjHL5IJ5225OSCxJJ4LgziyEJ7AaJtE9L2/EU6H7Nt/DDQ== + dependencies: + JSONStream "^1.0.4" + is-text-path "^1.0.1" + lodash "^4.17.15" + meow "^5.0.0" + split2 "^2.0.0" + through2 "^3.0.0" + trim-off-newlines "^1.0.0" + +conventional-recommended-bump@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/conventional-recommended-bump/-/conventional-recommended-bump-5.0.1.tgz#5af63903947b6e089e77767601cb592cabb106ba" + integrity sha512-RVdt0elRcCxL90IrNP0fYCpq1uGt2MALko0eyeQ+zQuDVWtMGAy9ng6yYn3kax42lCj9+XBxQ8ZN6S9bdKxDhQ== + dependencies: + concat-stream "^2.0.0" + conventional-changelog-preset-loader "^2.1.1" + conventional-commits-filter "^2.0.2" + conventional-commits-parser "^3.0.3" + git-raw-commits "2.0.0" + git-semver-tags "^2.0.3" + meow "^4.0.0" + q "^1.5.1" + +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== + dependencies: + aproba "^1.1.1" + fs-write-stream-atomic "^1.0.8" + iferr "^0.1.5" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.0" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +cosmiconfig@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +cross-spawn@^6.0.0, cross-spawn@^6.0.5: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +currently-unhandled@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" + integrity sha1-mI3zP+qxke95mmE2nddsF635V+o= + dependencies: + array-find-index "^1.0.1" + +cyclist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" + integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= + +dargs@^4.0.1: + version "4.1.0" + resolved "https://registry.yarnpkg.com/dargs/-/dargs-4.1.0.tgz#03a9dbb4b5c2f139bf14ae53f0b8a2a6a86f4e17" + integrity sha1-A6nbtLXC8Tm/FK5T8LiipqhvThc= + dependencies: + number-is-nan "^1.0.0" + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +dateformat@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" + integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== + +debug@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +debuglog@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" + integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= + +decamelize-keys@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" + integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= + dependencies: + decamelize "^1.1.0" + map-obj "^1.0.0" + +decamelize@^1.1.0, decamelize@^1.1.2, decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +dedent@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" + integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +defaults@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" + +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +deprecation@^2.0.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" + integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== + +detect-indent@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" + integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= + +dezalgo@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" + integrity sha1-f3Qt4Gb8dIvI24IFad3c5Jvw1FY= + dependencies: + asap "^2.0.0" + wrappy "1" + +dir-glob@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" + integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== + dependencies: + path-type "^3.0.0" + +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dot-prop@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177" + integrity sha1-G3CK8JSknJoOfbyteQq6U52sEXc= + dependencies: + is-obj "^1.0.0" + +dot-prop@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== + dependencies: + is-obj "^1.0.0" + +duplexer@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= + +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +encoding@^0.1.11: + version "0.1.12" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" + integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= + dependencies: + iconv-lite "~0.4.13" + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +env-paths@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0" + integrity sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA= + +err-code@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" + integrity sha1-BuARbTAo9q70gGhJ6w6mp0iuaWA= + +error-ex@^1.2.0, error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.12.0, es-abstract@^1.5.1, es-abstract@^1.7.0: + version "1.16.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.2.tgz#4e874331645e9925edef141e74fc4bd144669d34" + integrity sha512-jYo/J8XU2emLXl3OLwfwtuFfuF2w6DYPs+xy9ZfVyPkDcrauu6LYrw/q2TyCtrbc/KUdCiC5e9UajRhgNkVopA== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.1.4" + is-regex "^1.0.4" + object-inspect "^1.7.0" + object-keys "^1.1.1" + string.prototype.trimleft "^2.1.0" + string.prototype.trimright "^2.1.0" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es6-promise@^4.0.3: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +es6-promisify@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" + integrity sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM= + dependencies: + es6-promise "^4.0.3" + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +eslint-config-standard@^13.0.1: + version "13.0.1" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-13.0.1.tgz#c9c6ffe0cfb8a51535bc5c7ec9f70eafb8c6b2c0" + integrity sha512-zLKp4QOgq6JFgRm1dDCVv1Iu0P5uZ4v5Wa4DTOkg2RFMxdCX/9Qf7lz9ezRj2dBRa955cWQF/O/LWEiYWAHbTw== + +eslint-import-resolver-node@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" + integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== + dependencies: + debug "^2.6.9" + resolve "^1.5.0" + +eslint-module-utils@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz#7b4675875bf96b0dbf1b21977456e5bb1f5e018c" + integrity sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw== + dependencies: + debug "^2.6.8" + pkg-dir "^2.0.0" + +eslint-plugin-es@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-1.4.1.tgz#12acae0f4953e76ba444bfd1b2271081ac620998" + integrity sha512-5fa/gR2yR3NxQf+UXkeLeP8FBBl6tSgdrAz1+cF84v1FMM4twGwQoqTnn+QxFLcPOrF4pdKEJKDB/q9GoyJrCA== + dependencies: + eslint-utils "^1.4.2" + regexpp "^2.0.1" + +eslint-plugin-import@^2.18.1: + version "2.18.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz#02f1180b90b077b33d447a17a2326ceb400aceb6" + integrity sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ== + dependencies: + array-includes "^3.0.3" + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.2" + eslint-module-utils "^2.4.0" + has "^1.0.3" + minimatch "^3.0.4" + object.values "^1.1.0" + read-pkg-up "^2.0.0" + resolve "^1.11.0" + +eslint-plugin-node@^9.1.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-9.2.0.tgz#b1911f111002d366c5954a6d96d3cd5bf2a3036a" + integrity sha512-2abNmzAH/JpxI4gEOwd6K8wZIodK3BmHbTxz4s79OIYwwIt2gkpEXlAouJXu4H1c9ySTnRso0tsuthSOZbUMlA== + dependencies: + eslint-plugin-es "^1.4.1" + eslint-utils "^1.4.2" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + +eslint-plugin-promise@^4.2.1: + version "4.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" + integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw== + +eslint-plugin-standard@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz#ff0519f7ffaff114f76d1bd7c3996eef0f6e20b4" + integrity sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ== + +eslint-scope@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" + integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +eslint-utils@^1.4.2, eslint-utils@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" + integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== + +eslint@^6.0.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.1.tgz#269ccccec3ef60ab32358a44d147ac209154b919" + integrity sha512-UWzBS79pNcsDSxgxbdjkmzn/B6BhsXMfUaOHnNwyE8nD+Q6pyT96ow2MccVayUTV4yMid4qLhMiQaywctRkBLA== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.10.0" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^5.0.0" + eslint-utils "^1.4.3" + eslint-visitor-keys "^1.1.0" + espree "^6.1.2" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^7.0.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.14" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.3" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^6.1.2: + version "6.1.2" + resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" + integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== + dependencies: + acorn "^7.1.0" + acorn-jsx "^5.1.0" + eslint-visitor-keys "^1.1.0" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esquery@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" + integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== + dependencies: + estraverse "^4.0.0" + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +eventemitter3@^3.1.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" + integrity sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q== + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +fast-deep-equal@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" + integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= + +fast-glob@^2.2.6: + version "2.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" + integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== + dependencies: + "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.1.2" + glob-parent "^3.1.0" + is-glob "^4.0.0" + merge2 "^1.2.3" + micromatch "^3.1.10" + +fast-json-stable-stringify@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" + integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + +fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" + integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + dependencies: + escape-string-regexp "^1.0.5" + +figures@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" + integrity sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg== + dependencies: + escape-string-regexp "^1.0.5" + +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +find-up@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" + integrity sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= + dependencies: + path-exists "^2.0.0" + pinkie-promise "^2.0.0" + +find-up@^2.0.0, find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== + dependencies: + flatted "^2.0.0" + rimraf "2.6.3" + write "1.0.3" + +flatted@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" + integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== + +flush-write-stream@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== + dependencies: + inherits "^2.0.3" + readable-stream "^2.3.6" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +from2@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-minipass@^1.2.5: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + +fs-write-stream-atomic@^1.0.8: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +genfun@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/genfun/-/genfun-5.0.0.tgz#9dd9710a06900a5c4a5bf57aca5da4e52fe76537" + integrity sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-pkg-repo@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d" + integrity sha1-xztInAbYDMVTbCyFP54FIyBWly0= + dependencies: + hosted-git-info "^2.1.4" + meow "^3.3.0" + normalize-package-data "^2.3.0" + parse-github-repo-url "^1.3.0" + through2 "^2.0.0" + +get-port@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/get-port/-/get-port-4.2.0.tgz#e37368b1e863b7629c43c5a323625f95cf24b119" + integrity sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw== + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= + +get-stream@^4.0.0, get-stream@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +git-raw-commits@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.0.tgz#d92addf74440c14bcc5c83ecce3fb7f8a79118b5" + integrity sha512-w4jFEJFgKXMQJ0H0ikBk2S+4KP2VEjhCvLCNqbNRQC8BgGWgLKNCO7a9K9LI+TVT7Gfoloje502sEnctibffgg== + dependencies: + dargs "^4.0.1" + lodash.template "^4.0.2" + meow "^4.0.0" + split2 "^2.0.0" + through2 "^2.0.0" + +git-remote-origin-url@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz#5282659dae2107145a11126112ad3216ec5fa65f" + integrity sha1-UoJlna4hBxRaERJhEq0yFuxfpl8= + dependencies: + gitconfiglocal "^1.0.0" + pify "^2.3.0" + +git-semver-tags@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/git-semver-tags/-/git-semver-tags-2.0.3.tgz#48988a718acf593800f99622a952a77c405bfa34" + integrity sha512-tj4FD4ww2RX2ae//jSrXZzrocla9db5h0V7ikPl1P/WwoZar9epdUhwR7XHXSgc+ZkNq72BEEerqQuicoEQfzA== + dependencies: + meow "^4.0.0" + semver "^6.0.0" + +git-up@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/git-up/-/git-up-4.0.1.tgz#cb2ef086653640e721d2042fe3104857d89007c0" + integrity sha512-LFTZZrBlrCrGCG07/dm1aCjjpL1z9L3+5aEeI9SBhAqSc+kiA9Or1bgZhQFNppJX6h/f5McrvJt1mQXTFm6Qrw== + dependencies: + is-ssh "^1.3.0" + parse-url "^5.0.0" + +git-url-parse@^11.1.2: + version "11.1.2" + resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-11.1.2.tgz#aff1a897c36cc93699270587bea3dbcbbb95de67" + integrity sha512-gZeLVGY8QVKMIkckncX+iCq2/L8PlwncvDFKiWkBn9EtCfYDbliRTTp6qzyQ1VMdITUfq7293zDzfpjdiGASSQ== + dependencies: + git-up "^4.0.0" + +gitconfiglocal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz#41d045f3851a5ea88f03f24ca1c6178114464b9b" + integrity sha1-QdBF84UaXqiPA/JMocYXgRRGS5s= + dependencies: + ini "^1.3.2" + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-parent@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" + integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== + dependencies: + is-glob "^4.0.1" + +glob-to-regexp@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" + integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= + +glob@^7.0.3, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^12.1.0: + version "12.3.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13" + integrity sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw== + dependencies: + type-fest "^0.8.1" + +globby@^9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" + integrity sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg== + dependencies: + "@types/glob" "^7.1.1" + array-union "^1.0.2" + dir-glob "^2.2.2" + fast-glob "^2.2.6" + glob "^7.1.3" + ignore "^4.0.3" + pify "^4.0.1" + slash "^2.0.0" + +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + +handlebars@^4.4.0: + version "4.5.3" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" + integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA== + dependencies: + neo-async "^2.6.0" + optimist "^0.6.1" + source-map "^0.6.1" + optionalDependencies: + uglify-js "^3.1.4" + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.0: + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + dependencies: + ajv "^6.5.5" + har-schema "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + +has-unicode@^2.0.0, has-unicode@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.1, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hosted-git-info@^2.1.4, hosted-git-info@^2.7.1: + version "2.8.5" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" + integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg== + +http-cache-semantics@^3.8.1: + version "3.8.1" + resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" + integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== + +http-proxy-agent@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz#e4821beef5b2142a2026bd73926fe537631c5405" + integrity sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg== + dependencies: + agent-base "4" + debug "3.1.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-proxy-agent@^2.2.3: + version "2.2.4" + resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-2.2.4.tgz#4ee7a737abd92678a293d9b34a1af4d0d08c787b" + integrity sha512-OmvfoQ53WLjtA9HeYP9RNrWMJzzAz1JGaSFr1nijg0PVR1JaD/xbJq1mdEIIlxGpXp9eSe/O2LgU9DJmTPd0Eg== + dependencies: + agent-base "^4.3.0" + debug "^3.1.0" + +humanize-ms@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed" + integrity sha1-xG4xWaKT9riW2ikxbYtv6Lt5u+0= + dependencies: + ms "^2.0.0" + +iconv-lite@^0.4.24, iconv-lite@~0.4.13: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +iferr@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= + +ignore-walk@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" + integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== + dependencies: + minimatch "^3.0.4" + +ignore@^4.0.3, ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.1: + version "5.1.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" + integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-fresh@^3.0.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" + integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-local@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" + integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== + dependencies: + pkg-dir "^3.0.0" + resolve-cwd "^2.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indent-string@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" + integrity sha1-ji1INIdCEhtKghi3oTfppSBJ3IA= + dependencies: + repeating "^2.0.0" + +indent-string@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" + integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= + +infer-owner@^1.0.3, infer-owner@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@^1.3.2, ini@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +init-package-json@^1.10.3: + version "1.10.3" + resolved "https://registry.yarnpkg.com/init-package-json/-/init-package-json-1.10.3.tgz#45ffe2f610a8ca134f2bd1db5637b235070f6cbe" + integrity sha512-zKSiXKhQveNteyhcj1CoOP8tqp1QuxPIPBl8Bid99DGLFqA1p87M6lNgfjJHSBoWJJlidGOv5rWjyYKEB3g2Jw== + dependencies: + glob "^7.1.1" + npm-package-arg "^4.0.0 || ^5.0.0 || ^6.0.0" + promzard "^0.3.0" + read "~1.0.1" + read-package-json "1 || 2" + semver "2.x || 3.x || 4 || 5" + validate-npm-package-license "^3.0.1" + validate-npm-package-name "^3.0.0" + +inquirer@^6.2.0: + version "6.5.2" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" + integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + +inquirer@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.0.tgz#9e2b032dde77da1db5db804758b8fea3a970519a" + integrity sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ== + dependencies: + ansi-escapes "^4.2.1" + chalk "^2.4.2" + cli-cursor "^3.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^3.0.0" + lodash "^4.17.15" + mute-stream "0.0.8" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^4.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + +ip@1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-callable@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" + integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== + +is-ci@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" + integrity sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w== + dependencies: + ci-info "^2.0.0" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" + integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-finite@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" + integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0, is-glob@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-obj@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + +is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-plain-object@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928" + integrity sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg== + dependencies: + isobject "^4.0.0" + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= + +is-regex@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" + integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + dependencies: + has "^1.0.1" + +is-ssh@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.1.tgz#f349a8cadd24e65298037a522cf7520f2e81a0f3" + integrity sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg== + dependencies: + protocols "^1.1.0" + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-symbol@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== + dependencies: + has-symbols "^1.0.1" + +is-text-path@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-text-path/-/is-text-path-1.0.1.tgz#4e1aa0fb51bfbcb3e92688001397202c1775b66e" + integrity sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4= + dependencies: + text-extensions "^1.0.0" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-utf8@^0.2.0: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" + integrity sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI= + +is-windows@^1.0.0, is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isobject@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" + integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + +json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +jsonparse@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" + integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA= + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== + +lerna@^3.19.0: + version "3.19.0" + resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.19.0.tgz#6d53b613eca7da426ab1e97c01ce6fb39754da6c" + integrity sha512-YtMmwEqzWHQCh7Ynk7BvjrZri3EkSeVqTAcwZIqWlv9V/dCfvFPyRqp+2NIjPB5nj1FWXLRH6F05VT/qvzuuOA== + dependencies: + "@lerna/add" "3.19.0" + "@lerna/bootstrap" "3.18.5" + "@lerna/changed" "3.18.5" + "@lerna/clean" "3.18.5" + "@lerna/cli" "3.18.5" + "@lerna/create" "3.18.5" + "@lerna/diff" "3.18.5" + "@lerna/exec" "3.18.5" + "@lerna/import" "3.18.5" + "@lerna/init" "3.18.5" + "@lerna/link" "3.18.5" + "@lerna/list" "3.18.5" + "@lerna/publish" "3.18.5" + "@lerna/run" "3.18.5" + "@lerna/version" "3.18.5" + import-local "^2.0.0" + npmlog "^4.1.2" + +levn@^0.3.0, levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +load-json-file@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" + integrity sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + pinkie-promise "^2.0.0" + strip-bom "^2.0.0" + +load-json-file@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" + integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= + dependencies: + graceful-fs "^4.1.2" + parse-json "^2.2.0" + pify "^2.0.0" + strip-bom "^3.0.0" + +load-json-file@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" + integrity sha1-L19Fq5HjMhYjT9U62rZo607AmTs= + dependencies: + graceful-fs "^4.1.2" + parse-json "^4.0.0" + pify "^3.0.0" + strip-bom "^3.0.0" + +load-json-file@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-5.3.0.tgz#4d3c1e01fa1c03ea78a60ac7af932c9ce53403f3" + integrity sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw== + dependencies: + graceful-fs "^4.1.15" + parse-json "^4.0.0" + pify "^4.0.1" + strip-bom "^3.0.0" + type-fest "^0.3.0" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= + +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= + +lodash.get@^4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" + integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= + +lodash.ismatch@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" + integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= + +lodash.set@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" + integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM= + +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= + +lodash.template@^4.0.2, lodash.template@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" + integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.templatesettings "^4.0.0" + +lodash.templatesettings@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" + integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== + dependencies: + lodash._reinterpolate "^3.0.0" + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + +lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +loud-rejection@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" + integrity sha1-W0b4AUft7leIcPCG0Eghz5mOVR8= + dependencies: + currently-unhandled "^0.4.1" + signal-exit "^3.0.0" + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +macos-release@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" + integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA== + +make-dir@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== + dependencies: + pify "^3.0.0" + +make-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +make-fetch-happen@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz#aa8387104f2687edca01c8687ee45013d02d19bd" + integrity sha512-07JHC0r1ykIoruKO8ifMXu+xEU8qOXDFETylktdug6vJDACnP+HKevOu3PXyNPzFyTSlz8vrBYlBO1JZRe8Cag== + dependencies: + agentkeepalive "^3.4.1" + cacache "^12.0.0" + http-cache-semantics "^3.8.1" + http-proxy-agent "^2.1.0" + https-proxy-agent "^2.2.3" + lru-cache "^5.1.1" + mississippi "^3.0.0" + node-fetch-npm "^2.0.2" + promise-retry "^1.1.1" + socks-proxy-agent "^4.0.0" + ssri "^6.0.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-obj@^1.0.0, map-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-1.0.1.tgz#d933ceb9205d82bdcf4886f6742bdc2b4dea146d" + integrity sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0= + +map-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" + integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +meow@^3.3.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" + integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= + dependencies: + camelcase-keys "^2.0.0" + decamelize "^1.1.2" + loud-rejection "^1.0.0" + map-obj "^1.0.1" + minimist "^1.1.3" + normalize-package-data "^2.3.4" + object-assign "^4.0.1" + read-pkg-up "^1.0.1" + redent "^1.0.0" + trim-newlines "^1.0.0" + +meow@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/meow/-/meow-4.0.1.tgz#d48598f6f4b1472f35bf6317a95945ace347f975" + integrity sha512-xcSBHD5Z86zaOc+781KrupuHAzeGXSLtiAOmBsiLDiPSaYSB6hdew2ng9EBAnZ62jagG9MHAOdxpDi/lWBFJ/A== + dependencies: + camelcase-keys "^4.0.0" + decamelize-keys "^1.0.0" + loud-rejection "^1.0.0" + minimist "^1.1.3" + minimist-options "^3.0.1" + normalize-package-data "^2.3.4" + read-pkg-up "^3.0.0" + redent "^2.0.0" + trim-newlines "^2.0.0" + +meow@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" + integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig== + dependencies: + camelcase-keys "^4.0.0" + decamelize-keys "^1.0.0" + loud-rejection "^1.0.0" + minimist-options "^3.0.1" + normalize-package-data "^2.3.4" + read-pkg-up "^3.0.0" + redent "^2.0.0" + trim-newlines "^2.0.0" + yargs-parser "^10.0.0" + +merge2@^1.2.3: + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== + +micromatch@^3.1.10: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +mime-db@1.42.0: + version "1.42.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" + integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== + +mime-types@^2.1.12, mime-types@~2.1.19: + version "2.1.25" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437" + integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg== + dependencies: + mime-db "1.42.0" + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist-options@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" + integrity sha512-FyBrT/d0d4+uiZRbqznPXqw3IpZZG3gl3wKWiX784FycUKVwBt0uLBFkQrtE4tZOrgo78nZp2jnKz3L65T5LdQ== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@^1.1.3, minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +minimist@~0.0.1: + version "0.0.10" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" + integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= + +minipass@^2.3.5, minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minizlib@^1.2.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== + dependencies: + concat-stream "^1.5.0" + duplexify "^3.4.2" + end-of-stream "^1.1.0" + flush-write-stream "^1.0.0" + from2 "^2.1.0" + parallel-transform "^1.1.0" + pump "^3.0.0" + pumpify "^1.3.3" + stream-each "^1.1.0" + through2 "^2.0.0" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp-promise@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" + integrity sha1-6bj2jlUsaKnBcTuEiD96HdA5uKE= + dependencies: + mkdirp "*" + +mkdirp@*, mkdirp@^0.5.0, mkdirp@^0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +modify-values@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" + integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== + +move-concurrently@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= + dependencies: + aproba "^1.1.1" + copy-concurrently "^1.0.0" + fs-write-stream-atomic "^1.0.8" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.3" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@^2.0.0, ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +multimatch@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-3.0.0.tgz#0e2534cc6bc238d9ab67e1b9cd5fcd85a6dbf70b" + integrity sha512-22foS/gqQfANZ3o+W7ST2x25ueHDVNWl/b9OlGcLpy/iKxjCpvcNCM51YCenUi7Mt/jAjjqv8JwZRs8YP5sRjA== + dependencies: + array-differ "^2.0.3" + array-union "^1.0.2" + arrify "^1.0.1" + minimatch "^3.0.4" + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= + +mute-stream@0.0.8, mute-stream@~0.0.4: + version "0.0.8" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" + integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== + +mz@^2.5.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q== + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + +neo-async@^2.6.0: + version "2.6.1" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" + integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +node-fetch-npm@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7" + integrity sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw== + dependencies: + encoding "^0.1.11" + json-parse-better-errors "^1.0.0" + safe-buffer "^5.1.1" + +node-fetch@^2.3.0, node-fetch@^2.5.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" + integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== + +node-gyp@^5.0.2: + version "5.0.5" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.0.5.tgz#f6cf1da246eb8c42b097d7cd4d6c3ce23a4163af" + integrity sha512-WABl9s4/mqQdZneZHVWVG4TVr6QQJZUC6PAx47ITSk9lreZ1n+7Z9mMAIbA3vnO4J9W20P7LhCxtzfWsAD/KDw== + dependencies: + env-paths "^1.0.0" + glob "^7.0.3" + graceful-fs "^4.1.2" + mkdirp "^0.5.0" + nopt "2 || 3" + npmlog "0 || 1 || 2 || 3 || 4" + request "^2.87.0" + rimraf "2" + semver "~5.3.0" + tar "^4.4.12" + which "1" + +"nopt@2 || 3": + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= + dependencies: + abbrev "1" + +normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8" + integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA== + dependencies: + hosted-git-info "^2.1.4" + resolve "^1.10.0" + semver "2 || 3 || 4 || 5" + validate-npm-package-license "^3.0.1" + +normalize-url@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" + integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== + +npm-bundled@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" + integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== + +npm-lifecycle@^3.1.2: + version "3.1.4" + resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-3.1.4.tgz#de6975c7d8df65f5150db110b57cce498b0b604c" + integrity sha512-tgs1PaucZwkxECGKhC/stbEgFyc3TGh2TJcg2CDr6jbvQRdteHNhmMeljRzpe4wgFAXQADoy1cSqqi7mtiAa5A== + dependencies: + byline "^5.0.0" + graceful-fs "^4.1.15" + node-gyp "^5.0.2" + resolve-from "^4.0.0" + slide "^1.1.6" + uid-number "0.0.6" + umask "^1.1.0" + which "^1.3.1" + +"npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", npm-package-arg@^6.0.0, npm-package-arg@^6.1.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.1.tgz#02168cb0a49a2b75bf988a28698de7b529df5cb7" + integrity sha512-qBpssaL3IOZWi5vEKUKW0cO7kzLeT+EQO9W8RsLOZf76KF9E/K9+wH0C7t06HXPpaH8WH5xF1MExLuCwbTqRUg== + dependencies: + hosted-git-info "^2.7.1" + osenv "^0.1.5" + semver "^5.6.0" + validate-npm-package-name "^3.0.0" + +npm-packlist@^1.4.4: + version "1.4.6" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.6.tgz#53ba3ed11f8523079f1457376dd379ee4ea42ff4" + integrity sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + +npm-pick-manifest@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/npm-pick-manifest/-/npm-pick-manifest-3.0.2.tgz#f4d9e5fd4be2153e5f4e5f9b7be8dc419a99abb7" + integrity sha512-wNprTNg+X5nf+tDi+hbjdHhM4bX+mKqv6XmPh7B5eG+QY9VARfQPfCEH013H5GqfNj6ee8Ij2fg8yk0mzps1Vw== + dependencies: + figgy-pudding "^3.5.1" + npm-package-arg "^6.0.0" + semver "^5.4.1" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4.0.1, object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" + integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + +object-keys@^1.0.12, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.getownpropertydescriptors@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" + integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + dependencies: + define-properties "^1.1.2" + es-abstract "^1.5.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +object.values@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" + integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.12.0" + function-bind "^1.1.1" + has "^1.0.3" + +octokit-pagination-methods@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4" + integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + dependencies: + mimic-fn "^1.0.0" + +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + +optimist@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" + integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= + dependencies: + minimist "~0.0.1" + wordwrap "~0.0.2" + +optionator@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-name@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.1.0.tgz#dec19d966296e1cd62d701a5a66ee1ddeae70801" + integrity sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg== + dependencies: + macos-release "^2.2.0" + windows-release "^3.1.0" + +os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" + integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== + dependencies: + p-try "^2.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-map-series@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca" + integrity sha1-v5j+V1cFZYqeE1G++4WuTB8Hvco= + dependencies: + p-reduce "^1.0.0" + +p-map@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + +p-pipe@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-1.2.0.tgz#4b1a11399a11520a67790ee5a0c1d5881d6befe9" + integrity sha1-SxoROZoRUgpneQ7loMHViB1r7+k= + +p-queue@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-4.0.0.tgz#ed0eee8798927ed6f2c2f5f5b77fdb2061a5d346" + integrity sha512-3cRXXn3/O0o3+eVmUroJPSj/esxoEFIm0ZOno/T+NzG/VZgPOqQ8WKmlNqubSEpZmCIngEy34unkHGg83ZIBmg== + dependencies: + eventemitter3 "^3.1.0" + +p-reduce@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-reduce/-/p-reduce-1.0.0.tgz#18c2b0dd936a4690a529f8231f58a0fdb6a47dfa" + integrity sha1-GMKw3ZNqRpClKfgjH1ig/bakffo= + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +p-waterfall@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-waterfall/-/p-waterfall-1.0.0.tgz#7ed94b3ceb3332782353af6aae11aa9fc235bb00" + integrity sha1-ftlLPOszMngjU69qrhGqn8I1uwA= + dependencies: + p-reduce "^1.0.0" + +packet-reader@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" + integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== + +parallel-transform@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" + integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== + dependencies: + cyclist "^1.0.1" + inherits "^2.0.3" + readable-stream "^2.1.5" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-github-repo-url@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50" + integrity sha1-nn2LslKmy2ukJZUGC3v23z28H1A= + +parse-json@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" + integrity sha1-9ID0BDTvgHQfhGkJn43qGPVaTck= + dependencies: + error-ex "^1.2.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-path@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.1.tgz#0ec769704949778cb3b8eda5e994c32073a1adff" + integrity sha512-d7yhga0Oc+PwNXDvQ0Jv1BuWkLVPXcAoQ/WREgd6vNNoKYaW52KI+RdOFjI63wjkmps9yUE8VS4veP+AgpQ/hA== + dependencies: + is-ssh "^1.3.0" + protocols "^1.4.0" + +parse-url@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-5.0.1.tgz#99c4084fc11be14141efa41b3d117a96fcb9527f" + integrity sha512-flNUPP27r3vJpROi0/R3/2efgKkyXqnXwyP1KQ2U0SfFRgdizOdWfvrrvJg1LuOoxs7GQhmxJlq23IpQ/BkByg== + dependencies: + is-ssh "^1.3.0" + normalize-url "^3.3.0" + parse-path "^4.0.0" + protocols "^1.4.0" + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-exists@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" + integrity sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= + dependencies: + pinkie-promise "^2.0.0" + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +path-type@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" + integrity sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE= + dependencies: + graceful-fs "^4.1.2" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +path-type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" + integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= + dependencies: + pify "^2.0.0" + +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +pg-connection-string@0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" + integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc= + +pg-copy-streams@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/pg-copy-streams/-/pg-copy-streams-0.3.0.tgz#a4fbc2a3b788d4e9da6f77ceb35422d8d7043b7f" + integrity sha1-pPvCo7eI1Onab3fOs1Qi2NcEO38= + +pg-int8@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" + integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== + +pg-pool@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.7.tgz#f14ecab83507941062c313df23f6adcd9fd0ce54" + integrity sha512-UiJyO5B9zZpu32GSlP0tXy8J2NsJ9EFGFfz5v6PSbdz/1hBLX1rNiiy5+mAm5iJJYwfCv4A0EBcQLGWwjbpzZw== + +pg-types@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" + integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== + dependencies: + pg-int8 "1.0.1" + postgres-array "~2.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.4" + postgres-interval "^1.1.0" + +pgpass@1.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" + integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY= + dependencies: + split "^1.0.0" + +pify@^2.0.0, pify@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + +pkg-dir@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" + integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= + dependencies: + find-up "^2.1.0" + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +postgres-array@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" + integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== + +postgres-bytea@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU= + +postgres-date@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.4.tgz#1c2728d62ef1bff49abdd35c1f86d4bdf118a728" + integrity sha512-bESRvKVuTrjoBluEcpv2346+6kgB7UlnqWZsnbnCccTNq/pqfj1j6oBaN5+b/NrDXepYUT/HKadqv3iS9lJuVA== + +postgres-interval@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" + integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== + dependencies: + xtend "^4.0.0" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= + +promise-retry@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/promise-retry/-/promise-retry-1.1.1.tgz#6739e968e3051da20ce6497fb2b50f6911df3d6d" + integrity sha1-ZznpaOMFHaIM5kl/srUPaRHfPW0= + dependencies: + err-code "^1.0.0" + retry "^0.10.0" + +promzard@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/promzard/-/promzard-0.3.0.tgz#26a5d6ee8c7dee4cb12208305acfb93ba382a9ee" + integrity sha1-JqXW7ox97kyxIggwWs+5O6OCqe4= + dependencies: + read "1" + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= + +protocols@^1.1.0, protocols@^1.4.0: + version "1.4.7" + resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.7.tgz#95f788a4f0e979b291ffefcf5636ad113d037d32" + integrity sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg== + +protoduck@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/protoduck/-/protoduck-5.0.1.tgz#03c3659ca18007b69a50fd82a7ebcc516261151f" + integrity sha512-WxoCeDCoCBY55BMvj4cAEjdVUFGRWed9ZxPlqTKYyw1nDDTQ4pqmnIMAGfJlg7Dx35uB/M+PHJPTmGOvaCaPTg== + dependencies: + genfun "^5.0.0" + +psl@^1.1.24: + version "1.4.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" + integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +q@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +quick-lru@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" + integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= + +read-cmd-shim@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz#87e43eba50098ba5a32d0ceb583ab8e43b961c16" + integrity sha512-v5yCqQ/7okKoZZkBQUAfTsQ3sVJtXdNfbPnI5cceppoxEVLYA3k+VtV2omkeo8MS94JCy4fSiUwlRBAwCVRPUA== + dependencies: + graceful-fs "^4.1.2" + +"read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@^2.0.13: + version "2.1.0" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.0.tgz#e3d42e6c35ea5ae820d9a03ab0c7291217fc51d5" + integrity sha512-KLhu8M1ZZNkMcrq1+0UJbR8Dii8KZUqB0Sha4mOx/bknfKI/fyrQVrG/YIt2UOtG667sD8+ee4EXMM91W9dC+A== + dependencies: + glob "^7.1.1" + json-parse-better-errors "^1.0.1" + normalize-package-data "^2.0.0" + slash "^1.0.0" + optionalDependencies: + graceful-fs "^4.1.2" + +read-package-tree@^5.1.6: + version "5.3.1" + resolved "https://registry.yarnpkg.com/read-package-tree/-/read-package-tree-5.3.1.tgz#a32cb64c7f31eb8a6f31ef06f9cedf74068fe636" + integrity sha512-mLUDsD5JVtlZxjSlPPx1RETkNjjvQYuweKwNVt1Sn8kP5Jh44pvYuUHCp6xSVDZWbNxVxG5lyZJ921aJH61sTw== + dependencies: + read-package-json "^2.0.0" + readdir-scoped-modules "^1.0.0" + util-promisify "^2.1.0" + +read-pkg-up@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" + integrity sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI= + dependencies: + find-up "^1.0.0" + read-pkg "^1.0.0" + +read-pkg-up@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" + integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= + dependencies: + find-up "^2.0.0" + read-pkg "^2.0.0" + +read-pkg-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" + integrity sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc= + dependencies: + find-up "^2.0.0" + read-pkg "^3.0.0" + +read-pkg@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" + integrity sha1-9f+qXs0pyzHAR0vKfXVra7KePyg= + dependencies: + load-json-file "^1.0.0" + normalize-package-data "^2.3.2" + path-type "^1.0.0" + +read-pkg@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" + integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= + dependencies: + load-json-file "^2.0.0" + normalize-package-data "^2.3.2" + path-type "^2.0.0" + +read-pkg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" + integrity sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k= + dependencies: + load-json-file "^4.0.0" + normalize-package-data "^2.3.2" + path-type "^3.0.0" + +read@1, read@~1.0.1: + version "1.0.7" + resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" + integrity sha1-s9oZvQUkMal2cdRKQmNK33ELQMQ= + dependencies: + mute-stream "~0.0.4" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +"readable-stream@2 || 3", readable-stream@^3.0.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" + integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdir-scoped-modules@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.1.0.tgz#8d45407b4f870a0dcaebc0e28670d18e74514309" + integrity sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw== + dependencies: + debuglog "^1.0.1" + dezalgo "^1.0.0" + graceful-fs "^4.1.2" + once "^1.3.0" + +redent@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" + integrity sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94= + dependencies: + indent-string "^2.1.0" + strip-indent "^1.0.1" + +redent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa" + integrity sha1-wbIAe0LVfrE4kHmzyDM2OdXhzKo= + dependencies: + indent-string "^3.0.0" + strip-indent "^2.0.0" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +repeating@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" + integrity sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo= + dependencies: + is-finite "^1.0.0" + +request@^2.87.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.0" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.4.3" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= + dependencies: + resolve-from "^3.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.0, resolve@^1.5.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16" + integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w== + dependencies: + path-parse "^1.0.6" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +restore-cursor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" + integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== + dependencies: + onetime "^5.1.0" + signal-exit "^3.0.2" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +retry@^0.10.0: + version "0.10.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" + integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q= + +rimraf@2, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= + dependencies: + is-promise "^2.1.0" + +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= + dependencies: + aproba "^1.1.1" + +rxjs@^6.4.0: + version "6.5.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" + integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== + dependencies: + tslib "^1.9.0" + +safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" + integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= + +semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.2.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@~5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +shallow-clone@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" + integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== + dependencies: + kind-of "^6.0.2" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= + +slash@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" + integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== + +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + +slide@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" + integrity sha1-VusCfWW00tzmyy4tMsTUr8nh1wc= + +smart-buffer@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba" + integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw== + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +socks-proxy-agent@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-4.0.2.tgz#3c8991f3145b2799e70e11bd5fbc8b1963116386" + integrity sha512-NT6syHhI9LmuEMSK6Kd2V7gNv5KFZoLE7V5udWmn0de+3Mkj3UMA/AJPLyeNUVmElCurSHtUdM3ETpR3z770Wg== + dependencies: + agent-base "~4.2.1" + socks "~2.3.2" + +socks@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/socks/-/socks-2.3.3.tgz#01129f0a5d534d2b897712ed8aceab7ee65d78e3" + integrity sha512-o5t52PCNtVdiOvzMry7wU4aOqYWL0PeCXRWBEiJow4/i/wr+wpsJQ9awEu1EonLIqsfGd5qSgDdxEOvCdmBEpA== + dependencies: + ip "1.1.5" + smart-buffer "^4.1.0" + +sort-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" + integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg= + dependencies: + is-plain-obj "^1.0.0" + +source-map-resolve@^0.5.0: + version "0.5.2" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + dependencies: + atob "^2.1.1" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.1, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +spdx-correct@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" + integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + dependencies: + spdx-expression-parse "^3.0.0" + spdx-license-ids "^3.0.0" + +spdx-exceptions@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" + integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + +spdx-expression-parse@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" + integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + dependencies: + spdx-exceptions "^2.1.0" + spdx-license-ids "^3.0.0" + +spdx-license-ids@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" + integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +split2@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-2.2.0.tgz#186b2575bcf83e85b7d18465756238ee4ee42493" + integrity sha512-RAb22TG39LhI31MbreBgIuKiIKhVsawfTgEGqKHTK87aG+ul/PB8Sqoi3I7kVdRWiCfrKxK3uo4/YUkpNvhPbw== + dependencies: + through2 "^2.0.2" + +split@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" + integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== + dependencies: + through "2" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +ssri@^6.0.0, ssri@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" + integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== + dependencies: + figgy-pudding "^3.5.1" + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +stream-each@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + +stream-shift@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" + integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +string-width@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string.prototype.trimleft@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" + integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" + integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-bom@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" + integrity sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4= + dependencies: + is-utf8 "^0.2.0" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM= + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-indent@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= + dependencies: + get-stdin "^4.0.1" + +strip-indent@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" + integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= + +strip-json-comments@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" + integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== + +strong-log-transformer@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10" + integrity sha512-B3Hgul+z0L9a236FAUC9iZsL+nVHgoCJnqCbN588DjYxvGXaXaaFbfmQ/JhvKjZwsOukuR72XbHv71Qkug0HxA== + dependencies: + duplexer "^0.1.1" + minimist "^1.2.0" + through "^2.3.4" + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== + dependencies: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + +tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: + version "4.4.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" + integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.8.6" + minizlib "^1.2.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.3" + +temp-dir@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" + integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0= + +temp-write@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/temp-write/-/temp-write-3.4.0.tgz#8cff630fb7e9da05f047c74ce4ce4d685457d492" + integrity sha1-jP9jD7fp2gXwR8dM5M5NaFRX1JI= + dependencies: + graceful-fs "^4.1.2" + is-stream "^1.1.0" + make-dir "^1.0.0" + pify "^3.0.0" + temp-dir "^1.0.0" + uuid "^3.0.1" + +text-extensions@^1.0.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" + integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +thenify-all@^1.0.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + integrity sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.0" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" + integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= + dependencies: + any-promise "^1.0.0" + +through2@^2.0.0, through2@^2.0.2: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through2@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" + integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== + dependencies: + readable-stream "2 || 3" + +through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +tough-cookie@~2.4.3: + version "2.4.3" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" + integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== + dependencies: + psl "^1.1.24" + punycode "^1.4.1" + +tr46@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" + integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= + dependencies: + punycode "^2.1.0" + +trim-newlines@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" + integrity sha1-WIeWa7WCpFA6QetST301ARgVphM= + +trim-newlines@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" + integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA= + +trim-off-newlines@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" + integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM= + +tslib@^1.9.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type-fest@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" + integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +uglify-js@^3.1.4: + version "3.7.0" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.0.tgz#14b854003386b7a7c045910f43afbc96d2aa5307" + integrity sha512-PC/ee458NEMITe1OufAjal65i6lB58R1HWMRcxwvdz1UopW0DYqlRL3xdu3IcTvTXsB02CRHykidkTRL+A3hQA== + dependencies: + commander "~2.20.3" + source-map "~0.6.1" + +uid-number@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" + integrity sha1-DqEOgDXo61uOREnwbaHHMGY7qoE= + +umask@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" + integrity sha1-8pzr8B31F5ErtY/5xOUP3o4zMg0= + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== + dependencies: + imurmurhash "^0.1.4" + +universal-user-agent@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.0.tgz#27da2ec87e32769619f68a14996465ea1cb9df16" + integrity sha512-eM8knLpev67iBDizr/YtqkJsF3GK8gzDc6st/WKzrTuPtcsOKW/0IdL4cnMBsU69pOx0otavLWBDGTwg+dB0aA== + dependencies: + os-name "^3.1.0" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util-promisify@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/util-promisify/-/util-promisify-2.1.0.tgz#3c2236476c4d32c5ff3c47002add7c13b9a82a53" + integrity sha1-PCI2R2xNMsX/PEcAKt18E7moKlM= + dependencies: + object.getownpropertydescriptors "^2.0.3" + +uuid@^3.0.1, uuid@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" + integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== + +v8-compile-cache@^2.0.3: + version "2.1.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" + integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== + +validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.3: + version "3.0.4" + resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" + integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew== + dependencies: + spdx-correct "^3.0.0" + spdx-expression-parse "^3.0.0" + +validate-npm-package-name@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/validate-npm-package-name/-/validate-npm-package-name-3.0.0.tgz#5fa912d81eb7d0c74afc140de7317f0ca7df437e" + integrity sha1-X6kS2B630MdK/BQN5zF/DKffQ34= + dependencies: + builtins "^1.0.3" + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +wcwidth@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" + integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= + dependencies: + defaults "^1.0.3" + +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== + +whatwg-url@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" + integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@1, which@^1.2.9, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +windows-release@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.2.0.tgz#8122dad5afc303d833422380680a79cdfa91785f" + integrity sha512-QTlz2hKLrdqukrsapKsINzqMgOUpQW268eJ0OaOpJN32h272waxR9fkB9VoWRtK7uKHG5EHJcTXQBD8XZVJkFA== + dependencies: + execa "^1.0.0" + +word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wordwrap@~0.0.2: + version "0.0.3" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" + integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write-file-atomic@^2.0.0, write-file-atomic@^2.3.0, write-file-atomic@^2.4.2: + version "2.4.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481" + integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ== + dependencies: + graceful-fs "^4.1.11" + imurmurhash "^0.1.4" + signal-exit "^3.0.2" + +write-json-file@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-2.3.0.tgz#2b64c8a33004d54b8698c76d585a77ceb61da32f" + integrity sha1-K2TIozAE1UuGmMdtWFp3zrYdoy8= + dependencies: + detect-indent "^5.0.0" + graceful-fs "^4.1.2" + make-dir "^1.0.0" + pify "^3.0.0" + sort-keys "^2.0.0" + write-file-atomic "^2.0.0" + +write-json-file@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/write-json-file/-/write-json-file-3.2.0.tgz#65bbdc9ecd8a1458e15952770ccbadfcff5fe62a" + integrity sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ== + dependencies: + detect-indent "^5.0.0" + graceful-fs "^4.1.15" + make-dir "^2.1.0" + pify "^4.0.1" + sort-keys "^2.0.0" + write-file-atomic "^2.4.2" + +write-pkg@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/write-pkg/-/write-pkg-3.2.0.tgz#0e178fe97820d389a8928bc79535dbe68c2cff21" + integrity sha512-tX2ifZ0YqEFOF1wjRW2Pk93NLsj02+n1UP5RvO6rCs0K6R2g1padvf006cY74PQJKMGS2r42NK7FD0dG6Y6paw== + dependencies: + sort-keys "^2.0.0" + write-json-file "^2.2.0" + +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + +xtend@^4.0.0, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yargs-parser@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" + integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== + dependencies: + camelcase "^4.1.0" + +yargs-parser@^15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.0.tgz#cdd7a97490ec836195f59f3f4dbe5ea9e8f75f08" + integrity sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@^14.2.2: + version "14.2.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.2.tgz#2769564379009ff8597cdd38fba09da9b493c4b5" + integrity sha512-/4ld+4VV5RnrynMhPZJ/ZpOCGSCeghMykZ3BhdFBDa9Wy/RH6uEGNWDJog+aUlq+9OM1CFTgtYRW5Is1Po9NOA== + dependencies: + cliui "^5.0.0" + decamelize "^1.2.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^15.0.0" From 7feaafd771a366634b0a6a8198b183304ecfb4e4 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 17 Dec 2019 10:34:09 -0600 Subject: [PATCH 0529/1037] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59a692b7c..3d933854f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.15.0 + +- Change repository structure to support lerna & future monorepo [development](https://github.com/brianc/node-postgres/pull/2014). +- [Warn about deprecation](https://github.com/brianc/node-postgres/pull/2021) for calling constructors without `new`. + ### 7.14.0 - Reverts 7.13.0 as it contained [an accidental breaking change](https://github.com/brianc/node-postgres/pull/2010) for self-signed SSL cert verification. 7.14.0 is identical to 7.12.1. From ebb81dbfa635eca73d16d54b501f04c8d843bac5 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 17 Dec 2019 10:35:38 -0600 Subject: [PATCH 0530/1037] Publish - pg@7.15.0 --- packages/pg/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg/package.json b/packages/pg/package.json index 5d0653724..bd1b3432e 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.14.0", + "version": "7.15.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 236db3813d1602ed32a36b016326550bc3007c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20W=C3=BCrbach?= Date: Wed, 18 Dec 2019 17:08:30 +0100 Subject: [PATCH 0531/1037] Handle client errors in pool.query (#131) If an error not related to the query occurs, the client is emitting an error event. Forward this event to the callback. --- index.js | 18 ++++++++++++++++++ test/error-handling.js | 15 +++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/index.js b/index.js index e517f76f3..1c7faf210 100644 --- a/index.js +++ b/index.js @@ -316,13 +316,31 @@ class Pool extends EventEmitter { } const response = promisify(this.Promise, cb) cb = response.callback + this.connect((err, client) => { if (err) { return cb(err) } + + let clientReleased = false + const onError = (err) => { + if (clientReleased) { + return + } + clientReleased = true + client.release(err) + cb(err) + } + + client.once('error', onError) this.log('dispatching query') client.query(text, values, (err, res) => { this.log('query dispatched') + client.removeListener('error', onError) + if (clientReleased) { + return + } + clientReleased = true client.release(err) if (err) { return cb(err) diff --git a/test/error-handling.js b/test/error-handling.js index 1e4166838..9ef8848ed 100644 --- a/test/error-handling.js +++ b/test/error-handling.js @@ -226,4 +226,19 @@ describe('pool error handling', function () { }) }) }) + + it('handles post-checkout client failures in pool.query', (done) => { + const pool = new Pool({ max: 1 }) + pool.on('error', () => { + // We double close the connection in this test, prevent exception caused by that + }) + pool.query('SELECT pg_sleep(5)', [], (err) => { + expect(err).to.be.an(Error) + done() + }) + + setTimeout(() => { + pool._clients[0].end() + }, 1000) + }) }) From 8f819a0e8d11522e96246635a9da4371b8b87ce8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Dec 2019 10:08:42 -0600 Subject: [PATCH 0532/1037] Bump js-yaml from 3.12.0 to 3.13.1 (#137) Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 3.12.0 to 3.13.1. - [Release notes](https://github.com/nodeca/js-yaml/releases) - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/3.12.0...3.13.1) Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 08410f56b..c1251e748 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1125,9 +1125,9 @@ "dev": true }, "js-yaml": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", - "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", + "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", "dev": true, "requires": { "argparse": "^1.0.7", From 423baa644affeff21984ef41def480829d170f01 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 18 Dec 2019 13:42:47 -0600 Subject: [PATCH 0533/1037] Update lint rules for pg-cursor --- .eslintrc | 20 +- package.json | 3 +- packages/pg-cursor/.eslintrc | 17 -- packages/pg-cursor/index.js | 46 ++-- packages/pg-cursor/package.json | 5 +- packages/pg-cursor/test/close.js | 18 +- packages/pg-cursor/test/error-handling.js | 12 +- packages/pg-cursor/test/index.js | 35 +-- packages/pg-cursor/test/no-data-handling.js | 4 +- packages/pg-cursor/test/pool.js | 24 +- packages/pg-cursor/test/query-config.js | 6 +- packages/pg-cursor/test/transactions.js | 2 +- packages/pg/package.json | 3 +- yarn.lock | 278 ++++++++++++++++++-- 14 files changed, 348 insertions(+), 125 deletions(-) delete mode 100644 packages/pg-cursor/.eslintrc diff --git a/.eslintrc b/.eslintrc index 43aee6027..6242db30c 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,19 +1,21 @@ { - "plugins": [ - "node" - ], - "extends": [ - "standard", - "eslint:recommended", - "plugin:node/recommended" - ], + "plugins": ["node"], + "extends": ["standard", "eslint:recommended", "plugin:node/recommended"], "parserOptions": { "ecmaVersion": 2017 }, "env": { "node": true, - "es6": true + "es6": true, + "mocha": true }, "rules": { + "space-before-function-paren": "off", + "node/no-unpublished-require": [ + "error", + { + "allowModules": ["pg"] + } + ] } } diff --git a/package.json b/package.json index 5dd581b2e..8386726e9 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,8 @@ "packages/*" ], "scripts": { - "test": "yarn lerna exec --parallel yarn test" + "test": "yarn lerna exec --parallel yarn test", + "lint": "yarn lerna exec --parallel yarn lint" }, "devDependencies": { "lerna": "^3.19.0" diff --git a/packages/pg-cursor/.eslintrc b/packages/pg-cursor/.eslintrc deleted file mode 100644 index aa7df694d..000000000 --- a/packages/pg-cursor/.eslintrc +++ /dev/null @@ -1,17 +0,0 @@ -{ - "extends": ["eslint:recommended"], - "parserOptions": { - "ecmaVersion": 2017 - }, - "plugins": ["prettier"], - "rules": { - "prettier/prettier": "error", - "prefer-const": "error", - "no-var": "error" - }, - "env": { - "es6": true, - "node": true, - "mocha": true - } -} diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index 3fa9c9a53..405a67129 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -6,7 +6,7 @@ const util = require('util') let nextUniqueID = 1 // concept borrowed from org.postgresql.core.v3.QueryExecutorImpl -function Cursor(text, values, config) { +function Cursor (text, values, config) { EventEmitter.call(this) this._conf = config || {} @@ -25,18 +25,18 @@ function Cursor(text, values, config) { util.inherits(Cursor, EventEmitter) -Cursor.prototype._ifNoData = function() { +Cursor.prototype._ifNoData = function () { this.state = 'idle' this._shiftQueue() } -Cursor.prototype._rowDescription = function() { +Cursor.prototype._rowDescription = function () { if (this.connection) { this.connection.removeListener('noData', this._ifNoData) } } -Cursor.prototype.submit = function(connection) { +Cursor.prototype.submit = function (connection) { this.connection = connection this._portal = 'C_' + nextUniqueID++ @@ -44,7 +44,7 @@ Cursor.prototype.submit = function(connection) { con.parse( { - text: this.text, + text: this.text }, true ) @@ -52,7 +52,7 @@ Cursor.prototype.submit = function(connection) { con.bind( { portal: this._portal, - values: this.values, + values: this.values }, true ) @@ -60,7 +60,7 @@ Cursor.prototype.submit = function(connection) { con.describe( { type: 'P', - name: this._portal, // AWS Redshift requires a portal name + name: this._portal // AWS Redshift requires a portal name }, true ) @@ -75,13 +75,13 @@ Cursor.prototype.submit = function(connection) { con.once('rowDescription', this._rowDescription) } -Cursor.prototype._shiftQueue = function() { +Cursor.prototype._shiftQueue = function () { if (this._queue.length) { this._getRows.apply(this, this._queue.shift()) } } -Cursor.prototype._closePortal = function() { +Cursor.prototype._closePortal = function () { // because we opened a named portal to stream results // we need to close the same named portal. Leaving a named portal // open can lock tables for modification if inside a transaction. @@ -90,19 +90,19 @@ Cursor.prototype._closePortal = function() { this.connection.sync() } -Cursor.prototype.handleRowDescription = function(msg) { +Cursor.prototype.handleRowDescription = function (msg) { this._result.addFields(msg.fields) this.state = 'idle' this._shiftQueue() } -Cursor.prototype.handleDataRow = function(msg) { +Cursor.prototype.handleDataRow = function (msg) { const row = this._result.parseRow(msg.fields) this.emit('row', row, this._result) this._rows.push(row) } -Cursor.prototype._sendRows = function() { +Cursor.prototype._sendRows = function () { this.state = 'idle' setImmediate(() => { const cb = this._cb @@ -118,26 +118,26 @@ Cursor.prototype._sendRows = function() { }) } -Cursor.prototype.handleCommandComplete = function(msg) { +Cursor.prototype.handleCommandComplete = function (msg) { this._result.addCommandComplete(msg) this._closePortal() } -Cursor.prototype.handlePortalSuspended = function() { +Cursor.prototype.handlePortalSuspended = function () { this._sendRows() } -Cursor.prototype.handleReadyForQuery = function() { +Cursor.prototype.handleReadyForQuery = function () { this._sendRows() this.state = 'done' this.emit('end', this._result) } -Cursor.prototype.handleEmptyQuery = function() { +Cursor.prototype.handleEmptyQuery = function () { this.connection.sync() } -Cursor.prototype.handleError = function(msg) { +Cursor.prototype.handleError = function (msg) { this.connection.removeListener('noData', this._ifNoData) this.connection.removeListener('rowDescription', this._rowDescription) this.state = 'error' @@ -159,13 +159,13 @@ Cursor.prototype.handleError = function(msg) { this.connection.sync() } -Cursor.prototype._getRows = function(rows, cb) { +Cursor.prototype._getRows = function (rows, cb) { this.state = 'busy' this._cb = cb this._rows = [] const msg = { portal: this._portal, - rows: rows, + rows: rows } this.connection.execute(msg, true) this.connection.flush() @@ -173,7 +173,7 @@ Cursor.prototype._getRows = function(rows, cb) { // users really shouldn't be calling 'end' here and terminating a connection to postgres // via the low level connection.end api -Cursor.prototype.end = util.deprecate(function(cb) { +Cursor.prototype.end = util.deprecate(function (cb) { if (this.state !== 'initialized') { this.connection.sync() } @@ -181,7 +181,7 @@ Cursor.prototype.end = util.deprecate(function(cb) { this.connection.end() }, 'Cursor.end is deprecated. Call end on the client itself to end a connection to the database.') -Cursor.prototype.close = function(cb) { +Cursor.prototype.close = function (cb) { if (this.state === 'done') { if (cb) { return setImmediate(cb) @@ -192,13 +192,13 @@ Cursor.prototype.close = function(cb) { this._closePortal() this.state = 'done' if (cb) { - this.connection.once('closeComplete', function() { + this.connection.once('closeComplete', function () { cb() }) } } -Cursor.prototype.read = function(rows, cb) { +Cursor.prototype.read = function (rows, cb) { if (this.state === 'idle') { return this._getRows(rows, cb) } diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 14b34ee9c..60213bb5c 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -7,7 +7,8 @@ "test": "test" }, "scripts": { - "test": " mocha && eslint ." + "test": "mocha && eslint .", + "lint": "eslint ." }, "repository": { "type": "git", @@ -26,7 +27,7 @@ "prettier": { "semi": false, "printWidth": 120, - "trailingComma": "es5", + "trailingComma": "none", "singleQuote": true } } diff --git a/packages/pg-cursor/test/close.js b/packages/pg-cursor/test/close.js index 23fb7f9de..5497c51b2 100644 --- a/packages/pg-cursor/test/close.js +++ b/packages/pg-cursor/test/close.js @@ -3,40 +3,40 @@ const Cursor = require('../') const pg = require('pg') const text = 'SELECT generate_series as num FROM generate_series(0, 50)' -describe('close', function() { - beforeEach(function(done) { +describe('close', function () { + beforeEach(function (done) { const client = (this.client = new pg.Client()) client.connect(done) client.on('drain', client.end.bind(client)) }) - it('can close a finished cursor without a callback', function(done) { + it('can close a finished cursor without a callback', function (done) { const cursor = new Cursor(text) this.client.query(cursor) this.client.query('SELECT NOW()', done) - cursor.read(100, function(err) { + cursor.read(100, function (err) { assert.ifError(err) cursor.close() }) }) - it('closes cursor early', function(done) { + it('closes cursor early', function (done) { const cursor = new Cursor(text) this.client.query(cursor) this.client.query('SELECT NOW()', done) - cursor.read(25, function(err) { + cursor.read(25, function (err) { assert.ifError(err) cursor.close() }) }) - it('works with callback style', function(done) { + it('works with callback style', function (done) { const cursor = new Cursor(text) const client = this.client client.query(cursor) - cursor.read(25, function(err) { + cursor.read(25, function (err) { assert.ifError(err) - cursor.close(function(err) { + cursor.close(function (err) { assert.ifError(err) client.query('SELECT NOW()', done) }) diff --git a/packages/pg-cursor/test/error-handling.js b/packages/pg-cursor/test/error-handling.js index e559d9090..43d34581f 100644 --- a/packages/pg-cursor/test/error-handling.js +++ b/packages/pg-cursor/test/error-handling.js @@ -29,11 +29,11 @@ describe('read callback does not fire sync', () => { let after = false cursor.read(1, function(err) { assert(err, 'error should be returned') - assert.equal(after, true, 'should not call read sync') + assert.strictEqual(after, true, 'should not call read sync') after = false cursor.read(1, function(err) { assert(err, 'error should be returned') - assert.equal(after, true, 'should not call read sync') + assert.strictEqual(after, true, 'should not call read sync') client.end() done() }) @@ -49,13 +49,13 @@ describe('read callback does not fire sync', () => { let after = false cursor.read(1, function(err) { assert(!err) - assert.equal(after, true, 'should not call read sync') + assert.strictEqual(after, true, 'should not call read sync') cursor.read(1, function(err) { assert(!err) after = false cursor.read(1, function(err) { assert(!err) - assert.equal(after, true, 'should not call read sync') + assert.strictEqual(after, true, 'should not call read sync') client.end() done() }) @@ -73,11 +73,11 @@ describe('proper cleanup', function() { const cursor1 = client.query(new Cursor(text)) cursor1.read(8, function(err, rows) { assert.ifError(err) - assert.equal(rows.length, 5) + assert.strictEqual(rows.length, 5) const cursor2 = client.query(new Cursor(text)) cursor2.read(8, function(err, rows) { assert.ifError(err) - assert.equal(rows.length, 5) + assert.strictEqual(rows.length, 5) client.end() done() }) diff --git a/packages/pg-cursor/test/index.js b/packages/pg-cursor/test/index.js index 0f41f882a..fe210096e 100644 --- a/packages/pg-cursor/test/index.js +++ b/packages/pg-cursor/test/index.js @@ -22,7 +22,7 @@ describe('cursor', function() { const cursor = this.pgCursor(text) cursor.read(10, function(err, res) { assert.ifError(err) - assert.equal(res.length, 6) + assert.strictEqual(res.length, 6) done() }) }) @@ -31,7 +31,7 @@ describe('cursor', function() { const cursor = this.pgCursor(text) cursor.read(3, function(err, res) { assert.ifError(err) - assert.equal(res.length, 3) + assert.strictEqual(res.length, 3) done() }) }) @@ -48,13 +48,13 @@ describe('cursor', function() { const cursor = this.pgCursor(text) cursor.read(2, function(err, res) { assert.ifError(err) - assert.equal(res.length, 2) + assert.strictEqual(res.length, 2) cursor.read(3, function(err, res) { assert(!err) - assert.equal(res.length, 3) + assert.strictEqual(res.length, 3) cursor.read(1, function(err, res) { assert(!err) - assert.equal(res.length, 1) + assert.strictEqual(res.length, 1) cursor.read(1, function(err, res) { assert(!err) assert.ifError(err) @@ -72,10 +72,10 @@ describe('cursor', function() { assert(!err) cursor.read(100, function(err, res) { assert(!err) - assert.equal(res.length, 4) + assert.strictEqual(res.length, 4) cursor.read(100, function(err, res) { assert(!err) - assert.equal(res.length, 0) + assert.strictEqual(res.length, 0) done() }) }) @@ -92,7 +92,7 @@ describe('cursor', function() { cursor.read(100, function(err, rows) { if (err) return done(err) if (!rows.length) { - assert.equal(count, 100001) + assert.strictEqual(count, 100001) return done() } count += rows.length @@ -111,10 +111,10 @@ describe('cursor', function() { const cursor = this.pgCursor(text, values) cursor.read(1, function(err, rows) { if (err) return done(err) - assert.equal(rows[0].me.name, 'brian') + assert.strictEqual(rows[0].me.name, 'brian') cursor.read(1, function(err, rows) { assert(!err) - assert.equal(rows.length, 0) + assert.strictEqual(rows.length, 0) done() }) }) @@ -124,9 +124,12 @@ describe('cursor', function() { const cursor = this.pgCursor(text) cursor.read(1, function(err, rows, result) { assert.ifError(err) - assert.equal(rows.length, 1) + assert.strictEqual(rows.length, 1) assert.strictEqual(rows, result.rows) - assert.deepEqual(result.fields.map(f => f.name), ['num']) + assert.deepStrictEqual( + result.fields.map(f => f.name), + ['num'] + ) done() }) }) @@ -136,7 +139,7 @@ describe('cursor', function() { cursor.read(10) cursor.on('row', (row, result) => result.addRow(row)) cursor.on('end', result => { - assert.equal(result.rows.length, 6) + assert.strictEqual(result.rows.length, 6) done() }) }) @@ -145,7 +148,7 @@ describe('cursor', function() { const cursor = this.pgCursor(text) cursor.on('row', (row, result) => result.addRow(row)) cursor.on('end', result => { - assert.equal(result.rows.length, 3) + assert.strictEqual(result.rows.length, 3) done() }) @@ -168,8 +171,8 @@ describe('cursor', function() { const cursor = pgCursor('insert into pg_cursor_test values($1, $2)', ['a', 'b']) cursor.read(1, function(err, rows, result) { assert.ifError(err) - assert.equal(rows.length, 0) - assert.equal(result.rowCount, 1) + assert.strictEqual(rows.length, 0) + assert.strictEqual(result.rowCount, 1) done() }) }) diff --git a/packages/pg-cursor/test/no-data-handling.js b/packages/pg-cursor/test/no-data-handling.js index ab2ed3f6a..755658746 100644 --- a/packages/pg-cursor/test/no-data-handling.js +++ b/packages/pg-cursor/test/no-data-handling.js @@ -17,7 +17,7 @@ describe('queries with no data', function() { this.client.query(cursor) cursor.read(100, function(err, rows) { assert.ifError(err) - assert.equal(rows.length, 0) + assert.strictEqual(rows.length, 0) done() }) }) @@ -27,7 +27,7 @@ describe('queries with no data', function() { cursor = this.client.query(cursor) cursor.read(100, function(err, rows) { assert.ifError(err) - assert.equal(rows.length, 0) + assert.strictEqual(rows.length, 0) done() }) }) diff --git a/packages/pg-cursor/test/pool.js b/packages/pg-cursor/test/pool.js index 61f5e2795..9af79276c 100644 --- a/packages/pg-cursor/test/pool.js +++ b/packages/pg-cursor/test/pool.js @@ -5,7 +5,7 @@ const pg = require('pg') const text = 'SELECT generate_series as num FROM generate_series(0, 50)' -function poolQueryPromise(pool, readRowCount) { +function poolQueryPromise (pool, readRowCount) { return new Promise((resolve, reject) => { pool.connect((err, client, done) => { if (err) { @@ -31,16 +31,16 @@ function poolQueryPromise(pool, readRowCount) { }) } -describe('pool', function() { - beforeEach(function() { +describe('pool', function () { + beforeEach(function () { this.pool = new pg.Pool({ max: 1 }) }) - afterEach(function() { + afterEach(function () { this.pool.end() }) - it('closes cursor early, single pool query', function(done) { + it('closes cursor early, single pool query', function (done) { poolQueryPromise(this.pool, 25) .then(() => done()) .catch(err => { @@ -49,7 +49,7 @@ describe('pool', function() { }) }) - it('closes cursor early, saturated pool', function(done) { + it('closes cursor early, saturated pool', function (done) { const promises = [] for (let i = 0; i < 10; i++) { promises.push(poolQueryPromise(this.pool, 25)) @@ -62,7 +62,7 @@ describe('pool', function() { }) }) - it('closes exhausted cursor, single pool query', function(done) { + it('closes exhausted cursor, single pool query', function (done) { poolQueryPromise(this.pool, 100) .then(() => done()) .catch(err => { @@ -71,7 +71,7 @@ describe('pool', function() { }) }) - it('closes exhausted cursor, saturated pool', function(done) { + it('closes exhausted cursor, saturated pool', function (done) { const promises = [] for (let i = 0; i < 10; i++) { promises.push(poolQueryPromise(this.pool, 100)) @@ -84,16 +84,16 @@ describe('pool', function() { }) }) - it('can close multiple times on a pool', async function() { + it('can close multiple times on a pool', async function () { const pool = new pg.Pool({ max: 1 }) const run = async () => { const cursor = new Cursor(text) const client = await pool.connect() client.query(cursor) - new Promise(resolve => { - cursor.read(25, function(err) { + await new Promise(resolve => { + cursor.read(25, function (err) { assert.ifError(err) - cursor.close(function(err) { + cursor.close(function (err) { assert.ifError(err) client.release() resolve() diff --git a/packages/pg-cursor/test/query-config.js b/packages/pg-cursor/test/query-config.js index 53b612c8b..42692b90b 100644 --- a/packages/pg-cursor/test/query-config.js +++ b/packages/pg-cursor/test/query-config.js @@ -11,7 +11,7 @@ describe('query config passed to result', () => { const cursor = client.query(new Cursor(text, null, { rowMode: 'array' })) cursor.read(10, (err, rows) => { assert(!err) - assert.deepEqual(rows, [[0], [1], [2], [3], [4], [5]]) + assert.deepStrictEqual(rows, [[0], [1], [2], [3], [4], [5]]) client.end() done() }) @@ -22,12 +22,12 @@ describe('query config passed to result', () => { client.connect() const text = 'SELECT generate_series as num FROM generate_series(0, 2)' const types = { - getTypeParser: () => () => 'foo', + getTypeParser: () => () => 'foo' } const cursor = client.query(new Cursor(text, null, { types })) cursor.read(10, (err, rows) => { assert(!err) - assert.deepEqual(rows, [{ num: 'foo' }, { num: 'foo' }, { num: 'foo' }]) + assert.deepStrictEqual(rows, [{ num: 'foo' }, { num: 'foo' }, { num: 'foo' }]) client.end() done() }) diff --git a/packages/pg-cursor/test/transactions.js b/packages/pg-cursor/test/transactions.js index f83cc1d77..a0ee5e6f9 100644 --- a/packages/pg-cursor/test/transactions.js +++ b/packages/pg-cursor/test/transactions.js @@ -12,7 +12,7 @@ describe('transactions', () => { const rows = await new Promise((resolve, reject) => { cursor.read(10, (err, rows) => (err ? reject(err) : resolve(rows))) }) - assert.equal(rows.length, 0) + assert.strictEqual(rows.length, 0) await client.query('ALTER TABLE foobar ADD COLUMN name TEXT') await client.end() }) diff --git a/packages/pg/package.json b/packages/pg/package.json index bd1b3432e..651d91c46 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -41,7 +41,8 @@ }, "minNativeVersion": "2.0.0", "scripts": { - "test": "make test-all" + "test": "make test-all", + "lint": "make lint" }, "files": [ "lib", diff --git a/yarn.lock b/yarn.lock index 845ed02be..05d5e8f93 100644 --- a/yarn.lock +++ b/yarn.lock @@ -918,6 +918,11 @@ ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ansi-colors@3.2.3: + version "3.2.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha1-V9NbhoboUeLMBMQD8cACA5dqGBM= + ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" @@ -1168,6 +1173,11 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha1-uqVZ7hTO1zRSIputcyZGfGH6vWA= + btoa-lite@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" @@ -1300,7 +1310,7 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1646,6 +1656,13 @@ debug@3.1.0: dependencies: ms "2.0.0" +debug@3.2.6, debug@^3.1.0: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -1653,13 +1670,6 @@ debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: dependencies: ms "2.0.0" -debug@^3.1.0: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - debug@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" @@ -1764,6 +1774,11 @@ dezalgo@^1.0.0: asap "^2.0.0" wrappy "1" +diff@3.5.0: + version "3.5.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI= + dir-glob@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" @@ -1901,11 +1916,18 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" -escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +eslint-config-prettier@^6.4.0: + version "6.7.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-config-prettier/-/eslint-config-prettier-6.7.0.tgz#9a876952e12df2b284adbd3440994bf1f39dfbb9" + integrity sha1-modpUuEt8rKErb00QJlL8fOd+7k= + dependencies: + get-stdin "^6.0.0" + eslint-config-standard@^13.0.1: version "13.0.1" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-13.0.1.tgz#c9c6ffe0cfb8a51535bc5c7ec9f70eafb8c6b2c0" @@ -1964,6 +1986,13 @@ eslint-plugin-node@^9.1.0: resolve "^1.10.1" semver "^6.1.0" +eslint-plugin-prettier@^3.1.1: + version "3.1.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz#432e5a667666ab84ce72f945c72f77d996a5c9ba" + integrity sha1-Qy5aZnZmq4TOcvlFxy932Zalybo= + dependencies: + prettier-linter-helpers "^1.0.0" + eslint-plugin-promise@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" @@ -2037,6 +2066,49 @@ eslint@^6.0.1: text-table "^0.2.0" v8-compile-cache "^2.0.3" +eslint@^6.5.1: + version "6.7.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint/-/eslint-6.7.2.tgz#c17707ca4ad7b2d8af986a33feba71e18a9fecd1" + integrity sha1-wXcHykrXstivmGoz/rpx4Yqf7NE= + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.10.0" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^5.0.0" + eslint-utils "^1.4.3" + eslint-visitor-keys "^1.1.0" + espree "^6.1.2" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^7.0.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.14" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.3" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + espree@^6.1.2: version "6.1.2" resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" @@ -2164,6 +2236,11 @@ fast-deep-equal@^2.0.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-diff@^1.1.2: + version "1.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha1-c+4RmC2Gyq95WYKNUZz+kn+sXwM= + fast-glob@^2.2.6: version "2.2.7" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" @@ -2222,6 +2299,13 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -2237,13 +2321,6 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" -find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -2253,6 +2330,13 @@ flat-cache@^2.0.1: rimraf "2.6.3" write "1.0.3" +flat@^4.1.0: + version "4.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" + integrity sha1-CQvsiwXjnLowl0fx1YjwTbr5jbI= + dependencies: + is-buffer "~2.0.3" + flatted@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" @@ -2386,6 +2470,11 @@ get-stdin@^4.0.1: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha1-ngm/cSs2CrkiXoEgSPcf3pyJZXs= + get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -2474,6 +2563,18 @@ glob-to-regexp@^0.3.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= +glob@7.1.3: + version "7.1.3" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha1-OWCDLT8VdBCDQtr9OmezMsCWnfE= + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.0.3, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" @@ -2512,6 +2613,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== +growl@1.10.5: + version "1.10.5" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha1-8nNdwig2dPpnR4sQGBBZNVw2nl4= + handlebars@^4.4.0: version "4.5.3" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" @@ -2541,7 +2647,7 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= -has-symbols@^1.0.1: +has-symbols@^1.0.0, has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== @@ -2589,6 +2695,11 @@ has@^1.0.1, has@^1.0.3: dependencies: function-bind "^1.1.1" +he@1.2.0: + version "1.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha1-hK5l+n6vsWX922FWauFLrwVmTw8= + hosted-git-info@^2.1.4, hosted-git-info@^2.7.1: version "2.8.5" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" @@ -2805,6 +2916,11 @@ is-buffer@^1.1.5: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== +is-buffer@~2.0.3: + version "2.0.4" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha1-PlcvI8hBGlz9lVfISeNmXgspBiM= + is-callable@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" @@ -3035,7 +3151,7 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@^3.13.1: +js-yaml@3.13.1, js-yaml@^3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -3263,6 +3379,13 @@ lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +log-symbols@2.2.0: + version "2.2.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo= + dependencies: + chalk "^2.0.1" + loud-rejection@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/loud-rejection/-/loud-rejection-1.6.0.tgz#5b46f80147edee578870f086d04821cf998e551f" @@ -3429,7 +3552,7 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -3505,13 +3628,42 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@*, mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" +mocha@^6.2.2: + version "6.2.2" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" + integrity sha1-XYmH4olAyviVen12ZLkQ3Fsv6iA= + dependencies: + ansi-colors "3.2.3" + browser-stdout "1.3.1" + debug "3.2.6" + diff "3.5.0" + escape-string-regexp "1.0.5" + find-up "3.0.0" + glob "7.1.3" + growl "1.10.5" + he "1.2.0" + js-yaml "3.13.1" + log-symbols "2.2.0" + minimatch "3.0.4" + mkdirp "0.5.1" + ms "2.1.1" + node-environment-flags "1.0.5" + object.assign "4.1.0" + strip-json-comments "2.0.1" + supports-color "6.0.0" + which "1.3.1" + wide-align "1.1.3" + yargs "13.3.0" + yargs-parser "13.1.1" + yargs-unparser "1.6.0" + modify-values@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" @@ -3534,6 +3686,11 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= +ms@2.1.1: + version "2.1.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo= + ms@^2.0.0, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -3600,6 +3757,14 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-environment-flags@1.0.5: + version "1.0.5" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha1-+pMCdfW/Xa4YjWGSsktMi7rD12o= + dependencies: + object.getownpropertydescriptors "^2.0.3" + semver "^5.7.0" + node-fetch-npm@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7" @@ -3745,7 +3910,7 @@ object-inspect@^1.7.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== -object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -3757,6 +3922,16 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" +object.assign@4.1.0: + version "4.1.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha1-lovxEA15Vrs8oIbwBvhGs7xACNo= + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + object.getownpropertydescriptors@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" @@ -4168,6 +4343,18 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= +prettier-linter-helpers@^1.0.0: + version "1.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha1-0j1B/hN1ZG3i0BBNNFSjAIgCz3s= + dependencies: + fast-diff "^1.1.2" + +prettier@^1.18.2: + version "1.19.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha1-99f1/4qc2HKnvkyhQglZVqYHl8s= + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -4966,6 +5153,11 @@ strip-indent@^2.0.0: resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= +strip-json-comments@2.0.1: + version "2.0.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + strip-json-comments@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" @@ -4980,6 +5172,13 @@ strong-log-transformer@^2.0.0: minimist "^1.2.0" through "^2.3.4" +supports-color@6.0.0: + version "6.0.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha1-ds/nQs8fQbubHCmtAwaMBbTA5Ao= + dependencies: + has-flag "^3.0.0" + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -5323,14 +5522,14 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1, which@^1.2.9, which@^1.3.1: +which@1, which@1.3.1, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== dependencies: isexe "^2.0.0" -wide-align@^1.1.0: +wide-align@1.1.3, wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== @@ -5431,6 +5630,14 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== +yargs-parser@13.1.1, yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha1-0mBYUyqgbTZf4JH2ofwGsvfl7KA= + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^10.0.0: version "10.1.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" @@ -5446,6 +5653,31 @@ yargs-parser@^15.0.0: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-unparser@1.6.0: + version "1.6.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha1-7yXCx2n/a9CeSw+dfGBfsnhG6p8= + dependencies: + flat "^4.1.0" + lodash "^4.17.15" + yargs "^13.3.0" + +yargs@13.3.0, yargs@^13.3.0: + version "13.3.0" + resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha1-TGV6VeB+Xyz5R/ijZlZ8BKDe3IM= + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.1" + yargs@^14.2.2: version "14.2.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.2.tgz#2769564379009ff8597cdd38fba09da9b493c4b5" From 5c0c93ce1d9f066f73964c30b4bc0366d769d7aa Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 18 Dec 2019 13:47:56 -0600 Subject: [PATCH 0534/1037] Remove nested travis file --- packages/pg-cursor/.travis.yml | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 packages/pg-cursor/.travis.yml diff --git a/packages/pg-cursor/.travis.yml b/packages/pg-cursor/.travis.yml deleted file mode 100644 index aea6a149e..000000000 --- a/packages/pg-cursor/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: node_js -dist: trusty -sudo: false -node_js: - - '8' - - '10' - - '12' -env: - - PGUSER=postgres -services: - - postgresql -addons: - postgresql: '9.6' -before_script: - - psql -c 'create database travis;' -U postgres | true From 57177d749e57b271f92962058e586b39396a95e3 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 18 Dec 2019 13:53:57 -0600 Subject: [PATCH 0535/1037] Use public npm - accidentally had my work npm configured --- packages/pg-cursor/yarn.lock | 1298 ---------------------------------- yarn.lock | 391 +++++----- 2 files changed, 178 insertions(+), 1511 deletions(-) delete mode 100644 packages/pg-cursor/yarn.lock diff --git a/packages/pg-cursor/yarn.lock b/packages/pg-cursor/yarn.lock deleted file mode 100644 index 51b9a87f7..000000000 --- a/packages/pg-cursor/yarn.lock +++ /dev/null @@ -1,1298 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/code-frame@^7.0.0": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" - integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== - dependencies: - "@babel/highlight" "^7.0.0" - -"@babel/highlight@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== - dependencies: - chalk "^2.0.0" - esutils "^2.0.2" - js-tokens "^4.0.0" - -acorn-jsx@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" - integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== - -acorn@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" - integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== - -ajv@^6.10.0, ajv@^6.10.2: - version "6.10.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" - integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== - dependencies: - fast-deep-equal "^2.0.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -ansi-colors@3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" - integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== - -ansi-escapes@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" - integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -astral-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" - integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -buffer-writer@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" - integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== - -callsites@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" - integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -chardet@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" - integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== - -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= - dependencies: - restore-cursor "^2.0.0" - -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= - -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== - dependencies: - color-name "1.1.3" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -cross-spawn@^6.0.5: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== - dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" - -debug@3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -debug@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -define-properties@^1.1.2, define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -diff@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -es-abstract@^1.5.1: - version "1.16.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" - integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== - dependencies: - es-to-primitive "^1.2.0" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.0" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-inspect "^1.6.0" - object-keys "^1.1.1" - string.prototype.trimleft "^2.1.0" - string.prototype.trimright "^2.1.0" - -es-to-primitive@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -eslint-config-prettier@^6.4.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.4.0.tgz#0a04f147e31d33c6c161b2dd0971418ac52d0477" - integrity sha512-YrKucoFdc7SEko5Sxe4r6ixqXPDP1tunGw91POeZTTRKItf/AMFYt/YLEQtZMkR2LVpAVhcAcZgcWpm1oGPW7w== - dependencies: - get-stdin "^6.0.0" - -eslint-plugin-prettier@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.1.tgz#507b8562410d02a03f0ddc949c616f877852f2ba" - integrity sha512-A+TZuHZ0KU0cnn56/9mfR7/KjUJ9QNVXUhwvRFSR7PGPe0zQR6PTkmyqg1AtUUEOzTqeRsUwyKFh0oVZKVCrtA== - dependencies: - prettier-linter-helpers "^1.0.0" - -eslint-scope@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" - integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-utils@^1.4.2: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== - dependencies: - eslint-visitor-keys "^1.1.0" - -eslint-visitor-keys@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== - -eslint@^6.5.1: - version "6.5.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.5.1.tgz#828e4c469697d43bb586144be152198b91e96ed6" - integrity sha512-32h99BoLYStT1iq1v2P9uwpyznQ4M2jRiFB6acitKz52Gqn+vPaMDUTB1bYi1WN4Nquj2w+t+bimYUG83DC55A== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.2" - eslint-visitor-keys "^1.1.0" - espree "^6.1.1" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^11.7.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^6.4.1" - is-glob "^4.0.0" - js-yaml "^3.13.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" - table "^5.2.3" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - -espree@^6.1.1: - version "6.1.2" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" - integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== - dependencies: - acorn "^7.1.0" - acorn-jsx "^5.1.0" - eslint-visitor-keys "^1.1.0" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== - dependencies: - estraverse "^4.0.0" - -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== - dependencies: - estraverse "^4.1.0" - -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -external-editor@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" - integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== - dependencies: - chardet "^0.7.0" - iconv-lite "^0.4.24" - tmp "^0.0.33" - -fast-deep-equal@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= - -fast-diff@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= - -fast-levenshtein@~2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" - integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== - dependencies: - flat-cache "^2.0.1" - -find-up@3.0.0, find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -flat-cache@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" - integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== - dependencies: - flatted "^2.0.0" - rimraf "2.6.3" - write "1.0.3" - -flat@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" - integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== - dependencies: - is-buffer "~2.0.3" - -flatted@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" - integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -get-stdin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== - -glob-parent@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" - integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== - dependencies: - is-glob "^4.0.1" - -glob@7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.3: - version "7.1.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.5.tgz#6714c69bee20f3c3e64c4dd905553e532b40cdc0" - integrity sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.7.0: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= - -has@^1.0.1, has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -iconv-lite@^0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -ignore@^4.0.6: - version "4.0.6" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" - integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== - -import-fresh@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.1.0.tgz#6d33fa1dcef6df930fae003446f33415af905118" - integrity sha512-PpuksHKGt8rXfWEr9m9EHIpgyyaltBy8+eF6GJM0QCAxMgxCfucMF3mjecK2QsJr0amJW7gTqh5/wht0z2UhEQ== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -inquirer@^6.4.1: - version "6.5.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" - integrity sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ== - dependencies: - ansi-escapes "^3.2.0" - chalk "^2.4.2" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^2.0.0" - lodash "^4.17.12" - mute-stream "0.0.7" - run-async "^2.2.0" - rxjs "^6.4.0" - string-width "^2.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" - -is-buffer@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" - integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== - -is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== - -is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= - -is-extglob@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-glob@^4.0.0, is-glob@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" - integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== - dependencies: - is-extglob "^2.1.1" - -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= - -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= - dependencies: - has "^1.0.1" - -is-symbol@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== - dependencies: - has-symbols "^1.0.0" - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -js-tokens@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-yaml@3.13.1, js-yaml@^3.13.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - -log-symbols@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - -minimatch@3.0.4, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -mkdirp@0.5.1, mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -mocha@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" - integrity sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A== - dependencies: - ansi-colors "3.2.3" - browser-stdout "1.3.1" - debug "3.2.6" - diff "3.5.0" - escape-string-regexp "1.0.5" - find-up "3.0.0" - glob "7.1.3" - growl "1.10.5" - he "1.2.0" - js-yaml "3.13.1" - log-symbols "2.2.0" - minimatch "3.0.4" - mkdirp "0.5.1" - ms "2.1.1" - node-environment-flags "1.0.5" - object.assign "4.1.0" - strip-json-comments "2.0.1" - supports-color "6.0.0" - which "1.3.1" - wide-align "1.1.3" - yargs "13.3.0" - yargs-parser "13.1.1" - yargs-unparser "1.6.0" - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - -ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= - -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - -node-environment-flags@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" - integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== - dependencies: - object.getownpropertydescriptors "^2.0.3" - semver "^5.7.0" - -object-inspect@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== - -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - -object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= - dependencies: - mimic-fn "^1.0.0" - -optionator@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - integrity sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q= - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.4" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - wordwrap "~1.0.0" - -os-tmpdir@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= - -p-limit@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== - dependencies: - p-try "^2.0.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -packet-reader@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" - integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== - -parent-module@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" - integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== - dependencies: - callsites "^3.0.0" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -pg-connection-string@0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" - integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc= - -pg-int8@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" - integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== - -pg-pool@^2.0.4: - version "2.0.7" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.7.tgz#f14ecab83507941062c313df23f6adcd9fd0ce54" - integrity sha512-UiJyO5B9zZpu32GSlP0tXy8J2NsJ9EFGFfz5v6PSbdz/1hBLX1rNiiy5+mAm5iJJYwfCv4A0EBcQLGWwjbpzZw== - -pg-types@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" - integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== - dependencies: - pg-int8 "1.0.1" - postgres-array "~2.0.0" - postgres-bytea "~1.0.0" - postgres-date "~1.0.4" - postgres-interval "^1.1.0" - -pg@7.x: - version "7.12.1" - resolved "https://registry.yarnpkg.com/pg/-/pg-7.12.1.tgz#880636d46d2efbe0968e64e9fe0eeece8ef72a7e" - integrity sha512-l1UuyfEvoswYfcUe6k+JaxiN+5vkOgYcVSbSuw3FvdLqDbaoa2RJo1zfJKfPsSYPFVERd4GHvX3s2PjG1asSDA== - dependencies: - buffer-writer "2.0.0" - packet-reader "1.0.0" - pg-connection-string "0.1.3" - pg-pool "^2.0.4" - pg-types "^2.1.0" - pgpass "1.x" - semver "4.3.2" - -pgpass@1.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" - integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY= - dependencies: - split "^1.0.0" - -postgres-array@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" - integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== - -postgres-bytea@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" - integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU= - -postgres-date@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.4.tgz#1c2728d62ef1bff49abdd35c1f86d4bdf118a728" - integrity sha512-bESRvKVuTrjoBluEcpv2346+6kgB7UlnqWZsnbnCccTNq/pqfj1j6oBaN5+b/NrDXepYUT/HKadqv3iS9lJuVA== - -postgres-interval@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" - integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== - dependencies: - xtend "^4.0.0" - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -prettier-linter-helpers@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== - dependencies: - fast-diff "^1.1.2" - -prettier@^1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" - integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== - -progress@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" - integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== - -punycode@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -resolve-from@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" - integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== - -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -rimraf@2.6.3: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= - dependencies: - is-promise "^2.1.0" - -rxjs@^6.4.0: - version "6.5.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" - integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== - dependencies: - tslib "^1.9.0" - -"safer-buffer@>= 2.1.2 < 3": - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -semver@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" - integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= - -semver@^5.5.0, semver@^5.7.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.1.2: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= - -slice-ansi@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" - integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== - dependencies: - ansi-styles "^3.2.0" - astral-regex "^1.0.0" - is-fullwidth-code-point "^2.0.0" - -split@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== - dependencies: - through "2" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -"string-width@^1.0.2 || 2", string-width@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string.prototype.trimleft@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" - integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== - dependencies: - define-properties "^1.1.3" - function-bind "^1.1.1" - -string.prototype.trimright@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" - integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== - dependencies: - define-properties "^1.1.3" - function-bind "^1.1.1" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-json-comments@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -strip-json-comments@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" - integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== - -supports-color@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" - integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== - dependencies: - has-flag "^3.0.0" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -table@^5.2.3: - version "5.4.6" - resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" - integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== - dependencies: - ajv "^6.10.2" - lodash "^4.17.14" - slice-ansi "^2.1.0" - string-width "^3.0.0" - -text-table@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -through@2, through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -tmp@^0.0.33: - version "0.0.33" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" - integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== - dependencies: - os-tmpdir "~1.0.2" - -tslib@^1.9.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" - integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - -uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== - dependencies: - punycode "^2.1.0" - -v8-compile-cache@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" - integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - -which@1.3.1, which@^1.2.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -wide-align@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= - -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" - integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== - dependencies: - mkdirp "^0.5.1" - -xtend@^4.0.0: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== - -y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== - -yargs-parser@13.1.1, yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-unparser@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" - integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== - dependencies: - flat "^4.1.0" - lodash "^4.17.15" - yargs "^13.3.0" - -yargs@13.3.0, yargs@^13.3.0: - version "13.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.1" diff --git a/yarn.lock b/yarn.lock index 05d5e8f93..110a8dc72 100644 --- a/yarn.lock +++ b/yarn.lock @@ -807,9 +807,9 @@ universal-user-agent "^4.0.0" "@octokit/rest@^16.28.4": - version "16.35.0" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.35.0.tgz#7ccc1f802f407d5b8eb21768c6deca44e7b4c0d8" - integrity sha512-9ShFqYWo0CLoGYhA1FdtdykJuMzS/9H6vSbbQWDX4pWr4p9v+15MsH/wpd/3fIU+tSxylaNO48+PIHqOkBRx3w== + version "16.35.2" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.35.2.tgz#0098c9e2a895d4afb0fa6578479283553543143c" + integrity sha512-iijaNZpn9hBpUdh8YdXqNiWazmq4R1vCUsmxpBB0kCQ0asHZpCx+HNs22eiHuwYKRhO31ZSAGBJLi0c+3XHaKQ== dependencies: "@octokit/request" "^5.2.0" "@octokit/request-error" "^1.0.2" @@ -851,9 +851,9 @@ integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== "@types/node@*", "@types/node@>= 8": - version "12.12.14" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.14.tgz#1c1d6e3c75dba466e0326948d56e8bd72a1903d2" - integrity sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA== + version "12.12.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.21.tgz#aa44a6363291c7037111c47e4661ad210aded23f" + integrity sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA== "@zkochan/cmd-shim@^3.1.0": version "3.1.0" @@ -920,8 +920,8 @@ ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: ansi-colors@3.2.3: version "3.2.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" - integrity sha1-V9NbhoboUeLMBMQD8cACA5dqGBM= + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" + integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== ansi-escapes@^3.2.0: version "3.2.0" @@ -1023,12 +1023,12 @@ array-ify@^1.0.0: integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= array-includes@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.0.3.tgz#184b48f62d92d7452bb31b323165c7f8bd02266d" - integrity sha1-GEtI9i2S10UrsxsyMWXH+L0CJm0= + version "3.1.0" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.0.tgz#48a929ef4c6bb1fa6dc4a92c9b023a261b0ca404" + integrity sha512-ONOEQoKrvXPKk7Su92Co0YMqYO32FfqJTzkKU9u2UpIXyYZIzLSvpdg4AwvSw4mSUW0czu6inK+zby6Oj6gDjQ== dependencies: - define-properties "^1.1.2" - es-abstract "^1.7.0" + define-properties "^1.1.3" + es-abstract "^1.17.0-next.0" array-union@^1.0.2: version "1.0.2" @@ -1047,6 +1047,14 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= +array.prototype.flat@^1.2.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b" + integrity sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -1145,9 +1153,9 @@ bluebird@3.5.2: integrity sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg== bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5: - version "3.7.1" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.1.tgz#df70e302b471d7473489acf26a93d63b53f874de" - integrity sha512-DdmyoGCleJnkbp3nkbxTLJ18rjDsE4yCggEwKNXkeV123sPNfOCYeDoeuOY+F2FrSjO1YXcTU+dsy96KMy+gcg== + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== brace-expansion@^1.1.7: version "1.1.11" @@ -1175,8 +1183,8 @@ braces@^2.3.1: browser-stdout@1.3.1: version "1.3.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha1-uqVZ7hTO1zRSIputcyZGfGH6vWA= + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== btoa-lite@^1.0.0: version "1.0.0" @@ -1663,7 +1671,7 @@ debug@3.2.6, debug@^3.1.0: dependencies: ms "^2.1.1" -debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: +debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -1776,8 +1784,8 @@ dezalgo@^1.0.0: diff@3.5.0: version "3.5.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha1-gAwN0eCov7yVg1wgKtIg/jF+WhI= + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== dir-glob@^2.2.2: version "2.2.2" @@ -1862,10 +1870,10 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -env-paths@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0" - integrity sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA= +env-paths@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" + integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== err-code@^1.0.0: version "1.1.2" @@ -1879,10 +1887,10 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.12.0, es-abstract@^1.5.1, es-abstract@^1.7.0: - version "1.16.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.2.tgz#4e874331645e9925edef141e74fc4bd144669d34" - integrity sha512-jYo/J8XU2emLXl3OLwfwtuFfuF2w6DYPs+xy9ZfVyPkDcrauu6LYrw/q2TyCtrbc/KUdCiC5e9UajRhgNkVopA== +es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1: + version "1.17.0-next.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0-next.1.tgz#94acc93e20b05a6e96dacb5ab2f1cb3a81fc2172" + integrity sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" @@ -1892,6 +1900,7 @@ es-abstract@^1.12.0, es-abstract@^1.5.1, es-abstract@^1.7.0: is-regex "^1.0.4" object-inspect "^1.7.0" object-keys "^1.1.1" + object.assign "^4.1.0" string.prototype.trimleft "^2.1.0" string.prototype.trimright "^2.1.0" @@ -1923,8 +1932,8 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: eslint-config-prettier@^6.4.0: version "6.7.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-config-prettier/-/eslint-config-prettier-6.7.0.tgz#9a876952e12df2b284adbd3440994bf1f39dfbb9" - integrity sha1-modpUuEt8rKErb00QJlL8fOd+7k= + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.7.0.tgz#9a876952e12df2b284adbd3440994bf1f39dfbb9" + integrity sha512-FamQVKM3jjUVwhG4hEMnbtsq7xOIDm+SY5iBPfR8gKsJoAB2IQnNF+bk1+8Fy44Nq7PPJaLvkRxILYdJWoguKQ== dependencies: get-stdin "^6.0.0" @@ -1941,12 +1950,12 @@ eslint-import-resolver-node@^0.3.2: debug "^2.6.9" resolve "^1.5.0" -eslint-module-utils@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.4.1.tgz#7b4675875bf96b0dbf1b21977456e5bb1f5e018c" - integrity sha512-H6DOj+ejw7Tesdgbfs4jeS4YMFrT8uI8xwd1gtQqXssaR0EQ26L+2O/w6wkYFy2MymON0fTwHmXBvvfLNZVZEw== +eslint-module-utils@^2.4.1: + version "2.5.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.5.0.tgz#cdf0b40d623032274ccd2abd7e64c4e524d6e19c" + integrity sha512-kCo8pZaNz2dsAW7nCUjuVoI11EBXXpIzfNxmaoLhXoRDOnqXLC4iSGVRdZPhOitfbdEfMEfKOiENaK6wDPZEGw== dependencies: - debug "^2.6.8" + debug "^2.6.9" pkg-dir "^2.0.0" eslint-plugin-es@^1.4.1: @@ -1958,21 +1967,22 @@ eslint-plugin-es@^1.4.1: regexpp "^2.0.1" eslint-plugin-import@^2.18.1: - version "2.18.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.18.2.tgz#02f1180b90b077b33d447a17a2326ceb400aceb6" - integrity sha512-5ohpsHAiUBRNaBWAF08izwUGlbrJoJJ+W9/TBwsGoR1MnlgfwMIKrFeSjWbt6moabiXW9xNvtFz+97KHRfI4HQ== + version "2.19.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.19.1.tgz#5654e10b7839d064dd0d46cd1b88ec2133a11448" + integrity sha512-x68131aKoCZlCae7rDXKSAQmbT5DQuManyXo2sK6fJJ0aK5CWAkv6A6HJZGgqC8IhjQxYPgo6/IY4Oz8AFsbBw== dependencies: array-includes "^3.0.3" + array.prototype.flat "^1.2.1" contains-path "^0.1.0" debug "^2.6.9" doctrine "1.5.0" eslint-import-resolver-node "^0.3.2" - eslint-module-utils "^2.4.0" + eslint-module-utils "^2.4.1" has "^1.0.3" minimatch "^3.0.4" object.values "^1.1.0" read-pkg-up "^2.0.0" - resolve "^1.11.0" + resolve "^1.12.0" eslint-plugin-node@^9.1.0: version "9.2.0" @@ -1988,8 +1998,8 @@ eslint-plugin-node@^9.1.0: eslint-plugin-prettier@^3.1.1: version "3.1.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz#432e5a667666ab84ce72f945c72f77d996a5c9ba" - integrity sha1-Qy5aZnZmq4TOcvlFxy932Zalybo= + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz#432e5a667666ab84ce72f945c72f77d996a5c9ba" + integrity sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA== dependencies: prettier-linter-helpers "^1.0.0" @@ -2023,53 +2033,10 @@ eslint-visitor-keys@^1.1.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== -eslint@^6.0.1: - version "6.7.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.1.tgz#269ccccec3ef60ab32358a44d147ac209154b919" - integrity sha512-UWzBS79pNcsDSxgxbdjkmzn/B6BhsXMfUaOHnNwyE8nD+Q6pyT96ow2MccVayUTV4yMid4qLhMiQaywctRkBLA== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^7.0.0" - is-glob "^4.0.0" - js-yaml "^3.13.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.3" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" - table "^5.2.3" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - -eslint@^6.5.1: +eslint@^6.0.1, eslint@^6.5.1: version "6.7.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/eslint/-/eslint-6.7.2.tgz#c17707ca4ad7b2d8af986a33feba71e18a9fecd1" - integrity sha1-wXcHykrXstivmGoz/rpx4Yqf7NE= + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.2.tgz#c17707ca4ad7b2d8af986a33feba71e18a9fecd1" + integrity sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng== dependencies: "@babel/code-frame" "^7.0.0" ajv "^6.10.0" @@ -2238,8 +2205,8 @@ fast-deep-equal@^2.0.1: fast-diff@^1.1.2: version "1.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" - integrity sha1-c+4RmC2Gyq95WYKNUZz+kn+sXwM= + resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03" + integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w== fast-glob@^2.2.6: version "2.2.7" @@ -2254,9 +2221,9 @@ fast-glob@^2.2.6: micromatch "^3.1.10" fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== fast-levenshtein@~2.0.6: version "2.0.6" @@ -2332,8 +2299,8 @@ flat-cache@^2.0.1: flat@^4.1.0: version "4.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" - integrity sha1-CQvsiwXjnLowl0fx1YjwTbr5jbI= + resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" + integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== dependencies: is-buffer "~2.0.3" @@ -2472,8 +2439,8 @@ get-stdin@^4.0.1: get-stdin@^6.0.0: version "6.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha1-ngm/cSs2CrkiXoEgSPcf3pyJZXs= + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" @@ -2565,8 +2532,8 @@ glob-to-regexp@^0.3.0: glob@7.1.3: version "7.1.3" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha1-OWCDLT8VdBCDQtr9OmezMsCWnfE= + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -2575,7 +2542,7 @@ glob@7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.3, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: +glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -2608,15 +2575,15 @@ globby@^9.2.0: pify "^4.0.1" slash "^2.0.0" -graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0: +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2: version "4.2.3" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== growl@1.10.5: version "1.10.5" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha1-8nNdwig2dPpnR4sQGBBZNVw2nl4= + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== handlebars@^4.4.0: version "4.5.3" @@ -2688,7 +2655,7 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" -has@^1.0.1, has@^1.0.3: +has@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== @@ -2697,8 +2664,8 @@ has@^1.0.1, has@^1.0.3: he@1.2.0: version "1.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha1-hK5l+n6vsWX922FWauFLrwVmTw8= + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== hosted-git-info@^2.1.4, hosted-git-info@^2.7.1: version "2.8.5" @@ -2869,9 +2836,9 @@ inquirer@^6.2.0: through "^2.3.6" inquirer@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.0.tgz#9e2b032dde77da1db5db804758b8fea3a970519a" - integrity sha512-rSdC7zelHdRQFkWnhsMu2+2SO41mpv2oF2zy4tMhmiLWkcKbOAs87fWAJhVXttKVwhdZvymvnuM95EyEXg2/tQ== + version "7.0.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.1.tgz#13f7980eedc73c689feff3994b109c4e799c6ebb" + integrity sha512-V1FFQ3TIO15det8PijPLFR9M9baSlnRs9nL7zWu1MNVA2T9YVl9ZbrHJhYs7e9X8jeMZ3lr2JH/rdHFgNCBdYw== dependencies: ansi-escapes "^4.2.1" chalk "^2.4.2" @@ -2882,7 +2849,7 @@ inquirer@^7.0.0: lodash "^4.17.15" mute-stream "0.0.8" run-async "^2.2.0" - rxjs "^6.4.0" + rxjs "^6.5.3" string-width "^4.1.0" strip-ansi "^5.1.0" through "^2.3.6" @@ -2918,8 +2885,8 @@ is-buffer@^1.1.5: is-buffer@~2.0.3: version "2.0.4" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" - integrity sha1-PlcvI8hBGlz9lVfISeNmXgspBiM= + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== is-callable@^1.1.4: version "1.1.4" @@ -3067,11 +3034,11 @@ is-promise@^2.1.0: integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== dependencies: - has "^1.0.1" + has "^1.0.3" is-ssh@^1.3.0: version "1.3.1" @@ -3381,8 +3348,8 @@ lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: log-symbols@2.2.0: version "2.2.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha1-V0Dhxdbw39pK2TI7UzIQfva0xAo= + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" + integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== dependencies: chalk "^2.0.1" @@ -3637,8 +3604,8 @@ mkdirp@*, mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: mocha@^6.2.2: version "6.2.2" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" - integrity sha1-XYmH4olAyviVen12ZLkQ3Fsv6iA= + resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" + integrity sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A== dependencies: ansi-colors "3.2.3" browser-stdout "1.3.1" @@ -3688,8 +3655,8 @@ ms@2.0.0: ms@2.1.1: version "2.1.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha1-MKWGTrPrsKZvLr5tcnrwagnYbgo= + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== ms@^2.0.0, ms@^2.1.1: version "2.1.2" @@ -3759,8 +3726,8 @@ nice-try@^1.0.4: node-environment-flags@1.0.5: version "1.0.5" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" - integrity sha1-+pMCdfW/Xa4YjWGSsktMi7rD12o= + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" + integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== dependencies: object.getownpropertydescriptors "^2.0.3" semver "^5.7.0" @@ -3780,28 +3747,29 @@ node-fetch@^2.3.0, node-fetch@^2.5.0: integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== node-gyp@^5.0.2: - version "5.0.5" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.0.5.tgz#f6cf1da246eb8c42b097d7cd4d6c3ce23a4163af" - integrity sha512-WABl9s4/mqQdZneZHVWVG4TVr6QQJZUC6PAx47ITSk9lreZ1n+7Z9mMAIbA3vnO4J9W20P7LhCxtzfWsAD/KDw== + version "5.0.7" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.0.7.tgz#dd4225e735e840cf2870e4037c2ed9c28a31719e" + integrity sha512-K8aByl8OJD51V0VbUURTKsmdswkQQusIvlvmTyhHlIT1hBvaSxzdxpSle857XuXa7uc02UEZx9OR5aDxSWS5Qw== dependencies: - env-paths "^1.0.0" - glob "^7.0.3" - graceful-fs "^4.1.2" - mkdirp "^0.5.0" - nopt "2 || 3" - npmlog "0 || 1 || 2 || 3 || 4" - request "^2.87.0" - rimraf "2" - semver "~5.3.0" + env-paths "^2.2.0" + glob "^7.1.4" + graceful-fs "^4.2.2" + mkdirp "^0.5.1" + nopt "^4.0.1" + npmlog "^4.1.2" + request "^2.88.0" + rimraf "^2.6.3" + semver "^5.7.1" tar "^4.4.12" - which "1" + which "^1.3.1" -"nopt@2 || 3": - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= dependencies: abbrev "1" + osenv "^0.1.4" normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package-data@^2.3.2, normalize-package-data@^2.3.4, normalize-package-data@^2.3.5, normalize-package-data@^2.4.0, normalize-package-data@^2.5.0: version "2.5.0" @@ -3819,9 +3787,11 @@ normalize-url@^3.3.0: integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== npm-bundled@^1.0.1: - version "1.0.6" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" - integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== + version "1.1.1" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" + integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== + dependencies: + npm-normalize-package-bin "^1.0.1" npm-lifecycle@^3.1.2: version "3.1.4" @@ -3837,6 +3807,11 @@ npm-lifecycle@^3.1.2: umask "^1.1.0" which "^1.3.1" +npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + "npm-package-arg@^4.0.0 || ^5.0.0 || ^6.0.0", npm-package-arg@^6.0.0, npm-package-arg@^6.1.0: version "6.1.1" resolved "https://registry.yarnpkg.com/npm-package-arg/-/npm-package-arg-6.1.1.tgz#02168cb0a49a2b75bf988a28698de7b529df5cb7" @@ -3848,9 +3823,9 @@ npm-lifecycle@^3.1.2: validate-npm-package-name "^3.0.0" npm-packlist@^1.4.4: - version "1.4.6" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.6.tgz#53ba3ed11f8523079f1457376dd379ee4ea42ff4" - integrity sha512-u65uQdb+qwtGvEJh/DgQgW1Xg7sqeNbmxYyrvlNznaVTjV3E5P6F/EFjM+BVHXl7JJlsdG8A64M0XI8FI/IOlg== + version "1.4.7" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.7.tgz#9e954365a06b80b18111ea900945af4f88ed4848" + integrity sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -3871,7 +3846,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.1.2: +npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -3922,10 +3897,10 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@4.1.0: +object.assign@4.1.0, object.assign@^4.1.0: version "4.1.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha1-lovxEA15Vrs8oIbwBvhGs7xACNo= + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== dependencies: define-properties "^1.1.2" function-bind "^1.1.1" @@ -3933,12 +3908,12 @@ object.assign@4.1.0: object-keys "^1.0.11" object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= + version "2.1.0" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" + integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" object.pick@^1.3.0: version "1.3.0" @@ -3948,12 +3923,12 @@ object.pick@^1.3.0: isobject "^3.0.1" object.values@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.0.tgz#bf6810ef5da3e5325790eaaa2be213ea84624da9" - integrity sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg== + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== dependencies: define-properties "^1.1.3" - es-abstract "^1.12.0" + es-abstract "^1.17.0-next.1" function-bind "^1.1.1" has "^1.0.3" @@ -4021,7 +3996,7 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@^0.1.5: +osenv@^0.1.4, osenv@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== @@ -4345,15 +4320,15 @@ prelude-ls@~1.1.2: prettier-linter-helpers@^1.0.0: version "1.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" - integrity sha1-0j1B/hN1ZG3i0BBNNFSjAIgCz3s= + resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" + integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w== dependencies: fast-diff "^1.1.2" prettier@^1.18.2: version "1.19.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" - integrity sha1-99f1/4qc2HKnvkyhQglZVqYHl8s= + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== process-nextick-args@~2.0.0: version "2.0.1" @@ -4403,9 +4378,9 @@ protoduck@^5.0.1: genfun "^5.0.0" psl@^1.1.24: - version "1.4.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" - integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== + version "1.6.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.6.0.tgz#60557582ee23b6c43719d9890fb4170ecd91e110" + integrity sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA== pump@^2.0.0: version "2.0.1" @@ -4465,14 +4440,14 @@ read-cmd-shim@^1.0.1: graceful-fs "^4.1.2" "read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@^2.0.13: - version "2.1.0" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.0.tgz#e3d42e6c35ea5ae820d9a03ab0c7291217fc51d5" - integrity sha512-KLhu8M1ZZNkMcrq1+0UJbR8Dii8KZUqB0Sha4mOx/bknfKI/fyrQVrG/YIt2UOtG667sD8+ee4EXMM91W9dC+A== + version "2.1.1" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.1.tgz#16aa66c59e7d4dad6288f179dd9295fd59bb98f1" + integrity sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A== dependencies: glob "^7.1.1" json-parse-better-errors "^1.0.1" normalize-package-data "^2.0.0" - slash "^1.0.0" + npm-normalize-package-bin "^1.0.0" optionalDependencies: graceful-fs "^4.1.2" @@ -4621,7 +4596,7 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@^2.87.0: +request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== @@ -4679,10 +4654,10 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.10.0, resolve@^1.10.1, resolve@^1.11.0, resolve@^1.5.0: - version "1.13.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.13.1.tgz#be0aa4c06acd53083505abb35f4d66932ab35d16" - integrity sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w== +resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.5.0: + version "1.14.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.0.tgz#6d14c6f9db9f8002071332b600039abf82053f64" + integrity sha512-uviWSi5N67j3t3UKFxej1loCH0VZn5XuqdNxoLShPcYPw6cUZn74K1VRj+9myynRX03bxIBEkwlkob/ujLsJVw== dependencies: path-parse "^1.0.6" @@ -4712,13 +4687,6 @@ retry@^0.10.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q= -rimraf@2, rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -4726,6 +4694,13 @@ rimraf@2.6.3: dependencies: glob "^7.1.3" +rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + run-async@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" @@ -4740,7 +4715,7 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@^6.4.0: +rxjs@^6.4.0, rxjs@^6.5.3: version "6.5.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== @@ -4769,7 +4744,7 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: +"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -4784,11 +4759,6 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.2.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@~5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= - set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -4828,11 +4798,6 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= - slash@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" @@ -5027,9 +4992,9 @@ stream-each@^1.1.0: stream-shift "^1.0.0" stream-shift@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.0.tgz#d5c752825e5367e786f78e18e445ea223a155952" - integrity sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI= + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== string-width@^1.0.1: version "1.0.2" @@ -5155,7 +5120,7 @@ strip-indent@^2.0.0: strip-json-comments@2.0.1: version "2.0.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= strip-json-comments@^3.0.1: @@ -5174,8 +5139,8 @@ strong-log-transformer@^2.0.0: supports-color@6.0.0: version "6.0.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" - integrity sha1-ds/nQs8fQbubHCmtAwaMBbTA5Ao= + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" + integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== dependencies: has-flag "^3.0.0" @@ -5372,9 +5337,9 @@ typedarray@^0.0.6: integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= uglify-js@^3.1.4: - version "3.7.0" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.0.tgz#14b854003386b7a7c045910f43afbc96d2aa5307" - integrity sha512-PC/ee458NEMITe1OufAjal65i6lB58R1HWMRcxwvdz1UopW0DYqlRL3xdu3IcTvTXsB02CRHykidkTRL+A3hQA== + version "3.7.2" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.2.tgz#cb1a601e67536e9ed094a92dd1e333459643d3f9" + integrity sha512-uhRwZcANNWVLrxLfNFEdltoPNhECUR3lc+UdJoG9CBpMcSnKyWA94tc3eAujB1GcMY5Uwq8ZMp4qWpxWYDQmaA== dependencies: commander "~2.20.3" source-map "~0.6.1" @@ -5522,7 +5487,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1, which@1.3.1, which@^1.2.9, which@^1.3.1: +which@1.3.1, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -5632,8 +5597,8 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: yargs-parser@13.1.1, yargs-parser@^13.1.1: version "13.1.1" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha1-0mBYUyqgbTZf4JH2ofwGsvfl7KA= + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -5655,8 +5620,8 @@ yargs-parser@^15.0.0: yargs-unparser@1.6.0: version "1.6.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" - integrity sha1-7yXCx2n/a9CeSw+dfGBfsnhG6p8= + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" + integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== dependencies: flat "^4.1.0" lodash "^4.17.15" @@ -5664,8 +5629,8 @@ yargs-unparser@1.6.0: yargs@13.3.0, yargs@^13.3.0: version "13.3.0" - resolved "https://artifactory.robot.car/artifactory/api/npm/npm-virtual/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha1-TGV6VeB+Xyz5R/ijZlZ8BKDe3IM= + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" + integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== dependencies: cliui "^5.0.0" find-up "^3.0.0" From b14cf678ccd11d6ccc1bb6327e78d71edb432b77 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 18 Dec 2019 14:08:23 -0600 Subject: [PATCH 0536/1037] Remove postgres 9.1 from test matrix - json is not supported --- .travis.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5b65d51b5..03849285a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,11 +36,7 @@ matrix: addons: postgresql: "9.6" - # PostgreSQL 9.1 and 9.2 only work on precise - - node_js: lts/carbon - addons: - postgresql: "9.1" - dist: precise + # PostgreSQL 9.2 only works on precise - node_js: lts/carbon addons: postgresql: "9.2" From cccf84e14b3281b753e1baab7bc194aaac5024a8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 18 Dec 2019 15:59:06 -0600 Subject: [PATCH 0537/1037] Publish - pg-cursor@2.0.2 - pg@7.15.1 --- packages/pg-cursor/package.json | 4 ++-- packages/pg/package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 60213bb5c..c6841003d 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.0.1", + "version": "2.0.2", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -21,7 +21,7 @@ "eslint-config-prettier": "^6.4.0", "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "7.x", + "pg": "^7.15.1", "prettier": "^1.18.2" }, "prettier": { diff --git a/packages/pg/package.json b/packages/pg/package.json index 651d91c46..951e42df6 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.15.0", + "version": "7.15.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From e5d46749c0e41498da8451622dd3ed2218f717bd Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 18 Dec 2019 23:44:43 -0600 Subject: [PATCH 0538/1037] Work in progress...convert to more efficient reader --- .gitignore | 1 + packages/pg-packet-stream/package.json | 22 + packages/pg-packet-stream/src/index.test.ts | 103 +++ packages/pg-packet-stream/src/index.ts | 177 +++++ .../pg-packet-stream/src/types/chunky.d.ts | 1 + packages/pg-packet-stream/tsconfig.json | 23 + packages/pg/bench.js | 42 ++ packages/pg/lib/client.js | 7 +- packages/pg/lib/connection-fast.js | 709 ++++++++++++++++++ packages/pg/lib/result.js | 24 +- packages/pg/package.json | 1 + .../pg/test/integration/client/api-tests.js | 93 +-- yarn.lock | 107 ++- 13 files changed, 1249 insertions(+), 61 deletions(-) create mode 100644 packages/pg-packet-stream/package.json create mode 100644 packages/pg-packet-stream/src/index.test.ts create mode 100644 packages/pg-packet-stream/src/index.ts create mode 100644 packages/pg-packet-stream/src/types/chunky.d.ts create mode 100644 packages/pg-packet-stream/tsconfig.json create mode 100644 packages/pg/bench.js create mode 100644 packages/pg/lib/connection-fast.js diff --git a/.gitignore b/.gitignore index 88b672dd3..56eba3953 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ build/ node_modules/ package-lock.json *.swp +dist diff --git a/packages/pg-packet-stream/package.json b/packages/pg-packet-stream/package.json new file mode 100644 index 000000000..89027056b --- /dev/null +++ b/packages/pg-packet-stream/package.json @@ -0,0 +1,22 @@ +{ + "name": "pg-packet-stream", + "version": "1.0.0", + "main": "dist/index.js", + "license": "MIT", + "devDependencies": { + "@types/node": "^12.12.21", + "chunky": "^0.0.0", + "mocha": "^6.2.2", + "typescript": "^3.7.3" + }, + "scripts": { + "test": "mocha -r ts-node/register src/**/*.test.ts" + }, + "dependencies": { + "@types/chai": "^4.2.7", + "@types/mocha": "^5.2.7", + "chai": "^4.2.0", + "mocha": "^6.2.2", + "ts-node": "^8.5.4" + } +} diff --git a/packages/pg-packet-stream/src/index.test.ts b/packages/pg-packet-stream/src/index.test.ts new file mode 100644 index 000000000..f5be4e2a0 --- /dev/null +++ b/packages/pg-packet-stream/src/index.test.ts @@ -0,0 +1,103 @@ +import 'mocha'; +import { PgPacketStream, Packet } from './' +import { expect } from 'chai' +import chunky from 'chunky' + +const consume = async (stream: PgPacketStream, count: number): Promise => { + const result: Packet[] = []; + + return new Promise((resolve) => { + const read = () => { + stream.once('readable', () => { + let packet; + while (packet = stream.read()) { + result.push(packet) + } + if (result.length === count) { + resolve(result); + } else { + read() + } + + }) + } + read() + }) +} + +const emptyMessage = Buffer.from([0x0a, 0x00, 0x00, 0x00, 0x04]) +const oneByteMessage = Buffer.from([0x0b, 0x00, 0x00, 0x00, 0x05, 0x0a]) +const bigMessage = Buffer.from([0x0f, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e0, 0x0f]) + +describe('PgPacketStream', () => { + it('should chunk a perfect input packet', async () => { + const stream = new PgPacketStream() + stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x04])) + stream.end() + const buffers = await consume(stream, 1) + expect(buffers).to.have.length(1) + expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x04])) + }); + + it('should read 2 chunks into perfect input packet', async () => { + const stream = new PgPacketStream() + stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x08])) + stream.write(Buffer.from([0x1, 0x2, 0x3, 0x4])) + stream.end() + const buffers = await consume(stream, 1) + expect(buffers).to.have.length(1) + expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x08, 0x1, 0x2, 0x3, 0x4])) + }); + + it('should read a bunch of big messages', async () => { + const stream = new PgPacketStream(); + let totalBuffer = Buffer.allocUnsafe(0); + const num = 2; + for (let i = 0; i < 2; i++) { + totalBuffer = Buffer.concat([totalBuffer, bigMessage, bigMessage]) + } + const chunks = chunky(totalBuffer) + for (const chunk of chunks) { + stream.write(chunk) + } + stream.end() + const messages = await consume(stream, num * 2) + expect(messages.map(x => x.code)).to.eql(new Array(num * 2).fill(0x0f)) + }) + + it('should read multiple messages in a single chunk', async () => { + const stream = new PgPacketStream() + stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x04])) + stream.end() + const buffers = await consume(stream, 2) + expect(buffers).to.have.length(2) + expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x04])) + expect(buffers[1].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x04])) + }); + + it('should read multiple chunks into multiple packets', async () => { + const stream = new PgPacketStream() + stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x05, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x05, 0x0b])) + stream.write(Buffer.from([0x01, 0x00, 0x00])); + stream.write(Buffer.from([0x00, 0x06, 0x0c, 0x0d, 0x03, 0x00, 0x00, 0x00, 0x04])) + stream.end() + const buffers = await consume(stream, 4) + expect(buffers).to.have.length(4) + expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x05, 0x0a])) + expect(buffers[1].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x05, 0x0b])) + expect(buffers[2].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x0d])) + expect(buffers[3].packet).to.deep.equal(Buffer.from([0x3, 0x00, 0x00, 0x00, 0x04])) + }); + + it('reads packet that spans multiple chunks', async () => { + const stream = new PgPacketStream() + stream.write(Buffer.from([0x0d, 0x00, 0x00, 0x00])) + stream.write(Buffer.from([0x09])) // length + stream.write(Buffer.from([0x0a, 0x0b, 0x0c, 0x0d])) + stream.write(Buffer.from([0x0a, 0x0b, 0x0c, 0x0d])) + stream.write(Buffer.from([0x0a, 0x0b, 0x0c, 0x0d])) + stream.end() + const buffers = await consume(stream, 1) + expect(buffers).to.have.length(1) + }) +}); diff --git a/packages/pg-packet-stream/src/index.ts b/packages/pg-packet-stream/src/index.ts new file mode 100644 index 000000000..95f0e82c6 --- /dev/null +++ b/packages/pg-packet-stream/src/index.ts @@ -0,0 +1,177 @@ +import { Transform, TransformCallback, TransformOptions } from 'stream'; +import assert from 'assert' + +export const hello = () => 'Hello world!' + +// this is a single byte +const CODE_LENGTH = 1; +// this is a Uint32 +const LEN_LENGTH = 4; + +export type Packet = { + code: number; + packet: Buffer; +} + +type FieldFormat = "text" | "binary" + +class Field { + constructor(public name: string) { + + } + +} + +const emptyBuffer = Buffer.allocUnsafe(0); + +class BufferReader { + private buffer: Buffer = emptyBuffer; + constructor(private offset: number = 0) { + + } + + public setBuffer(offset: number, buffer: Buffer): void { + this.offset = offset; + this.buffer = buffer; + } + + public int16() { + const result = this.buffer.readInt16BE(this.offset); + this.offset += 2; + return result; + } + + public int32() { + const result = this.buffer.readInt32BE(this.offset); + this.offset += 4; + return result; + } + + public string(length: number): string { + // TODO(bmc): support non-utf8 encoding + const result = this.buffer.toString('utf8', this.offset, this.offset + length) + this.offset += length; + return result; + } + + public bytes(length: number): Buffer { + const result = this.buffer.slice(this.offset, this.offset + length); + this.offset += length; + return result + } +} + +type Mode = 'text' | 'binary'; + +type StreamOptions = TransformOptions & { + mode: Mode +} + +const parseComplete = { + name: 'parseComplete', + length: 5, +}; + +const bindComplete = { + name: 'bindComplete', + length: 5, +} + +const closeComplete = { + name: 'closeComplete', + length: 5, +} + +export class PgPacketStream extends Transform { + private remainingBuffer: Buffer = emptyBuffer; + private reader = new BufferReader(); + private mode: Mode; + + constructor(opts: StreamOptions) { + super({ + ...opts, + readableObjectMode: true + }) + if (opts.mode === 'binary') { + throw new Error('Binary mode not supported yet') + } + this.mode = opts.mode; + } + + public _transform(buffer: Buffer, encoding: string, callback: TransformCallback) { + const combinedBuffer = this.remainingBuffer.byteLength ? Buffer.concat([this.remainingBuffer, buffer], this.remainingBuffer.length + buffer.length) : buffer; + let offset = 0; + while ((offset + CODE_LENGTH + LEN_LENGTH) <= combinedBuffer.byteLength) { + // code is 1 byte long - it identifies the message type + const code = combinedBuffer[offset]; + + // length is 1 Uint32BE - it is the length of the message EXCLUDING the code + const length = combinedBuffer.readUInt32BE(offset + CODE_LENGTH); + + const fullMessageLength = CODE_LENGTH + length; + + if (fullMessageLength + offset <= combinedBuffer.byteLength) { + this.handlePacket(offset, code, length, combinedBuffer); + offset += fullMessageLength; + } else { + break; + } + } + + if (offset === combinedBuffer.byteLength) { + this.remainingBuffer = emptyBuffer; + } else { + this.remainingBuffer = combinedBuffer.slice(offset) + } + + callback(null); + } + + private handlePacket(offset: number, code: number, length: number, combinedBuffer: Buffer) { + switch (code) { + case 0x44: // D + this.parseDataRowMessage(offset, length, combinedBuffer); + break; + case 0x32: // 2 + this.emit('message', bindComplete); + break; + case 0x31: // 1 + this.emit('message', parseComplete); + break; + case 0x33: // 3 + this.emit('message', closeComplete); + break; + default: + const packet = combinedBuffer.slice(offset, CODE_LENGTH + length + offset) + this.push({ code, length, packet, buffer: packet.slice(5) }) + } + } + + public _flush(callback: TransformCallback) { + } + + private parseDataRowMessage(offset: number, length: number, bytes: Buffer) { + this.reader.setBuffer(offset + 5, bytes); + const fieldCount = this.reader.int16(); + const fields: any[] = new Array(fieldCount); + for (let i = 0; i < fieldCount; i++) { + const len = this.reader.int32(); + if (len === -1) { + fields[i] = null + } else if (this.mode === 'text') { + fields[i] = this.reader.string(len) + } + } + const message = new DataRowMessage(length, fields); + this.emit('message', message); + } +} + + +class DataRowMessage { + public readonly fieldCount: number; + public readonly name: string = 'dataRow' + constructor(public length: number, public fields: any[]) { + this.fieldCount = fields.length; + } +} diff --git a/packages/pg-packet-stream/src/types/chunky.d.ts b/packages/pg-packet-stream/src/types/chunky.d.ts new file mode 100644 index 000000000..7389bda66 --- /dev/null +++ b/packages/pg-packet-stream/src/types/chunky.d.ts @@ -0,0 +1 @@ +declare module 'chunky' diff --git a/packages/pg-packet-stream/tsconfig.json b/packages/pg-packet-stream/tsconfig.json new file mode 100644 index 000000000..f6661febd --- /dev/null +++ b/packages/pg-packet-stream/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "module": "commonjs", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": true, + "target": "es6", + "noImplicitAny": true, + "moduleResolution": "node", + "sourceMap": true, + "outDir": "dist", + "baseUrl": ".", + "paths": { + "*": [ + "node_modules/*", + "src/types/*" + ] + } + }, + "include": [ + "src/**/*" + ] +} diff --git a/packages/pg/bench.js b/packages/pg/bench.js new file mode 100644 index 000000000..b650177e2 --- /dev/null +++ b/packages/pg/bench.js @@ -0,0 +1,42 @@ +const pg = require("./lib"); +const pool = new pg.Pool() + +const q = { + text: + "select typname, typnamespace, typowner, typlen, typbyval, typcategory, typispreferred, typisdefined, typdelim, typrelid, typelem, typarray from pg_type where typtypmod = $1 and typisdefined = $2", + values: [-1, true] +}; + +const exec = async client => { + const result = await client.query({ + text: q.text, + values: q.values, + rowMode: "array" + }); +}; + +const bench = async (client, time) => { + let start = Date.now(); + let count = 0; + while (true) { + await exec(client); + count++; + if (Date.now() - start > time) { + return count; + } + } +}; + +const run = async () => { + const client = new pg.Client(); + await client.connect(); + await bench(client, 1000); + console.log("warmup done"); + const seconds = 5; + const queries = await bench(client, seconds * 1000); + console.log("queries:", queries); + console.log("qps", queries / seconds); + await client.end(); +}; + +run().catch(e => console.error(e) || process.exit(-1)); diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 370630a02..077a9f676 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -18,6 +18,9 @@ var ConnectionParameters = require('./connection-parameters') var Query = require('./query') var defaults = require('./defaults') var Connection = require('./connection') +if (process.env.PG_FAST_CONNECTION) { + Connection = require('./connection-fast') +} var Client = function (config) { EventEmitter.call(this) @@ -112,7 +115,7 @@ Client.prototype._connect = function (callback) { con.startup(self.getStartupConf()) }) - function checkPgPass (cb) { + function checkPgPass(cb) { return function (msg) { if (typeof self.password === 'function') { self._Promise.resolve() @@ -492,7 +495,7 @@ Client.prototype.query = function (config, values, callback) { // we already returned an error, // just do nothing if query completes - query.callback = () => {} + query.callback = () => { } // Remove from queue var index = this.queryQueue.indexOf(query) diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js new file mode 100644 index 000000000..5ad38f166 --- /dev/null +++ b/packages/pg/lib/connection-fast.js @@ -0,0 +1,709 @@ +'use strict' +/** + * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) + * All rights reserved. + * + * This source code is licensed under the MIT license found in the + * README.md file in the root directory of this source tree. + */ + +var net = require('net') +var EventEmitter = require('events').EventEmitter +var util = require('util') + +var Writer = require('buffer-writer') +var Reader = require('packet-reader') +var PacketStream = require('pg-packet-stream') + +console.log(PacketStream.hello()) + +var TEXT_MODE = 0 +var BINARY_MODE = 1 +console.log('using faster connection') +var Connection = function (config) { + EventEmitter.call(this) + config = config || {} + this.stream = config.stream || new net.Socket() + this.stream.setNoDelay(true) + this._keepAlive = config.keepAlive + this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis + this.lastBuffer = false + this.lastOffset = 0 + this.buffer = null + this.offset = null + this.encoding = config.encoding || 'utf8' + this.parsedStatements = {} + this.writer = new Writer() + this.ssl = config.ssl || false + this._ending = false + this._mode = TEXT_MODE + this._emitMessage = false + this._reader = new Reader({ + headerSize: 1, + lengthPadding: -4 + }) + var self = this + this.on('newListener', function (eventName) { + if (eventName === 'message') { + self._emitMessage = true + } + }) +} + +util.inherits(Connection, EventEmitter) + +Connection.prototype.connect = function (port, host) { + var self = this + + if (this.stream.readyState === 'closed') { + this.stream.connect(port, host) + } else if (this.stream.readyState === 'open') { + this.emit('connect') + } + + this.stream.on('connect', function () { + if (self._keepAlive) { + self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis) + } + self.emit('connect') + }) + + const reportStreamError = function (error) { + // errors about disconnections should be ignored during disconnect + if (self._ending && (error.code === 'ECONNRESET' || error.code === 'EPIPE')) { + return + } + self.emit('error', error) + } + this.stream.on('error', reportStreamError) + + this.stream.on('close', function () { + self.emit('end') + }) + + if (!this.ssl) { + return this.attachListeners(this.stream) + } + + this.stream.once('data', function (buffer) { + var responseCode = buffer.toString('utf8') + switch (responseCode) { + case 'N': // Server does not support SSL connections + return self.emit('error', new Error('The server does not support SSL connections')) + case 'S': // Server supports SSL connections, continue with a secure connection + break + default: + // Any other response byte, including 'E' (ErrorResponse) indicating a server error + return self.emit('error', new Error('There was an error establishing an SSL connection')) + } + var tls = require('tls') + const options = { + socket: self.stream, + checkServerIdentity: self.ssl.checkServerIdentity || tls.checkServerIdentity, + rejectUnauthorized: self.ssl.rejectUnauthorized, + ca: self.ssl.ca, + pfx: self.ssl.pfx, + key: self.ssl.key, + passphrase: self.ssl.passphrase, + cert: self.ssl.cert, + secureOptions: self.ssl.secureOptions, + NPNProtocols: self.ssl.NPNProtocols + } + if (net.isIP(host) === 0) { + options.servername = host + } + self.stream = tls.connect(options) + self.attachListeners(self.stream) + self.stream.on('error', reportStreamError) + + self.emit('sslconnect') + }) +} + +Connection.prototype.attachListeners = function (stream) { + var self = this + const mode = this._mode === TEXT_MODE ? 'text' : 'binary'; + const packetStream = new PacketStream.PgPacketStream({ mode }) + packetStream.on('message', (msg) => { + self.emit(msg.name, msg) + }) + stream.pipe(packetStream).on('data', (packet) => { + // console.log('buff', packet) + var msg = self.parseMessage(packet) + var eventName = msg.name === 'error' ? 'errorMessage' : msg.name + if (self._emitMessage) { + self.emit('message', msg) + } + self.emit(eventName, msg) + }) + stream.on('end', function () { + self.emit('end') + }) +} + +Connection.prototype.requestSsl = function () { + var bodyBuffer = this.writer + .addInt16(0x04d2) + .addInt16(0x162f) + .flush() + + var length = bodyBuffer.length + 4 + + var buffer = new Writer() + .addInt32(length) + .add(bodyBuffer) + .join() + this.stream.write(buffer) +} + +Connection.prototype.startup = function (config) { + var writer = this.writer.addInt16(3).addInt16(0) + + Object.keys(config).forEach(function (key) { + var val = config[key] + writer.addCString(key).addCString(val) + }) + + writer.addCString('client_encoding').addCString("'utf-8'") + + var bodyBuffer = writer.addCString('').flush() + // this message is sent without a code + + var length = bodyBuffer.length + 4 + + var buffer = new Writer() + .addInt32(length) + .add(bodyBuffer) + .join() + this.stream.write(buffer) +} + +Connection.prototype.cancel = function (processID, secretKey) { + var bodyBuffer = this.writer + .addInt16(1234) + .addInt16(5678) + .addInt32(processID) + .addInt32(secretKey) + .flush() + + var length = bodyBuffer.length + 4 + + var buffer = new Writer() + .addInt32(length) + .add(bodyBuffer) + .join() + this.stream.write(buffer) +} + +Connection.prototype.password = function (password) { + // 0x70 = 'p' + this._send(0x70, this.writer.addCString(password)) +} + +Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) { + // 0x70 = 'p' + this.writer + .addCString(mechanism) + .addInt32(Buffer.byteLength(initialResponse)) + .addString(initialResponse) + + this._send(0x70) +} + +Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) { + // 0x70 = 'p' + this.writer.addString(additionalData) + + this._send(0x70) +} + +Connection.prototype._send = function (code, more) { + if (!this.stream.writable) { + return false + } + return this.stream.write(this.writer.flush(code)) +} + +Connection.prototype.query = function (text) { + // 0x51 = Q + this.stream.write(this.writer.addCString(text).flush(0x51)) +} + +// send parse message +Connection.prototype.parse = function (query) { + // expect something like this: + // { name: 'queryName', + // text: 'select * from blah', + // types: ['int8', 'bool'] } + + // normalize missing query names to allow for null + query.name = query.name || '' + if (query.name.length > 63) { + /* eslint-disable no-console */ + console.error('Warning! Postgres only supports 63 characters for query names.') + console.error('You supplied %s (%s)', query.name, query.name.length) + console.error('This can cause conflicts and silent errors executing queries') + /* eslint-enable no-console */ + } + // normalize null type array + query.types = query.types || [] + var len = query.types.length + var buffer = this.writer + .addCString(query.name) // name of query + .addCString(query.text) // actual query text + .addInt16(len) + for (var i = 0; i < len; i++) { + buffer.addInt32(query.types[i]) + } + + var code = 0x50 + this._send(code) + this.flush() +} + +// send bind message +// "more" === true to buffer the message until flush() is called +Connection.prototype.bind = function (config) { + // normalize config + config = config || {} + config.portal = config.portal || '' + config.statement = config.statement || '' + config.binary = config.binary || false + var values = config.values || [] + var len = values.length + var useBinary = false + for (var j = 0; j < len; j++) { + useBinary |= values[j] instanceof Buffer + } + var buffer = this.writer.addCString(config.portal).addCString(config.statement) + if (!useBinary) { + buffer.addInt16(0) + } else { + buffer.addInt16(len) + for (j = 0; j < len; j++) { + buffer.addInt16(values[j] instanceof Buffer) + } + } + buffer.addInt16(len) + for (var i = 0; i < len; i++) { + var val = values[i] + if (val === null || typeof val === 'undefined') { + buffer.addInt32(-1) + } else if (val instanceof Buffer) { + buffer.addInt32(val.length) + buffer.add(val) + } else { + buffer.addInt32(Buffer.byteLength(val)) + buffer.addString(val) + } + } + + if (config.binary) { + buffer.addInt16(1) // format codes to use binary + buffer.addInt16(1) + } else { + buffer.addInt16(0) // format codes to use text + } + // 0x42 = 'B' + this._send(0x42) + this.flush() +} + +// send execute message +// "more" === true to buffer the message until flush() is called +Connection.prototype.execute = function (config) { + config = config || {} + config.portal = config.portal || '' + config.rows = config.rows || '' + this.writer.addCString(config.portal).addInt32(config.rows) + + // 0x45 = 'E' + this._send(0x45) + this.flush() +} + +var emptyBuffer = Buffer.alloc(0) + +const flushBuffer = Buffer.from([0x48, 0x00, 0x00, 0x00, 0x04]) +Connection.prototype.flush = function () { + if (this.stream.writable) { + this.stream.write(flushBuffer) + } +} + +const syncBuffer = Buffer.from([0x53, 0x00, 0x00, 0x00, 0x04]) +Connection.prototype.sync = function () { + this._ending = true + // clear out any pending data in the writer + this.writer.clear() + if (this.stream.writable) { + this.stream.write(syncBuffer) + this.stream.write(flushBuffer) + } +} + +const END_BUFFER = Buffer.from([0x58, 0x00, 0x00, 0x00, 0x04]) + +Connection.prototype.end = function () { + // 0x58 = 'X' + this.writer.clear() + this._ending = true + return this.stream.write(END_BUFFER, () => { + this.stream.end() + }) +} + +Connection.prototype.close = function (msg) { + this.writer.addCString(msg.type + (msg.name || '')) + this._send(0x43) +} + +Connection.prototype.describe = function (msg) { + this.writer.addCString(msg.type + (msg.name || '')) + this._send(0x44) + this.flush() +} + +Connection.prototype.sendCopyFromChunk = function (chunk) { + this.stream.write(this.writer.add(chunk).flush(0x64)) +} + +Connection.prototype.endCopyFrom = function () { + this.stream.write(this.writer.add(emptyBuffer).flush(0x63)) +} + +Connection.prototype.sendCopyFail = function (msg) { + // this.stream.write(this.writer.add(emptyBuffer).flush(0x66)); + this.writer.addCString(msg) + this._send(0x66) +} + +var Message = function (name, length) { + this.name = name + this.length = length +} + +Connection.prototype.parseMessage = function (packet) { + this.offset = 0 + const { code, length, buffer } = packet + switch (code) { + case 0x52: // R + return this.parseR(buffer, length) + + case 0x53: // S + return this.parseS(buffer, length) + + case 0x4b: // K + return this.parseK(buffer, length) + + case 0x43: // C + return this.parseC(buffer, length) + + case 0x5a: // Z + return this.parseZ(buffer, length) + + case 0x54: // T + return this.parseT(buffer, length) + + case 0x44: // D + return this.parseD(buffer, length) + + case 0x45: // E + return this.parseE(buffer, length) + + case 0x4e: // N + return this.parseN(buffer, length) + + case 0x31: // 1 + return new Message('parseComplete', length) + + case 0x32: // 2 + return new Message('bindComplete', length) + + case 0x33: // 3 + return new Message('closeComplete', length) + + case 0x41: // A + return this.parseA(buffer, length) + + case 0x6e: // n + return new Message('noData', length) + + case 0x49: // I + return new Message('emptyQuery', length) + + case 0x73: // s + return new Message('portalSuspended', length) + + case 0x47: // G + return this.parseG(buffer, length) + + case 0x48: // H + return this.parseH(buffer, length) + + case 0x57: // W + return new Message('replicationStart', length) + + case 0x63: // c + return new Message('copyDone', length) + + case 0x64: // d + return this.parsed(buffer, length) + } + console.log('could not parse', packet) +} + +Connection.prototype.parseR = function (buffer, length) { + var code = this.parseInt32(buffer) + + var msg = new Message('authenticationOk', length) + + switch (code) { + case 0: // AuthenticationOk + return msg + case 3: // AuthenticationCleartextPassword + if (msg.length === 8) { + msg.name = 'authenticationCleartextPassword' + return msg + } + break + case 5: // AuthenticationMD5Password + if (msg.length === 12) { + msg.name = 'authenticationMD5Password' + msg.salt = Buffer.alloc(4) + buffer.copy(msg.salt, 0, this.offset, this.offset + 4) + this.offset += 4 + return msg + } + + break + case 10: // AuthenticationSASL + msg.name = 'authenticationSASL' + msg.mechanisms = [] + do { + var mechanism = this.parseCString(buffer) + + if (mechanism) { + msg.mechanisms.push(mechanism) + } + } while (mechanism) + + return msg + case 11: // AuthenticationSASLContinue + msg.name = 'authenticationSASLContinue' + msg.data = this.readString(buffer, length - 4) + + return msg + case 12: // AuthenticationSASLFinal + msg.name = 'authenticationSASLFinal' + msg.data = this.readString(buffer, length - 4) + + return msg + } + + throw new Error('Unknown authenticationOk message type' + util.inspect(msg)) +} + +Connection.prototype.parseS = function (buffer, length) { + var msg = new Message('parameterStatus', length) + msg.parameterName = this.parseCString(buffer) + msg.parameterValue = this.parseCString(buffer) + return msg +} + +Connection.prototype.parseK = function (buffer, length) { + var msg = new Message('backendKeyData', length) + msg.processID = this.parseInt32(buffer) + msg.secretKey = this.parseInt32(buffer) + return msg +} + +Connection.prototype.parseC = function (buffer, length) { + var msg = new Message('commandComplete', length) + msg.text = this.parseCString(buffer) + return msg +} + +Connection.prototype.parseZ = function (buffer, length) { + var msg = new Message('readyForQuery', length) + msg.name = 'readyForQuery' + msg.status = this.readString(buffer, 1) + return msg +} + +var ROW_DESCRIPTION = 'rowDescription' +Connection.prototype.parseT = function (buffer, length) { + var msg = new Message(ROW_DESCRIPTION, length) + msg.fieldCount = this.parseInt16(buffer) + var fields = [] + for (var i = 0; i < msg.fieldCount; i++) { + fields.push(this.parseField(buffer)) + } + msg.fields = fields + return msg +} + +var Field = function () { + this.name = null + this.tableID = null + this.columnID = null + this.dataTypeID = null + this.dataTypeSize = null + this.dataTypeModifier = null + this.format = null +} + +var FORMAT_TEXT = 'text' +var FORMAT_BINARY = 'binary' +Connection.prototype.parseField = function (buffer) { + var field = new Field() + field.name = this.parseCString(buffer) + field.tableID = this.parseInt32(buffer) + field.columnID = this.parseInt16(buffer) + field.dataTypeID = this.parseInt32(buffer) + field.dataTypeSize = this.parseInt16(buffer) + field.dataTypeModifier = this.parseInt32(buffer) + if (this.parseInt16(buffer) === TEXT_MODE) { + this._mode = TEXT_MODE + field.format = FORMAT_TEXT + } else { + this._mode = BINARY_MODE + field.format = FORMAT_BINARY + } + return field +} + +var DATA_ROW = 'dataRow' +var DataRowMessage = function (length, fieldCount) { + this.name = DATA_ROW + this.length = length + this.fieldCount = fieldCount + this.fields = [] +} + +// extremely hot-path code +Connection.prototype.parseD = function (buffer, length) { + var fieldCount = this.parseInt16(buffer) + var msg = new DataRowMessage(length, fieldCount) + for (var i = 0; i < fieldCount; i++) { + msg.fields.push(this._readValue(buffer)) + } + return msg +} + +// extremely hot-path code +Connection.prototype._readValue = function (buffer) { + var length = this.parseInt32(buffer) + if (length === -1) return null + if (this._mode === TEXT_MODE) { + return this.readString(buffer, length) + } + return this.readBytes(buffer, length) +} + +// parses error +Connection.prototype.parseE = function (buffer, length) { + var fields = {} + var fieldType = this.readString(buffer, 1) + while (fieldType !== '\0') { + fields[fieldType] = this.parseCString(buffer) + fieldType = this.readString(buffer, 1) + } + + // the msg is an Error instance + var msg = new Error(fields.M) + + // for compatibility with Message + msg.name = 'error' + msg.length = length + + msg.severity = fields.S + msg.code = fields.C + msg.detail = fields.D + msg.hint = fields.H + msg.position = fields.P + msg.internalPosition = fields.p + msg.internalQuery = fields.q + msg.where = fields.W + msg.schema = fields.s + msg.table = fields.t + msg.column = fields.c + msg.dataType = fields.d + msg.constraint = fields.n + msg.file = fields.F + msg.line = fields.L + msg.routine = fields.R + return msg +} + +// same thing, different name +Connection.prototype.parseN = function (buffer, length) { + var msg = this.parseE(buffer, length) + msg.name = 'notice' + return msg +} + +Connection.prototype.parseA = function (buffer, length) { + var msg = new Message('notification', length) + msg.processId = this.parseInt32(buffer) + msg.channel = this.parseCString(buffer) + msg.payload = this.parseCString(buffer) + return msg +} + +Connection.prototype.parseG = function (buffer, length) { + var msg = new Message('copyInResponse', length) + return this.parseGH(buffer, msg) +} + +Connection.prototype.parseH = function (buffer, length) { + var msg = new Message('copyOutResponse', length) + return this.parseGH(buffer, msg) +} + +Connection.prototype.parseGH = function (buffer, msg) { + var isBinary = buffer[this.offset] !== 0 + this.offset++ + msg.binary = isBinary + var columnCount = this.parseInt16(buffer) + msg.columnTypes = [] + for (var i = 0; i < columnCount; i++) { + msg.columnTypes.push(this.parseInt16(buffer)) + } + return msg +} + +Connection.prototype.parsed = function (buffer, length) { + var msg = new Message('copyData', length) + msg.chunk = this.readBytes(buffer, msg.length - 4) + return msg +} + +Connection.prototype.parseInt32 = function (buffer) { + var value = buffer.readInt32BE(this.offset) + this.offset += 4 + return value +} + +Connection.prototype.parseInt16 = function (buffer) { + var value = buffer.readInt16BE(this.offset) + this.offset += 2 + return value +} + +Connection.prototype.readString = function (buffer, length) { + return buffer.toString(this.encoding, this.offset, (this.offset += length)) +} + +Connection.prototype.readBytes = function (buffer, length) { + return buffer.slice(this.offset, (this.offset += length)) +} + +Connection.prototype.parseCString = function (buffer) { + var start = this.offset + var end = buffer.indexOf(0, start) + this.offset = end + 1 + return buffer.toString(this.encoding, start, end) +} +// end parsing methods +module.exports = Connection diff --git a/packages/pg/lib/result.js b/packages/pg/lib/result.js index 088298bc4..7e59a413e 100644 --- a/packages/pg/lib/result.js +++ b/packages/pg/lib/result.js @@ -16,9 +16,9 @@ var Result = function (rowMode, types) { this.command = null this.rowCount = null this.oid = null - this.rows = [] - this.fields = [] - this._parsers = [] + this.rows = []; + this.fields = undefined; + this._parsers = undefined; this._types = types this.RowCtor = null this.rowAsArray = rowMode === 'array' @@ -53,13 +53,13 @@ Result.prototype.addCommandComplete = function (msg) { } Result.prototype._parseRowAsArray = function (rowData) { - var row = [] + var row = new Array(rowData.length) for (var i = 0, len = rowData.length; i < len; i++) { var rawValue = rowData[i] if (rawValue !== null) { - row.push(this._parsers[i](rawValue)) + row[i] = this._parsers[i](rawValue) } else { - row.push(null) + row[i] = null } } return row @@ -88,15 +88,17 @@ Result.prototype.addFields = function (fieldDescriptions) { // multiple query statements in 1 action can result in multiple sets // of rowDescriptions...eg: 'select NOW(); select 1::int;' // you need to reset the fields + this.fields = fieldDescriptions; if (this.fields.length) { - this.fields = [] - this._parsers = [] + this._parsers = new Array(fieldDescriptions.length); } for (var i = 0; i < fieldDescriptions.length; i++) { var desc = fieldDescriptions[i] - this.fields.push(desc) - var parser = (this._types || types).getTypeParser(desc.dataTypeID, desc.format || 'text') - this._parsers.push(parser) + if (this._types) { + this._parsers[i] = this._types.getTypeParser(desc.dataTypeID, desc.format || 'text'); + } else { + this._parsers[i] = types.getTypeParser(desc.dataTypeID, desc.format || 'text') + } } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 951e42df6..e254afba8 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -22,6 +22,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "0.1.3", + "pg-packet-stream": "^1.0.0", "pg-pool": "^2.0.7", "pg-types": "^2.1.0", "pgpass": "1.x", diff --git a/packages/pg/test/integration/client/api-tests.js b/packages/pg/test/integration/client/api-tests.js index c274bbd36..dab923505 100644 --- a/packages/pg/test/integration/client/api-tests.js +++ b/packages/pg/test/integration/client/api-tests.js @@ -4,6 +4,38 @@ var pg = helper.pg var suite = new helper.Suite() +suite.test('null and undefined are both inserted as NULL', function (done) { + const pool = new pg.Pool() + pool.connect( + assert.calls(function (err, client, release) { + assert(!err) + client.query( + 'CREATE TEMP TABLE my_nulls(a varchar(1), b varchar(1), c integer, d integer, e date, f date)' + ) + client.query( + 'INSERT INTO my_nulls(a,b,c,d,e,f) VALUES ($1,$2,$3,$4,$5,$6)', + [null, undefined, null, undefined, null, undefined] + ) + client.query( + 'SELECT * FROM my_nulls', + assert.calls(function (err, result) { + console.log(err) + assert.ifError(err) + assert.equal(result.rows.length, 1) + assert.isNull(result.rows[0].a) + assert.isNull(result.rows[0].b) + assert.isNull(result.rows[0].c) + assert.isNull(result.rows[0].d) + assert.isNull(result.rows[0].e) + assert.isNull(result.rows[0].f) + pool.end(done) + release() + }) + ) + }) + ) +}) + suite.test('pool callback behavior', done => { // test weird callback behavior with node-pool const pool = new pg.Pool() @@ -16,7 +48,7 @@ suite.test('pool callback behavior', done => { }) suite.test('query timeout', (cb) => { - const pool = new pg.Pool({query_timeout: 1000}) + const pool = new pg.Pool({ query_timeout: 1000 }) pool.connect().then((client) => { client.query('SELECT pg_sleep(2)', assert.calls(function (err, result) { assert(err) @@ -28,7 +60,7 @@ suite.test('query timeout', (cb) => { }) suite.test('query recover from timeout', (cb) => { - const pool = new pg.Pool({query_timeout: 1000}) + const pool = new pg.Pool({ query_timeout: 1000 }) pool.connect().then((client) => { client.query('SELECT pg_sleep(20)', assert.calls(function (err, result) { assert(err) @@ -46,7 +78,7 @@ suite.test('query recover from timeout', (cb) => { }) suite.test('query no timeout', (cb) => { - const pool = new pg.Pool({query_timeout: 10000}) + const pool = new pg.Pool({ query_timeout: 10000 }) pool.connect().then((client) => { client.query('SELECT pg_sleep(1)', assert.calls(function (err, result) { assert(!err) @@ -131,18 +163,18 @@ suite.test('raises error if cannot connect', function () { suite.test('query errors are handled and do not bubble if callback is provided', function (done) { const pool = new pg.Pool() pool.connect( - assert.calls(function (err, client, release) { - assert(!err) - client.query( - 'SELECT OISDJF FROM LEIWLISEJLSE', - assert.calls(function (err, result) { - assert.ok(err) - release() - pool.end(done) - }) - ) - }) - ) + assert.calls(function (err, client, release) { + assert(!err) + client.query( + 'SELECT OISDJF FROM LEIWLISEJLSE', + assert.calls(function (err, result) { + assert.ok(err) + release() + pool.end(done) + }) + ) + }) + ) } ) @@ -216,34 +248,3 @@ suite.test('can provide callback and config and parameters', function (done) { }) ) }) - -suite.test('null and undefined are both inserted as NULL', function (done) { - const pool = new pg.Pool() - pool.connect( - assert.calls(function (err, client, release) { - assert(!err) - client.query( - 'CREATE TEMP TABLE my_nulls(a varchar(1), b varchar(1), c integer, d integer, e date, f date)' - ) - client.query( - 'INSERT INTO my_nulls(a,b,c,d,e,f) VALUES ($1,$2,$3,$4,$5,$6)', - [null, undefined, null, undefined, null, undefined] - ) - client.query( - 'SELECT * FROM my_nulls', - assert.calls(function (err, result) { - assert(!err) - assert.equal(result.rows.length, 1) - assert.isNull(result.rows[0].a) - assert.isNull(result.rows[0].b) - assert.isNull(result.rows[0].c) - assert.isNull(result.rows[0].d) - assert.isNull(result.rows[0].e) - assert.isNull(result.rows[0].f) - pool.end(done) - release() - }) - ) - }) - ) -}) diff --git a/yarn.lock b/yarn.lock index 110a8dc72..cd374263a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -831,6 +831,11 @@ dependencies: "@types/node" ">= 8" +"@types/chai@^4.2.7": + version "4.2.7" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.7.tgz#1c8c25cbf6e59ffa7d6b9652c78e547d9a41692d" + integrity sha512-luq8meHGYwvky0O7u0eQZdA7B4Wd9owUCqvbw2m3XCrCU8mplYOujMBbvyS547AxJkC+pGnd0Cm15eNxEUNU8g== + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" @@ -850,7 +855,12 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/node@*", "@types/node@>= 8": +"@types/mocha@^5.2.7": + version "5.2.7" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" + integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== + +"@types/node@*", "@types/node@>= 8", "@types/node@^12.12.21": version "12.12.21" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.21.tgz#aa44a6363291c7037111c47e4661ad210aded23f" integrity sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA== @@ -985,6 +995,11 @@ are-we-there-yet@~1.1.2: delegates "^1.0.0" readable-stream "^2.0.6" +arg@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.2.tgz#e70c90579e02c63d80e3ad4e31d8bfdb8bd50064" + integrity sha512-+ytCkGcBtHZ3V2r2Z06AncYO8jz46UEamcspGoU8lHcEbpn6J77QK0vdWvChsclg/tM5XIJC5tnjmPp7Eq6Obg== + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -1077,6 +1092,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -1318,6 +1338,18 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= +chai@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" + integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + pathval "^1.1.0" + type-detect "^4.0.5" + chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1332,11 +1364,21 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= + chownr@^1.1.1, chownr@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== +chunky@^0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/chunky/-/chunky-0.0.0.tgz#1e7580a23c083897d2ad662459e7efd8465f608a" + integrity sha1-HnWAojwIOJfSrWYkWefv2EZfYIo= + ci-info@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" @@ -1713,6 +1755,13 @@ dedent@^0.7.0: resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" integrity sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw= +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" @@ -1787,6 +1836,11 @@ diff@3.5.0: resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== +diff@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff" + integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q== + dir-glob@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" @@ -2416,6 +2470,11 @@ get-caller-file@^2.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= + get-pkg-repo@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/get-pkg-repo/-/get-pkg-repo-1.4.0.tgz#c73b489c06d80cc5536c2c853f9e05232056972d" @@ -3388,6 +3447,11 @@ make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" +make-error@^1.1.1: + version "1.3.5" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" + integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== + make-fetch-happen@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/make-fetch-happen/-/make-fetch-happen-5.0.2.tgz#aa8387104f2687edca01c8687ee45013d02d19bd" @@ -4202,6 +4266,11 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" +pathval@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" + integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -4886,6 +4955,14 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" +source-map-support@^0.5.6: + version "0.5.16" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" + integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" @@ -4896,7 +4973,7 @@ source-map@^0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -5297,6 +5374,17 @@ trim-off-newlines@^1.0.0: resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM= +ts-node@^8.5.4: + version "8.5.4" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.5.4.tgz#a152add11fa19c221d0b48962c210cf467262ab2" + integrity sha512-izbVCRV68EasEPQ8MSIGBNK9dc/4sYJJKYA+IarMQct1RtEot6Xp0bXuClsbUSnKpg50ho+aOAx8en5c+y4OFw== + dependencies: + arg "^4.1.0" + diff "^4.0.1" + make-error "^1.1.1" + source-map-support "^0.5.6" + yn "^3.0.0" + tslib@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" @@ -5321,6 +5409,11 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" @@ -5336,6 +5429,11 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= +typescript@^3.7.3: + version "3.7.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69" + integrity sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw== + uglify-js@^3.1.4: version "3.7.2" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.2.tgz#cb1a601e67536e9ed094a92dd1e333459643d3f9" @@ -5659,3 +5757,8 @@ yargs@^14.2.2: which-module "^2.0.0" y18n "^4.0.0" yargs-parser "^15.0.0" + +yn@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From d2cad384520458674e56c396a8f1afa28f7b9fe5 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 19 Dec 2019 07:39:04 -0600 Subject: [PATCH 0539/1037] Dont use experimental parser yet --- packages/pg/bench.js | 1 + packages/pg/lib/connection-fast.js | 46 +++++++++++++++++++++--------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/packages/pg/bench.js b/packages/pg/bench.js index b650177e2..7a7084aee 100644 --- a/packages/pg/bench.js +++ b/packages/pg/bench.js @@ -36,6 +36,7 @@ const run = async () => { const queries = await bench(client, seconds * 1000); console.log("queries:", queries); console.log("qps", queries / seconds); + console.log("on my laptop best so far seen 713 qps") await client.end(); }; diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index 5ad38f166..aea9eacd4 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -15,8 +15,6 @@ var Writer = require('buffer-writer') var Reader = require('packet-reader') var PacketStream = require('pg-packet-stream') -console.log(PacketStream.hello()) - var TEXT_MODE = 0 var BINARY_MODE = 1 console.log('using faster connection') @@ -122,25 +120,45 @@ Connection.prototype.connect = function (port, host) { Connection.prototype.attachListeners = function (stream) { var self = this - const mode = this._mode === TEXT_MODE ? 'text' : 'binary'; - const packetStream = new PacketStream.PgPacketStream({ mode }) - packetStream.on('message', (msg) => { - self.emit(msg.name, msg) - }) - stream.pipe(packetStream).on('data', (packet) => { - // console.log('buff', packet) - var msg = self.parseMessage(packet) - var eventName = msg.name === 'error' ? 'errorMessage' : msg.name - if (self._emitMessage) { - self.emit('message', msg) + stream.on('data', function (buff) { + self._reader.addChunk(buff) + var packet = self._reader.read() + while (packet) { + var msg = self.parseMessage({ code: self._reader.header, length: packet.length + 4, buffer: packet }) + var eventName = msg.name === 'error' ? 'errorMessage' : msg.name + if (self._emitMessage) { + self.emit('message', msg) + } + self.emit(eventName, msg) + packet = self._reader.read() } - self.emit(eventName, msg) }) stream.on('end', function () { self.emit('end') }) } +// Connection.prototype.attachListeners = function (stream) { +// var self = this +// const mode = this._mode === TEXT_MODE ? 'text' : 'binary'; +// const packetStream = new PacketStream.PgPacketStream({ mode }) +// packetStream.on('message', (msg) => { +// self.emit(msg.name, msg) +// }) +// stream.pipe(packetStream).on('data', (packet) => { +// // console.log('buff', packet) +// var msg = self.parseMessage(packet) +// var eventName = msg.name === 'error' ? 'errorMessage' : msg.name +// if (self._emitMessage) { +// self.emit('message', msg) +// } +// self.emit(eventName, msg) +// }) +// stream.on('end', function () { +// self.emit('end') +// }) +// } + Connection.prototype.requestSsl = function () { var bodyBuffer = this.writer .addInt16(0x04d2) From 5edcfcb68d62ad2784f981e39de287ae06b5c069 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 19 Dec 2019 08:13:17 -0600 Subject: [PATCH 0540/1037] Add yarn.lock file --- yarn.lock | 1688 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1688 insertions(+) create mode 100644 yarn.lock diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 000000000..5bdbcbacd --- /dev/null +++ b/yarn.lock @@ -0,0 +1,1688 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= + dependencies: + acorn "^3.0.4" + +acorn-to-esprima@^2.0.6, acorn-to-esprima@^2.0.8: + version "2.0.8" + resolved "https://registry.yarnpkg.com/acorn-to-esprima/-/acorn-to-esprima-2.0.8.tgz#003f0c642eb92132f417d3708f14ada82adf2eb1" + integrity sha1-AD8MZC65ITL0F9NwjxStqCrfLrE= + +acorn@^3.0.4, acorn@^3.1.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= + +ajv-keywords@^1.0.0: + version "1.5.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" + integrity sha1-MU3QpLM2j609/NxU7eYXG4htrzw= + +ajv@^4.7.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" + integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY= + dependencies: + co "^4.6.0" + json-stable-stringify "^1.0.1" + +ansi-escapes@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" + integrity sha1-06ioOzGapneTZisT52HHkRQiMG4= + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-styles@^2.0.1, ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +babel-code-frame@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-messages@^6.23.0: + version "6.23.0" + resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" + integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= + dependencies: + babel-runtime "^6.22.0" + +babel-runtime@^6.22.0, babel-runtime@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" + integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= + dependencies: + core-js "^2.4.0" + regenerator-runtime "^0.11.0" + +babel-traverse@^6.4.5, babel-traverse@^6.9.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" + integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= + dependencies: + babel-code-frame "^6.26.0" + babel-messages "^6.23.0" + babel-runtime "^6.26.0" + babel-types "^6.26.0" + babylon "^6.18.0" + debug "^2.6.8" + globals "^9.18.0" + invariant "^2.2.2" + lodash "^4.17.4" + +babel-types@^6.26.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" + integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= + dependencies: + babel-runtime "^6.26.0" + esutils "^2.0.2" + lodash "^4.17.4" + to-fast-properties "^1.0.3" + +babylon@6.14.1: + version "6.14.1" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.14.1.tgz#956275fab72753ad9b3435d7afe58f8bf0a29815" + integrity sha1-lWJ1+rcnU62bNDXXr+WPi/CimBU= + +babylon@^6.18.0, babylon@^6.8.0: + version "6.18.0" + resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" + integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +bluebird@3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.1.tgz#b731ddf48e2dd3bedac2e75e1215a11bcb91fa07" + integrity sha1-tzHd9I4t077awudeEhWhG8uR+gc= + +bluebird@^3.0.5: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +buffer-writer@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" + integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== + +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= + dependencies: + callsites "^0.2.0" + +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= + +chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== + +cli-cursor@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" + integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc= + dependencies: + restore-cursor "^1.0.1" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + +clone@^1.0.2: + version "1.0.4" + resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" + integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= + +co@4.6.0, co@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" + integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +commander@2.15.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== + +commander@^2.2.0, commander@^2.9.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.4.6, concat-stream@^1.4.7: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +config-chain@~1.1.5: + version "1.1.12" + resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" + integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== + dependencies: + ini "^1.3.4" + proto-list "~1.2.1" + +core-js@^2.4.0: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +d@1, d@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" + integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== + dependencies: + es5-ext "^0.10.50" + type "^1.0.1" + +debug-log@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" + integrity sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8= + +debug@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" + integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== + dependencies: + ms "2.0.0" + +debug@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39" + integrity sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk= + +debug@^2.1.1, debug@^2.1.3, debug@^2.6.8: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +deep-is@~0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= + +defaults@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" + integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= + dependencies: + clone "^1.0.2" + +deglob@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/deglob/-/deglob-1.1.2.tgz#76d577c25fe3f7329412a2b59eadea57ac500e3f" + integrity sha1-dtV3wl/j9zKUEqK1nq3qV6xQDj8= + dependencies: + find-root "^1.0.0" + glob "^7.0.5" + ignore "^3.0.9" + pkg-config "^1.1.0" + run-parallel "^1.1.2" + uniq "^1.0.1" + xtend "^4.0.0" + +diff@3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" + integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== + +diff@^1.3.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" + integrity sha1-fyjS657nsVqX79ic5j3P2qPMur8= + +disparity@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/disparity/-/disparity-2.0.0.tgz#57ddacb47324ae5f58d2cc0da886db4ce9eeb718" + integrity sha1-V92stHMkrl9Y0swNqIbbTOnutxg= + dependencies: + ansi-styles "^2.0.1" + diff "^1.3.2" + +doctrine@^1.2.1, doctrine@^1.2.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + +editorconfig@^0.13.2: + version "0.13.3" + resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.13.3.tgz#e5219e587951d60958fd94ea9a9a008cdeff1b34" + integrity sha512-WkjsUNVCu+ITKDj73QDvi0trvpdDWdkDyHybDGSXPfekLCqwmpD7CP7iPbvBgosNuLcI96XTDwNa75JyFl7tEQ== + dependencies: + bluebird "^3.0.5" + commander "^2.9.0" + lru-cache "^3.2.0" + semver "^5.1.0" + sigmund "^1.0.1" + +es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@~0.10.14: + version "0.10.53" + resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" + integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== + dependencies: + es6-iterator "~2.0.3" + es6-symbol "~3.1.3" + next-tick "~1.0.0" + +es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" + integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= + dependencies: + d "1" + es5-ext "^0.10.35" + es6-symbol "^3.1.1" + +es6-map@^0.1.3: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" + integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-set "~0.1.5" + es6-symbol "~3.1.1" + event-emitter "~0.3.5" + +es6-set@~0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" + integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= + dependencies: + d "1" + es5-ext "~0.10.14" + es6-iterator "~2.0.1" + es6-symbol "3.1.1" + event-emitter "~0.3.5" + +es6-symbol@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" + integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= + dependencies: + d "1" + es5-ext "~0.10.14" + +es6-symbol@^3.1.1, es6-symbol@~3.1.1, es6-symbol@~3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" + integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== + dependencies: + d "^1.0.1" + ext "^1.1.2" + +es6-weak-map@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" + integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== + dependencies: + d "1" + es5-ext "^0.10.46" + es6-iterator "^2.0.3" + es6-symbol "^3.1.1" + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escope@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" + integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= + dependencies: + es6-map "^0.1.3" + es6-weak-map "^2.0.1" + esrecurse "^4.1.0" + estraverse "^4.1.1" + +esformatter-eol-last@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esformatter-eol-last/-/esformatter-eol-last-1.0.0.tgz#45a78ff4622b1d49e44f56b49905766a63290c07" + integrity sha1-RaeP9GIrHUnkT1a0mQV2amMpDAc= + dependencies: + string.prototype.endswith "^0.2.0" + +esformatter-ignore@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/esformatter-ignore/-/esformatter-ignore-0.1.3.tgz#04d3b875bfa49dde004cc58df6f6bbc3c0567f1e" + integrity sha1-BNO4db+knd4ATMWN9va7w8BWfx4= + +esformatter-jsx@^7.0.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/esformatter-jsx/-/esformatter-jsx-7.4.1.tgz#b2209ae0908f413a747b1205727cbf4ba4249602" + integrity sha1-siCa4JCPQTp0exIFcny/S6QklgI= + dependencies: + babylon "6.14.1" + esformatter-ignore "^0.1.3" + extend "3.0.0" + js-beautify "1.6.4" + +esformatter-literal-notation@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/esformatter-literal-notation/-/esformatter-literal-notation-1.0.1.tgz#710e7b420175fe3f7e5afad5bbad329103842e2f" + integrity sha1-cQ57QgF1/j9+WvrVu60ykQOELi8= + dependencies: + rocambole "^0.3.6" + rocambole-token "^1.2.1" + +esformatter-parser@^1.0, esformatter-parser@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/esformatter-parser/-/esformatter-parser-1.0.0.tgz#0854072d0487539ed39cae38d8a5432c17ec11d3" + integrity sha1-CFQHLQSHU57TnK442KVDLBfsEdM= + dependencies: + acorn-to-esprima "^2.0.8" + babel-traverse "^6.9.0" + babylon "^6.8.0" + rocambole "^0.7.0" + +esformatter-quotes@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/esformatter-quotes/-/esformatter-quotes-1.1.0.tgz#e22c6c445c7f306041d81c9b9e51fca6cbfaca82" + integrity sha1-4ixsRFx/MGBB2BybnlH8psv6yoI= + +esformatter-remove-trailing-commas@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/esformatter-remove-trailing-commas/-/esformatter-remove-trailing-commas-1.0.1.tgz#9397624c1faa980fc4ecc7e5e9813eb4f2b582a7" + integrity sha1-k5diTB+qmA/E7Mfl6YE+tPK1gqc= + dependencies: + rocambole-token "^1.2.1" + +esformatter-semicolon-first@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/esformatter-semicolon-first/-/esformatter-semicolon-first-1.2.0.tgz#e3b512d1d4e07310eabcabf57277ea7c8a56e242" + integrity sha1-47US0dTgcxDqvKv1cnfqfIpW4kI= + dependencies: + esformatter-parser "^1.0" + rocambole ">=0.6.0 <2.0" + rocambole-linebreak "^1.0.2" + rocambole-token "^1.2.1" + +esformatter-spaced-lined-comment@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/esformatter-spaced-lined-comment/-/esformatter-spaced-lined-comment-2.0.1.tgz#dc5f3407f93c295e1e56446bd344560da5e6dcac" + integrity sha1-3F80B/k8KV4eVkRr00RWDaXm3Kw= + +esformatter@^0.9.0: + version "0.9.6" + resolved "https://registry.yarnpkg.com/esformatter/-/esformatter-0.9.6.tgz#3608aec7828deee3cd3f46e1192aeb47268a957f" + integrity sha1-Ngiux4KN7uPNP0bhGSrrRyaKlX8= + dependencies: + acorn-to-esprima "^2.0.6" + babel-traverse "^6.4.5" + debug "^0.7.4" + disparity "^2.0.0" + esformatter-parser "^1.0.0" + glob "^5.0.3" + minimist "^1.1.1" + mout ">=0.9 <2.0" + npm-run "^2.0.0" + resolve "^1.1.5" + rocambole ">=0.7 <2.0" + rocambole-indent "^2.0.4" + rocambole-linebreak "^1.0.2" + rocambole-node "~1.0" + rocambole-token "^1.1.2" + rocambole-whitespace "^1.0.0" + stdin "*" + strip-json-comments "~0.1.1" + supports-color "^1.3.1" + user-home "^2.0.0" + +eslint-config-standard-jsx@1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-standard-jsx/-/eslint-config-standard-jsx-1.2.1.tgz#0d19b1705f0ad48363ef2a8bbfa71df012d989b3" + integrity sha1-DRmxcF8K1INj7yqLv6cd8BLZibM= + +eslint-config-standard@5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-5.3.1.tgz#591c969151744132f561d3b915a812ea413fe490" + integrity sha1-WRyWkVF0QTL1YdO5FagS6kE/5JA= + +eslint-plugin-promise@^1.0.8: + version "1.3.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-1.3.2.tgz#fce332d6f5ff523200a537704863ec3c2422ba7c" + integrity sha1-/OMy1vX/UjIApTdwSGPsPCQiunw= + +eslint-plugin-react@^5.0.1: + version "5.2.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-5.2.2.tgz#7db068e1f5487f6871e4deef36a381c303eac161" + integrity sha1-fbBo4fVIf2hx5N7vNqOBwwPqwWE= + dependencies: + doctrine "^1.2.2" + jsx-ast-utils "^1.2.1" + +eslint-plugin-standard@^1.3.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-1.3.3.tgz#a3085451523431e76f409c70cb8f94e32bf0ec7f" + integrity sha1-owhUUVI0MedvQJxwy4+U4yvw7H8= + +eslint@~2.10.2: + version "2.10.2" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-2.10.2.tgz#b2309482fef043d3203365a321285e6cce01c3d7" + integrity sha1-sjCUgv7wQ9MgM2WjIShebM4Bw9c= + dependencies: + chalk "^1.1.3" + concat-stream "^1.4.6" + debug "^2.1.1" + doctrine "^1.2.1" + es6-map "^0.1.3" + escope "^3.6.0" + espree "3.1.4" + estraverse "^4.2.0" + esutils "^2.0.2" + file-entry-cache "^1.1.1" + glob "^7.0.3" + globals "^9.2.0" + ignore "^3.1.2" + imurmurhash "^0.1.4" + inquirer "^0.12.0" + is-my-json-valid "^2.10.0" + is-resolvable "^1.0.0" + js-yaml "^3.5.1" + json-stable-stringify "^1.0.0" + lodash "^4.0.0" + mkdirp "^0.5.0" + optionator "^0.8.1" + path-is-absolute "^1.0.0" + path-is-inside "^1.0.1" + pluralize "^1.2.1" + progress "^1.1.8" + require-uncached "^1.0.2" + shelljs "^0.6.0" + strip-json-comments "~1.0.1" + table "^3.7.8" + text-table "~0.2.0" + user-home "^2.0.0" + +espree@3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.1.4.tgz#0726d7ac83af97a7c8498da9b363a3609d2a68a1" + integrity sha1-BybXrIOvl6fISY2ps2OjYJ0qaKE= + dependencies: + acorn "^3.1.0" + acorn-jsx "^3.0.0" + +esprima@^2.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esprima@~1.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad" + integrity sha1-n1V+CPw7TSbs6d00+Pv0drYlha0= + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +event-emitter@~0.3.5: + version "0.3.5" + resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" + integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= + dependencies: + d "1" + es5-ext "~0.10.14" + +exit-hook@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" + integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= + +expect.js@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/expect.js/-/expect.js-0.3.1.tgz#b0a59a0d2eff5437544ebf0ceaa6015841d09b5b" + integrity sha1-sKWaDS7/VDdUTr8M6qYBWEHQm1s= + +ext@^1.1.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" + integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== + dependencies: + type "^2.0.0" + +extend@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" + integrity sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ= + +fast-levenshtein@~2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + +figures@^1.3.5: + version "1.7.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" + integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= + dependencies: + escape-string-regexp "^1.0.5" + object-assign "^4.1.0" + +file-entry-cache@^1.1.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-1.3.1.tgz#44c61ea607ae4be9c1402f41f44270cbfe334ff8" + integrity sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g= + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + +find-root@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" + integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== + +flat-cache@^1.2.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" + integrity sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg== + dependencies: + circular-json "^0.3.1" + graceful-fs "^4.1.2" + rimraf "~2.6.2" + write "^0.2.1" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +generate-function@^2.0.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" + integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== + dependencies: + is-property "^1.0.2" + +generate-object-property@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" + integrity sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA= + dependencies: + is-property "^1.0.0" + +get-stdin@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" + integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= + +get-stdin@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" + integrity sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g= + +glob@7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^5.0.3: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + +glob@^7.0.3, glob@^7.0.5, glob@^7.1.3: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^9.18.0, globals@^9.2.0: + version "9.18.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" + integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== + +graceful-fs@^4.1.2: + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= + +ignore@^3.0.9, ignore@^3.1.2: + version "3.3.10" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +inquirer@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" + integrity sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34= + dependencies: + ansi-escapes "^1.1.0" + ansi-regex "^2.0.0" + chalk "^1.0.0" + cli-cursor "^1.0.1" + cli-width "^2.0.0" + figures "^1.3.5" + lodash "^4.3.0" + readline2 "^1.0.1" + run-async "^0.1.0" + rx-lite "^3.1.2" + string-width "^1.0.1" + strip-ansi "^3.0.0" + through "^2.3.6" + +invariant@^2.2.2: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-my-ip-valid@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" + integrity sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ== + +is-my-json-valid@^2.10.0: + version "2.20.0" + resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz#1345a6fca3e8daefc10d0fa77067f54cedafd59a" + integrity sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA== + dependencies: + generate-function "^2.0.0" + generate-object-property "^1.1.0" + is-my-ip-valid "^1.0.0" + jsonpointer "^4.0.0" + xtend "^4.0.0" + +is-property@^1.0.0, is-property@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= + +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== + +isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +js-beautify@1.6.4: + version "1.6.4" + resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.6.4.tgz#a9af79699742ac9a1b6fddc1fdbc78bc4d515fc3" + integrity sha1-qa95aZdCrJobb93B/bx4vE1RX8M= + dependencies: + config-chain "~1.1.5" + editorconfig "^0.13.2" + mkdirp "~0.5.0" + nopt "~3.0.1" + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + +js-yaml@^3.5.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" + integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= + dependencies: + jsonify "~0.0.0" + +jsonify@~0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" + integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= + +jsonpointer@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" + integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk= + +jsx-ast-utils@^1.2.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1" + integrity sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE= + +levn@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" + integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= + dependencies: + prelude-ls "~1.1.2" + type-check "~0.3.2" + +lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.3.0: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +loose-envify@^1.0.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru-cache@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" + integrity sha1-cXibO39Tmb7IVl3aOKow0qCX7+4= + dependencies: + pseudomap "^1.0.1" + +"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@^1.1.0, minimist@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +mocha@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== + dependencies: + browser-stdout "1.3.1" + commander "2.15.1" + debug "3.1.0" + diff "3.5.0" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.5" + he "1.1.1" + minimatch "3.0.4" + mkdirp "0.5.1" + supports-color "5.4.0" + +"mout@>=0.9 <2.0": + version "1.2.2" + resolved "https://registry.yarnpkg.com/mout/-/mout-1.2.2.tgz#c9b718a499806a0632cede178e80f436259e777d" + integrity sha512-w0OUxFEla6z3d7sVpMZGBCpQvYh8PHS1wZ6Wu9GNKHMpAHWJ0if0LsQZh3DlOqw55HlhJEOMLpFnwtxp99Y5GA== + +mout@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/mout/-/mout-0.11.1.tgz#ba3611df5f0e5b1ffbfd01166b8f02d1f5fa2b99" + integrity sha1-ujYR318OWx/7/QEWa48C0fX6K5k= + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +multiline@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/multiline/-/multiline-1.0.2.tgz#69b1f25ff074d2828904f244ddd06b7d96ef6c93" + integrity sha1-abHyX/B00oKJBPJE3dBrfZbvbJM= + dependencies: + strip-indent "^1.0.0" + +mute-stream@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" + integrity sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA= + +next-tick@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" + integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= + +nopt@~3.0.1: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= + dependencies: + abbrev "1" + +npm-path@^1.0.0, npm-path@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-1.1.0.tgz#0474ae00419c327d54701b7cf2cd05dc88be1140" + integrity sha1-BHSuAEGcMn1UcBt88s0F3Ii+EUA= + dependencies: + which "^1.2.4" + +npm-run@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/npm-run/-/npm-run-2.0.0.tgz#28dfc0ad5e2e46fe0848e2bd58ddf002e7b73c15" + integrity sha1-KN/ArV4uRv4ISOK9WN3wAue3PBU= + dependencies: + minimist "^1.1.1" + npm-path "^1.0.1" + npm-which "^2.0.0" + serializerr "^1.0.1" + spawn-sync "^1.0.5" + sync-exec "^0.5.0" + +npm-which@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-2.0.0.tgz#0c46982160b783093661d1d01bd4496d2feabbac" + integrity sha1-DEaYIWC3gwk2YdHQG9RJbS/qu6w= + dependencies: + commander "^2.2.0" + npm-path "^1.0.0" + which "^1.0.5" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +object-assign@^4.0.1, object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" + integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= + +optionator@^0.8.1: + version "0.8.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" + integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== + dependencies: + deep-is "~0.1.3" + fast-levenshtein "~2.0.6" + levn "~0.3.0" + prelude-ls "~1.1.2" + type-check "~0.3.2" + word-wrap "~1.2.3" + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-shim@^0.1.2: + version "0.1.3" + resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917" + integrity sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc= + +packet-reader@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" + integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-is-inside@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +pg-connection-string@0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" + integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc= + +pg-cursor@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/pg-cursor/-/pg-cursor-1.3.0.tgz#b220f1908976b7b40daa373c7ada5fca823ab0d9" + integrity sha1-siDxkIl2t7QNqjc8etpfyoI6sNk= + +pg-int8@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" + integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== + +pg-pool@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.7.tgz#f14ecab83507941062c313df23f6adcd9fd0ce54" + integrity sha512-UiJyO5B9zZpu32GSlP0tXy8J2NsJ9EFGFfz5v6PSbdz/1hBLX1rNiiy5+mAm5iJJYwfCv4A0EBcQLGWwjbpzZw== + +pg-types@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" + integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== + dependencies: + pg-int8 "1.0.1" + postgres-array "~2.0.0" + postgres-bytea "~1.0.0" + postgres-date "~1.0.4" + postgres-interval "^1.1.0" + +pg@*: + version "7.15.1" + resolved "https://registry.yarnpkg.com/pg/-/pg-7.15.1.tgz#a0bac84ebaeb809f3a369fb695ae89b314b08b22" + integrity sha512-o293Pxx5bNRpTv3Dh4+IIhPbTw19Bo4zvppLgR+MAV2I7AF3sMr9gPB4JPvBffWb24pDfC+7Ghe6xh2VxVMBpQ== + dependencies: + buffer-writer "2.0.0" + packet-reader "1.0.0" + pg-connection-string "0.1.3" + pg-pool "^2.0.7" + pg-types "^2.1.0" + pgpass "1.x" + semver "4.3.2" + +pgpass@1.x: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" + integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY= + dependencies: + split "^1.0.0" + +pkg-config@^1.0.1, pkg-config@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pkg-config/-/pkg-config-1.1.1.tgz#557ef22d73da3c8837107766c52eadabde298fe4" + integrity sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q= + dependencies: + debug-log "^1.0.0" + find-root "^1.0.0" + xtend "^4.0.1" + +pluralize@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" + integrity sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU= + +postgres-array@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" + integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== + +postgres-bytea@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" + integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU= + +postgres-date@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.4.tgz#1c2728d62ef1bff49abdd35c1f86d4bdf118a728" + integrity sha512-bESRvKVuTrjoBluEcpv2346+6kgB7UlnqWZsnbnCccTNq/pqfj1j6oBaN5+b/NrDXepYUT/HKadqv3iS9lJuVA== + +postgres-interval@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" + integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== + dependencies: + xtend "^4.0.0" + +prelude-ls@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" + integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +progress@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" + integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74= + +proto-list@~1.2.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" + integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= + +protochain@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/protochain/-/protochain-1.0.5.tgz#991c407e99de264aadf8f81504b5e7faf7bfa260" + integrity sha1-mRxAfpneJkqt+PgVBLXn+ve/omA= + +pseudomap@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + +readable-stream@^2.2.2: + version "2.3.6" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" + integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readline2@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" + integrity sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + mute-stream "0.0.5" + +regenerator-runtime@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" + integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== + +repeat-string@^1.5.0: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +require-uncached@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= + +resolve@^1.1.5: + version "1.14.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.1.tgz#9e018c540fcf0c427d678b9931cbf45e984bcaff" + integrity sha512-fn5Wobh4cxbLzuHaE+nphztHy43/b++4M6SsGFC2gB8uYwf0C8LcarfCz1un7UTW8OFQg9iNjZ4xpcFVGebDPg== + dependencies: + path-parse "^1.0.6" + +restore-cursor@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" + integrity sha1-NGYfRohjJ/7SmRR5FSJS35LapUE= + dependencies: + exit-hook "^1.0.0" + onetime "^1.0.0" + +rimraf@~2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== + dependencies: + glob "^7.1.3" + +rocambole-indent@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/rocambole-indent/-/rocambole-indent-2.0.4.tgz#a18a24977ca0400b861daa4631e861dcb52d085c" + integrity sha1-oYokl3ygQAuGHapGMehh3LUtCFw= + dependencies: + debug "^2.1.3" + mout "^0.11.0" + rocambole-token "^1.2.1" + +rocambole-linebreak@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/rocambole-linebreak/-/rocambole-linebreak-1.0.2.tgz#03621515b43b4721c97e5a1c1bca5a0366368f2f" + integrity sha1-A2IVFbQ7RyHJflocG8paA2Y2jy8= + dependencies: + debug "^2.1.3" + rocambole-token "^1.2.1" + semver "^4.3.1" + +rocambole-node@~1.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rocambole-node/-/rocambole-node-1.0.0.tgz#db5b49de7407b0080dd514872f28e393d0f7ff3f" + integrity sha1-21tJ3nQHsAgN1RSHLyjjk9D3/z8= + +rocambole-token@^1.1.2, rocambole-token@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/rocambole-token/-/rocambole-token-1.2.1.tgz#c785df7428dc3cb27ad7897047bd5238cc070d35" + integrity sha1-x4XfdCjcPLJ614lwR71SOMwHDTU= + +rocambole-whitespace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rocambole-whitespace/-/rocambole-whitespace-1.0.0.tgz#63330949256b29941f59b190459f999c6b1d3bf9" + integrity sha1-YzMJSSVrKZQfWbGQRZ+ZnGsdO/k= + dependencies: + debug "^2.1.3" + repeat-string "^1.5.0" + rocambole-token "^1.2.1" + +"rocambole@>=0.6.0 <2.0", "rocambole@>=0.7 <2.0", rocambole@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/rocambole/-/rocambole-0.7.0.tgz#f6c79505517dc42b6fb840842b8b953b0f968585" + integrity sha1-9seVBVF9xCtvuECEK4uVOw+WhYU= + dependencies: + esprima "^2.1" + +rocambole@^0.3.6: + version "0.3.6" + resolved "https://registry.yarnpkg.com/rocambole/-/rocambole-0.3.6.tgz#4debbf5943144bc7b6006d95be8facc0b74352a7" + integrity sha1-Teu/WUMUS8e2AG2Vvo+swLdDUqc= + dependencies: + esprima "~1.0" + +run-async@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" + integrity sha1-yK1KXhEGYeQCp9IbUw4AnyX444k= + dependencies: + once "^1.3.0" + +run-parallel@^1.1.2: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + +rx-lite@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" + integrity sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI= + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +semver@4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" + integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= + +semver@^4.3.1: + version "4.3.6" + resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" + integrity sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto= + +semver@^5.1.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +serializerr@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/serializerr/-/serializerr-1.0.3.tgz#12d4c5aa1c3ffb8f6d1dc5f395aa9455569c3f91" + integrity sha1-EtTFqhw/+49tHcXzlaqUVVacP5E= + dependencies: + protochain "^1.0.5" + +shelljs@^0.6.0: + version "0.6.1" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8" + integrity sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg= + +sigmund@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" + integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= + +slice-ansi@0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" + integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= + +spawn-sync@^1.0.5: + version "1.0.15" + resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" + integrity sha1-sAeZVX63+wyDdsKdROih6mfldHY= + dependencies: + concat-stream "^1.4.7" + os-shim "^0.1.2" + +split@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" + integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== + dependencies: + through "2" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +standard-engine@^4.0.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/standard-engine/-/standard-engine-4.1.3.tgz#7a31aad54f03d9f39355f43389ce0694f4094155" + integrity sha1-ejGq1U8D2fOTVfQzic4GlPQJQVU= + dependencies: + defaults "^1.0.2" + deglob "^1.0.0" + find-root "^1.0.0" + get-stdin "^5.0.1" + minimist "^1.1.0" + multiline "^1.0.2" + pkg-config "^1.0.1" + xtend "^4.0.0" + +standard-format@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/standard-format/-/standard-format-2.2.4.tgz#b90fb39a635f749cd4fd117fe4730d31179aaeef" + integrity sha1-uQ+zmmNfdJzU/RF/5HMNMRearu8= + dependencies: + deglob "^1.0.0" + esformatter "^0.9.0" + esformatter-eol-last "^1.0.0" + esformatter-jsx "^7.0.0" + esformatter-literal-notation "^1.0.0" + esformatter-quotes "^1.0.0" + esformatter-remove-trailing-commas "^1.0.1" + esformatter-semicolon-first "^1.1.0" + esformatter-spaced-lined-comment "^2.0.0" + minimist "^1.1.0" + stdin "0.0.1" + +standard@7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/standard/-/standard-7.1.2.tgz#40166eeec2405065d1a4f0e3f15babc6e274607e" + integrity sha1-QBZu7sJAUGXRpPDj8VurxuJ0YH4= + dependencies: + eslint "~2.10.2" + eslint-config-standard "5.3.1" + eslint-config-standard-jsx "1.2.1" + eslint-plugin-promise "^1.0.8" + eslint-plugin-react "^5.0.1" + eslint-plugin-standard "^1.3.1" + standard-engine "^4.0.0" + +stdin@*, stdin@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/stdin/-/stdin-0.0.1.tgz#d3041981aaec3dfdbc77a1b38d6372e38f5fb71e" + integrity sha1-0wQZgarsPf28d6GzjWNy449ftx4= + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +string-width@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string.prototype.endswith@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/string.prototype.endswith/-/string.prototype.endswith-0.2.0.tgz#a19c20dee51a98777e9a47e10f09be393b9bba75" + integrity sha1-oZwg3uUamHd+mkfhDwm+OTubunU= + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" + integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= + dependencies: + get-stdin "^4.0.1" + +strip-json-comments@~0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-0.1.3.tgz#164c64e370a8a3cc00c9e01b539e569823f0ee54" + integrity sha1-Fkxk43Coo8wAyeAbU55WmCPw7lQ= + +strip-json-comments@~1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" + integrity sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E= + +supports-color@5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== + dependencies: + has-flag "^3.0.0" + +supports-color@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.3.1.tgz#15758df09d8ff3b4acc307539fabe27095e1042d" + integrity sha1-FXWN8J2P87SswwdTn6vicJXhBC0= + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +sync-exec@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/sync-exec/-/sync-exec-0.5.0.tgz#3f7258e4a5ba17245381909fa6a6f6cf506e1661" + integrity sha1-P3JY5KW6FyRTgZCfpqb2z1BuFmE= + +table@^3.7.8: + version "3.8.3" + resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" + integrity sha1-K7xULw/amGGnVdOUf+/Ys/UThV8= + dependencies: + ajv "^4.7.0" + ajv-keywords "^1.0.0" + chalk "^1.1.1" + lodash "^4.0.0" + slice-ansi "0.0.4" + string-width "^2.0.0" + +text-table@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +through@2, through@^2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +to-fast-properties@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" + integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= + +type-check@~0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" + integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= + dependencies: + prelude-ls "~1.1.2" + +type@^1.0.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" + integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== + +type@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" + integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= + +user-home@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" + integrity sha1-nHC/2Babwdy/SGBODwS4tJzenp8= + dependencies: + os-homedir "^1.0.0" + +util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +which@^1.0.5, which@^1.2.4: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +word-wrap@~1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= + dependencies: + mkdirp "^0.5.1" + +xtend@^4.0.0, xtend@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== From e302c4c6ffc709292e8bbac3d4286a147faf8ed3 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 19 Dec 2019 08:13:27 -0600 Subject: [PATCH 0541/1037] Bump version --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index c1251e748..e1f089f91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "2.0.7", + "version": "2.0.8", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 0609ddbdb..30f2bb2dc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "2.0.7", + "version": "2.0.8", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { From cb96ae2d6e37b1414df405d80258e0e2bafeaba0 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 19 Dec 2019 08:16:52 -0600 Subject: [PATCH 0542/1037] Drop node 4.0 from test matrix --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0deb0216c..db2833db9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,10 +2,6 @@ language: node_js matrix: include: - - node_js: "4" - addons: - postgresql: "9.1" - dist: precise - node_js: "6" addons: postgresql: "9.4" From fa44905b3068ccd289ed7f7ee733d4cd94cc3de9 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 19 Dec 2019 14:33:37 -0600 Subject: [PATCH 0543/1037] port over some tests --- .../src/inbound-parser.test.ts | 477 ++++++++++++++++++ packages/pg-packet-stream/src/index.ts | 338 ++++++++++++- .../src/testing/buffer-list.ts | 75 +++ .../src/testing/test-buffers.ts | 151 ++++++ 4 files changed, 1020 insertions(+), 21 deletions(-) create mode 100644 packages/pg-packet-stream/src/inbound-parser.test.ts create mode 100644 packages/pg-packet-stream/src/testing/buffer-list.ts create mode 100644 packages/pg-packet-stream/src/testing/test-buffers.ts diff --git a/packages/pg-packet-stream/src/inbound-parser.test.ts b/packages/pg-packet-stream/src/inbound-parser.test.ts new file mode 100644 index 000000000..bdfb8a3b1 --- /dev/null +++ b/packages/pg-packet-stream/src/inbound-parser.test.ts @@ -0,0 +1,477 @@ +import buffers from './testing/test-buffers' +import BufferList from './testing/buffer-list' +import { PgPacketStream } from './' +import assert from 'assert' + +var authOkBuffer = buffers.authenticationOk() +var paramStatusBuffer = buffers.parameterStatus('client_encoding', 'UTF8') +var readyForQueryBuffer = buffers.readyForQuery() +var backendKeyDataBuffer = buffers.backendKeyData(1, 2) +var commandCompleteBuffer = buffers.commandComplete('SELECT 3') +var parseCompleteBuffer = buffers.parseComplete() +var bindCompleteBuffer = buffers.bindComplete() +var portalSuspendedBuffer = buffers.portalSuspended() + +var addRow = function (bufferList: BufferList, name: string, offset: number) { + return bufferList.addCString(name) // field name + .addInt32(offset++) // table id + .addInt16(offset++) // attribute of column number + .addInt32(offset++) // objectId of field's data type + .addInt16(offset++) // datatype size + .addInt32(offset++) // type modifier + .addInt16(0) // format code, 0 => text +} + +var row1 = { + name: 'id', + tableID: 1, + attributeNumber: 2, + dataTypeID: 3, + dataTypeSize: 4, + typeModifier: 5, + formatCode: 0 +} +var oneRowDescBuff = buffers.rowDescription([row1]) +row1.name = 'bang' + +var twoRowBuf = buffers.rowDescription([row1, { + name: 'whoah', + tableID: 10, + attributeNumber: 11, + dataTypeID: 12, + dataTypeSize: 13, + typeModifier: 14, + formatCode: 0 +}]) + +var emptyRowFieldBuf = new BufferList() + .addInt16(0) + .join(true, 'D') + +var emptyRowFieldBuf = buffers.dataRow([]) + +var oneFieldBuf = new BufferList() + .addInt16(1) // number of fields + .addInt32(5) // length of bytes of fields + .addCString('test') + .join(true, 'D') + +var oneFieldBuf = buffers.dataRow(['test']) + +var expectedAuthenticationOkayMessage = { + name: 'authenticationOk', + length: 8 +} + +var expectedParameterStatusMessage = { + name: 'parameterStatus', + parameterName: 'client_encoding', + parameterValue: 'UTF8', + length: 25 +} + +var expectedBackendKeyDataMessage = { + name: 'backendKeyData', + processID: 1, + secretKey: 2 +} + +var expectedReadyForQueryMessage = { + name: 'readyForQuery', + length: 5, + status: 'I' +} + +var expectedCommandCompleteMessage = { + name: 'commandComplete', + length: 13, + text: 'SELECT 3' +} +var emptyRowDescriptionBuffer = new BufferList() + .addInt16(0) // number of fields + .join(true, 'T') + +var expectedEmptyRowDescriptionMessage = { + name: 'rowDescription', + length: 6, + fieldCount: 0, + fields: [], +} +var expectedOneRowMessage = { + name: 'rowDescription', + length: 27, + fieldCount: 1, + fields: [{ + name: 'id', + tableID: 1, + columnID: 2, + dataTypeID: 3, + dataTypeSize: 4, + dataTypeModifier: 5, + format: 'text' + }] +} + +var expectedTwoRowMessage = { + name: 'rowDescription', + length: 53, + fieldCount: 2, + fields: [{ + name: 'bang', + tableID: 1, + columnID: 2, + dataTypeID: 3, + dataTypeSize: 4, + dataTypeModifier: 5, + format: 'text' + }, + { + name: 'whoah', + tableID: 10, + columnID: 11, + dataTypeID: 12, + dataTypeSize: 13, + dataTypeModifier: 14, + format: 'text' + }] +} + +var testForMessage = function (buffer: Buffer, expectedMessage: any) { + it('recieves and parses ' + expectedMessage.name, async () => { + const parser = new PgPacketStream(); + + await new Promise((resolve) => { + let lastMessage: any = {} + parser.on('message', function (msg) { + lastMessage = msg + }) + + parser.write(buffer); + + for (const key in expectedMessage) { + assert.deepEqual(lastMessage[key], expectedMessage[key]) + } + resolve(); + }) + }) +} + +var plainPasswordBuffer = buffers.authenticationCleartextPassword() +var md5PasswordBuffer = buffers.authenticationMD5Password() +var SASLBuffer = buffers.authenticationSASL() +var SASLContinueBuffer = buffers.authenticationSASLContinue() +var SASLFinalBuffer = buffers.authenticationSASLFinal() + +var expectedPlainPasswordMessage = { + name: 'authenticationCleartextPassword' +} + +var expectedMD5PasswordMessage = { + name: 'authenticationMD5Password', + salt: Buffer.from([1, 2, 3, 4]) +} + +var expectedSASLMessage = { + name: 'authenticationSASL', + mechanisms: ['SCRAM-SHA-256'] +} + +var expectedSASLContinueMessage = { + name: 'authenticationSASLContinue', + data: 'data', +} + +var expectedSASLFinalMessage = { + name: 'authenticationSASLFinal', + data: 'data', +} + +var notificationResponseBuffer = buffers.notification(4, 'hi', 'boom') +var expectedNotificationResponseMessage = { + name: 'notification', + processId: 4, + channel: 'hi', + payload: 'boom' +} + +describe('PgPacketStream', function () { + testForMessage(authOkBuffer, expectedAuthenticationOkayMessage) + testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage) + testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage) + testForMessage(SASLBuffer, expectedSASLMessage) + testForMessage(SASLContinueBuffer, expectedSASLContinueMessage) + testForMessage(SASLFinalBuffer, expectedSASLFinalMessage) + + testForMessage(paramStatusBuffer, expectedParameterStatusMessage) + testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage) + testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage) + testForMessage(commandCompleteBuffer, expectedCommandCompleteMessage) + testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage) + testForMessage(buffers.emptyQuery(), { + name: 'emptyQuery', + length: 4, + }) + + testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), { + name: 'noData' + }) + + describe('rowDescription messages', function () { + testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage) + testForMessage(oneRowDescBuff, expectedOneRowMessage) + testForMessage(twoRowBuf, expectedTwoRowMessage) + }) + + describe('parsing rows', function () { + describe('parsing empty row', function () { + testForMessage(emptyRowFieldBuf, { + name: 'dataRow', + fieldCount: 0 + }) + }) + + describe('parsing data row with fields', function () { + testForMessage(oneFieldBuf, { + name: 'dataRow', + fieldCount: 1, + fields: ['test'] + }) + }) + }) + + describe('notice message', function () { + // this uses the same logic as error message + var buff = buffers.notice([{ type: 'C', value: 'code' }]) + testForMessage(buff, { + name: 'notice', + code: 'code' + }) + }) + + testForMessage(buffers.error([]), { + name: 'error' + }) + + describe('with all the fields', function () { + var buffer = buffers.error([{ + type: 'S', + value: 'ERROR' + }, { + type: 'C', + value: 'code' + }, { + type: 'M', + value: 'message' + }, { + type: 'D', + value: 'details' + }, { + type: 'H', + value: 'hint' + }, { + type: 'P', + value: '100' + }, { + type: 'p', + value: '101' + }, { + type: 'q', + value: 'query' + }, { + type: 'W', + value: 'where' + }, { + type: 'F', + value: 'file' + }, { + type: 'L', + value: 'line' + }, { + type: 'R', + value: 'routine' + }, { + type: 'Z', // ignored + value: 'alsdkf' + }]) + + testForMessage(buffer, { + name: 'error', + severity: 'ERROR', + code: 'code', + message: 'message', + detail: 'details', + hint: 'hint', + position: '100', + internalPosition: '101', + internalQuery: 'query', + where: 'where', + file: 'file', + line: 'line', + routine: 'routine' + }) + }) + + testForMessage(parseCompleteBuffer, { + name: 'parseComplete' + }) + + testForMessage(bindCompleteBuffer, { + name: 'bindComplete' + }) + + testForMessage(bindCompleteBuffer, { + name: 'bindComplete' + }) + + testForMessage(buffers.closeComplete(), { + name: 'closeComplete' + }) + + describe('parses portal suspended message', function () { + testForMessage(portalSuspendedBuffer, { + name: 'portalSuspended' + }) + }) + + describe('parses replication start message', function () { + testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { + name: 'replicationStart', + length: 4 + }) + }) + + + // since the data message on a stream can randomly divide the incomming + // tcp packets anywhere, we need to make sure we can parse every single + // split on a tcp message + describe('split buffer, single message parsing', function () { + var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']) + + const parse = (buffers: Buffer[]): Promise => { + return new Promise((resolve) => { + const parser = new PgPacketStream(); + parser.once('message', (msg) => { + resolve(msg) + }) + for (const buffer of buffers) { + parser.write(buffer); + } + parser.end() + }) + } + + it('parses when full buffer comes in', async function () { + const message = await parse([fullBuffer]); + assert.equal(message.fields.length, 5) + assert.equal(message.fields[0], null) + assert.equal(message.fields[1], 'bang') + assert.equal(message.fields[2], 'zug zug') + assert.equal(message.fields[3], null) + assert.equal(message.fields[4], '!') + }) + + var testMessageRecievedAfterSpiltAt = async function (split: number) { + var firstBuffer = Buffer.alloc(fullBuffer.length - split) + var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) + fullBuffer.copy(firstBuffer, 0, 0) + fullBuffer.copy(secondBuffer, 0, firstBuffer.length) + const message = await parse([firstBuffer, secondBuffer]); + assert.equal(message.fields.length, 5) + assert.equal(message.fields[0], null) + assert.equal(message.fields[1], 'bang') + assert.equal(message.fields[2], 'zug zug') + assert.equal(message.fields[3], null) + assert.equal(message.fields[4], '!') + } + + it('parses when split in the middle', function () { + testMessageRecievedAfterSpiltAt(6) + }) + + it('parses when split at end', function () { + testMessageRecievedAfterSpiltAt(2) + }) + + it('parses when split at beginning', function () { + testMessageRecievedAfterSpiltAt(fullBuffer.length - 2) + testMessageRecievedAfterSpiltAt(fullBuffer.length - 1) + testMessageRecievedAfterSpiltAt(fullBuffer.length - 5) + }) + }) + + describe('split buffer, multiple message parsing', function () { + var dataRowBuffer = buffers.dataRow(['!']) + var readyForQueryBuffer = buffers.readyForQuery() + var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length) + dataRowBuffer.copy(fullBuffer, 0, 0) + readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0) + + const parse = (buffers: Buffer[]): Promise => { + return new Promise((resolve) => { + const parser = new PgPacketStream(); + const results: any[] = [] + parser.on('message', (msg) => { + results.push(msg) + if (results.length === 2) { + resolve(results) + } + }) + for (const buffer of buffers) { + parser.write(buffer); + } + parser.end() + }) + } + + var verifyMessages = function (messages: any[]) { + assert.strictEqual(messages.length, 2) + assert.deepEqual(messages[0], { + name: 'dataRow', + fieldCount: 1, + length: 11, + fields: ['!'] + }) + assert.equal(messages[0].fields[0], '!') + assert.deepEqual(messages[1], { + name: 'readyForQuery', + length: 5, + status: 'I' + }) + } + // sanity check + it('recieves both messages when packet is not split', async function () { + const messages = await parse([fullBuffer]) + verifyMessages(messages) + }) + + var splitAndVerifyTwoMessages = async function (split: number) { + var firstBuffer = Buffer.alloc(fullBuffer.length - split) + var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) + fullBuffer.copy(firstBuffer, 0, 0) + fullBuffer.copy(secondBuffer, 0, firstBuffer.length) + const messages = await parse([firstBuffer, secondBuffer]) + verifyMessages(messages) + } + + describe('recieves both messages when packet is split', function () { + it('in the middle', function () { + return splitAndVerifyTwoMessages(11) + }) + it('at the front', function () { + return Promise.all([ + splitAndVerifyTwoMessages(fullBuffer.length - 1), + splitAndVerifyTwoMessages(fullBuffer.length - 4), + splitAndVerifyTwoMessages(fullBuffer.length - 6) + ]) + }) + + it('at the end', function () { + return Promise.all([ + splitAndVerifyTwoMessages(8), + splitAndVerifyTwoMessages(1) + ]) + }) + }) + }) + +}) diff --git a/packages/pg-packet-stream/src/index.ts b/packages/pg-packet-stream/src/index.ts index 95f0e82c6..4c03d9874 100644 --- a/packages/pg-packet-stream/src/index.ts +++ b/packages/pg-packet-stream/src/index.ts @@ -15,17 +15,12 @@ export type Packet = { type FieldFormat = "text" | "binary" -class Field { - constructor(public name: string) { - - } - -} - const emptyBuffer = Buffer.allocUnsafe(0); class BufferReader { private buffer: Buffer = emptyBuffer; + // TODO(bmc): support non-utf8 encoding + private encoding: string = 'utf-8'; constructor(private offset: number = 0) { } @@ -48,12 +43,19 @@ class BufferReader { } public string(length: number): string { - // TODO(bmc): support non-utf8 encoding - const result = this.buffer.toString('utf8', this.offset, this.offset + length) + const result = this.buffer.toString(this.encoding, this.offset, this.offset + length) this.offset += length; return result; } + public cstring(): string { + var start = this.offset + var end = this.buffer.indexOf(0, start) + this.offset = end + 1 + return this.buffer.toString(this.encoding, start, end) + + } + public bytes(length: number): Buffer { const result = this.buffer.slice(this.offset, this.offset + length); this.offset += length; @@ -82,20 +84,60 @@ const closeComplete = { length: 5, } +const noData = { + name: 'noData', + length: 5 +} + +const portalSuspended = { + name: 'portalSuspended', + length: 5, +} + +const replicationStart = { + name: 'replicationStart', + length: 4, +} + +const emptyQuery = { + name: 'emptyQuery', + length: 4, +} + +enum MessageCodes { + DataRow = 0x44, // D + ParseComplete = 0x31, // 1 + BindComplete = 0x32, // 2 + CloseComplete = 0x33, // 3 + CommandComplete = 0x43, // C + ReadyForQuery = 0x5a, // Z + NoData = 0x6e, // n + NotificationResponse = 0x41, // A + AuthenticationResponse = 0x52, // R + ParameterStatus = 0x53, // S + BackendKeyData = 0x4b, // K + ErrorMessage = 0x45, // E + NoticeMessage = 0x4e, // N + RowDescriptionMessage = 0x54, // T + PortalSuspended = 0x73, // s + ReplicationStart = 0x57, // W + EmptyQuery = 0x49, // I +} + export class PgPacketStream extends Transform { private remainingBuffer: Buffer = emptyBuffer; private reader = new BufferReader(); private mode: Mode; - constructor(opts: StreamOptions) { + constructor(opts?: StreamOptions) { super({ ...opts, readableObjectMode: true }) - if (opts.mode === 'binary') { + if (opts?.mode === 'binary') { throw new Error('Binary mode not supported yet') } - this.mode = opts.mode; + this.mode = opts?.mode || 'text'; } public _transform(buffer: Buffer, encoding: string, callback: TransformCallback) { @@ -111,7 +153,7 @@ export class PgPacketStream extends Transform { const fullMessageLength = CODE_LENGTH + length; if (fullMessageLength + offset <= combinedBuffer.byteLength) { - this.handlePacket(offset, code, length, combinedBuffer); + this.handlePacket(offset + CODE_LENGTH + LEN_LENGTH, code, length, combinedBuffer); offset += fullMessageLength; } else { break; @@ -127,22 +169,62 @@ export class PgPacketStream extends Transform { callback(null); } - private handlePacket(offset: number, code: number, length: number, combinedBuffer: Buffer) { + private handlePacket(offset: number, code: number, length: number, bytes: Buffer) { switch (code) { - case 0x44: // D - this.parseDataRowMessage(offset, length, combinedBuffer); + case MessageCodes.DataRow: + this.parseDataRowMessage(offset, length, bytes); break; - case 0x32: // 2 + case MessageCodes.BindComplete: this.emit('message', bindComplete); break; - case 0x31: // 1 + case MessageCodes.ParseComplete: this.emit('message', parseComplete); break; - case 0x33: // 3 + case MessageCodes.CloseComplete: this.emit('message', closeComplete); break; + case MessageCodes.NoData: + this.emit('message', noData); + break; + case MessageCodes.PortalSuspended: + this.emit('message', portalSuspended); + break; + case MessageCodes.CommandComplete: + this.parseCommandCompleteMessage(offset, length, bytes); + break; + case MessageCodes.ReplicationStart: + this.emit('message', replicationStart); + break; + case MessageCodes.EmptyQuery: + this.emit('message', emptyQuery); + break; + case MessageCodes.ReadyForQuery: + this.parseReadyForQueryMessage(offset, length, bytes); + break; + case MessageCodes.NotificationResponse: + this.parseNotificationMessage(offset, length, bytes); + break; + case MessageCodes.AuthenticationResponse: + this.parseAuthenticationResponse(offset, length, bytes); + break; + case MessageCodes.ParameterStatus: + this.parseParameterStatusMessage(offset, length, bytes); + break; + case MessageCodes.BackendKeyData: + this.parseBackendKeyData(offset, length, bytes); + break; + case MessageCodes.ErrorMessage: + this.parseErrorMessage(offset, length, bytes, 'error'); + break; + case MessageCodes.NoticeMessage: + this.parseErrorMessage(offset, length, bytes, 'notice'); + break; + case MessageCodes.RowDescriptionMessage: + this.parseRowDescriptionMessage(offset, length, bytes); + break; default: - const packet = combinedBuffer.slice(offset, CODE_LENGTH + length + offset) + throw new Error('unhanled code: ' + code.toString(16)) + const packet = bytes.slice(offset, CODE_LENGTH + length + offset) this.push({ code, length, packet, buffer: packet.slice(5) }) } } @@ -150,8 +232,52 @@ export class PgPacketStream extends Transform { public _flush(callback: TransformCallback) { } + private parseReadyForQueryMessage(offset: number, length: number, bytes: Buffer) { + this.reader.setBuffer(offset, bytes); + const status = this.reader.string(1); + const message = new ReadyForQueryMessage(length, status) + this.emit('message', message) + } + + private parseCommandCompleteMessage(offset: number, length: number, bytes: Buffer) { + this.reader.setBuffer(offset, bytes); + const text = this.reader.cstring(); + const message = new CommandCompleteMessage(length, text); + this.emit('message', message) + } + + private parseNotificationMessage(offset: number, length: number, bytes: Buffer) { + this.reader.setBuffer(offset, bytes); + const processId = this.reader.int32(); + const channel = this.reader.cstring(); + const payload = this.reader.cstring(); + const message = new NotificationResponseMessage(length, processId, channel, payload); + this.emit('message', message) + } + + private parseRowDescriptionMessage(offset: number, length: number, bytes: Buffer) { + this.reader.setBuffer(offset, bytes); + const fieldCount = this.reader.int16() + const message = new RowDescriptionMessage(length, fieldCount); + for (let i = 0; i < fieldCount; i++) { + message.fields[i] = this.parseField() + } + this.emit('message', message); + } + + private parseField(): Field { + const name = this.reader.cstring() + const tableID = this.reader.int32() + const columnID = this.reader.int16() + const dataTypeID = this.reader.int32() + const dataTypeSize = this.reader.int16() + const dataTypeModifier = this.reader.int32() + const mode = this.reader.int16() === 0 ? 'text' : 'binary'; + return new Field(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, mode) + } + private parseDataRowMessage(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset + 5, bytes); + this.reader.setBuffer(offset, bytes); const fieldCount = this.reader.int16(); const fields: any[] = new Array(fieldCount); for (let i = 0; i < fieldCount; i++) { @@ -165,6 +291,176 @@ export class PgPacketStream extends Transform { const message = new DataRowMessage(length, fields); this.emit('message', message); } + + private parseParameterStatusMessage(offset: number, length: number, bytes: Buffer) { + this.reader.setBuffer(offset, bytes); + const name = this.reader.cstring(); + const value = this.reader.cstring() + const msg = new ParameterStatusMessage(length, name, value) + this.emit('message', msg) + } + + private parseBackendKeyData(offset: number, length: number, bytes: Buffer) { + this.reader.setBuffer(offset, bytes); + const processID = this.reader.int32() + const secretKey = this.reader.int32() + const msg = new BackendKeyDataMessage(length, processID, secretKey) + this.emit('message', msg) + } + + + public parseAuthenticationResponse(offset: number, length: number, bytes: Buffer) { + this.reader.setBuffer(offset, bytes); + const code = this.reader.int32() + // TODO(bmc): maybe better types here + const msg: any = { + name: 'authenticationOk', + length, + }; + + switch (code) { + case 0: // AuthenticationOk + break; + case 3: // AuthenticationCleartextPassword + if (msg.length === 8) { + msg.name = 'authenticationCleartextPassword' + } + break + case 5: // AuthenticationMD5Password + if (msg.length === 12) { + msg.name = 'authenticationMD5Password' + msg.salt = this.reader.bytes(4); + } + break + case 10: // AuthenticationSASL + msg.name = 'authenticationSASL' + msg.mechanisms = [] + let mechanism: string; + do { + mechanism = this.reader.cstring() + + if (mechanism) { + msg.mechanisms.push(mechanism) + } + } while (mechanism) + break; + case 11: // AuthenticationSASLContinue + msg.name = 'authenticationSASLContinue' + msg.data = this.reader.string(length - 4) + break; + case 12: // AuthenticationSASLFinal + msg.name = 'authenticationSASLFinal' + msg.data = this.reader.string(length - 4) + break; + default: + throw new Error('Unknown authenticationOk message type ' + code) + } + this.emit('message', msg) + } + + private parseErrorMessage(offset: number, length: number, bytes: Buffer, name: string) { + this.reader.setBuffer(offset, bytes); + var fields: Record = {} + var fieldType = this.reader.string(1) + while (fieldType !== '\0') { + fields[fieldType] = this.reader.cstring() + fieldType = this.reader.string(1) + } + + // the msg is an Error instance + var msg = new DatabaseError(fields.M, length, name) + + msg.severity = fields.S + msg.code = fields.C + msg.detail = fields.D + msg.hint = fields.H + msg.position = fields.P + msg.internalPosition = fields.p + msg.internalQuery = fields.q + msg.where = fields.W + msg.schema = fields.s + msg.table = fields.t + msg.column = fields.c + msg.dataType = fields.d + msg.constraint = fields.n + msg.file = fields.F + msg.line = fields.L + msg.routine = fields.R + this.emit('message', msg); + + } +} + +class DatabaseError extends Error { + public severity: string | undefined; + public code: string | undefined; + public detail: string | undefined; + public hint: string | undefined; + public position: string | undefined; + public internalPosition: string | undefined; + public internalQuery: string | undefined; + public where: string | undefined; + public schema: string | undefined; + public table: string | undefined; + public column: string | undefined; + public dataType: string | undefined; + public constraint: string | undefined; + public file: string | undefined; + public line: string | undefined; + public routine: string | undefined; + constructor(message: string, public readonly length: number, public readonly name: string) { + super(message) + } +} + +class Field { + constructor(public readonly name: string, public readonly tableID: number, public readonly columnID: number, public readonly dataTypeID: number, public readonly dataTypeSize: number, public readonly dataTypeModifier: number, public readonly format: FieldFormat) { + + } + +} + +class RowDescriptionMessage { + public readonly name: string = 'rowDescription'; + public readonly fields: Field[]; + constructor(public readonly length: number, public readonly fieldCount: number) { + this.fields = new Array(this.fieldCount) + } +} + +class ParameterStatusMessage { + public readonly name: string = 'parameterStatus'; + constructor(public readonly length: number, public readonly parameterName: string, public readonly parameterValue: string) { + + } +} + +class BackendKeyDataMessage { + public readonly name: string = 'backendKeyData'; + constructor(public readonly length: number, public readonly processID: number, public readonly secretKey: number) { + + } +} + +class NotificationResponseMessage { + public readonly name: string = 'notification'; + constructor(public readonly length: number, public readonly processId: number, public readonly channel: string, public readonly payload: string) { + + } +} + +class ReadyForQueryMessage { + public readonly name: string = 'readyForQuery'; + constructor(public readonly length: number, public readonly status: string) { + + } +} + +class CommandCompleteMessage { + public readonly name: string = 'commandComplete' + constructor(public readonly length: number, public readonly text: string) { + + } } diff --git a/packages/pg-packet-stream/src/testing/buffer-list.ts b/packages/pg-packet-stream/src/testing/buffer-list.ts new file mode 100644 index 000000000..6487ea0b3 --- /dev/null +++ b/packages/pg-packet-stream/src/testing/buffer-list.ts @@ -0,0 +1,75 @@ +export default class BufferList { + constructor(public buffers: Buffer[] = []) { + + } + + public add(buffer: Buffer, front?: boolean) { + this.buffers[front ? 'unshift' : 'push'](buffer) + return this + } + + public addInt16(val: number, front?: boolean) { + return this.add(Buffer.from([(val >>> 8), (val >>> 0)]), front) + } + + public getByteLength(initial?: number) { + return this.buffers.reduce(function (previous, current) { + return previous + current.length + }, initial || 0) + } + + public addInt32(val: number, first?: boolean) { + return this.add(Buffer.from([ + (val >>> 24 & 0xFF), + (val >>> 16 & 0xFF), + (val >>> 8 & 0xFF), + (val >>> 0 & 0xFF) + ]), first) + } + + public addCString(val: string, front?: boolean) { + var len = Buffer.byteLength(val) + var buffer = Buffer.alloc(len + 1) + buffer.write(val) + buffer[len] = 0 + return this.add(buffer, front) + } + + public addString(val: string, front?: boolean) { + var len = Buffer.byteLength(val) + var buffer = Buffer.alloc(len) + buffer.write(val) + return this.add(buffer, front) + } + + public addChar(char: string, first?: boolean) { + return this.add(Buffer.from(char, 'utf8'), first) + } + + public join(appendLength?: boolean, char?: string): Buffer { + var length = this.getByteLength() + if (appendLength) { + this.addInt32(length + 4, true) + return this.join(false, char) + } + if (char) { + this.addChar(char, true) + length++ + } + var result = Buffer.alloc(length) + var index = 0 + this.buffers.forEach(function (buffer) { + buffer.copy(result, index, 0) + index += buffer.length + }) + return result + } + + public static concat(): Buffer { + var total = new BufferList() + for (var i = 0; i < arguments.length; i++) { + total.add(arguments[i]) + } + return total.join() + } +} diff --git a/packages/pg-packet-stream/src/testing/test-buffers.ts b/packages/pg-packet-stream/src/testing/test-buffers.ts new file mode 100644 index 000000000..e0c71e023 --- /dev/null +++ b/packages/pg-packet-stream/src/testing/test-buffers.ts @@ -0,0 +1,151 @@ +// http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html +import BufferList from './buffer-list' + +const buffers = { + readyForQuery: function () { + return new BufferList() + .add(Buffer.from('I')) + .join(true, 'Z') + }, + + authenticationOk: function () { + return new BufferList() + .addInt32(0) + .join(true, 'R') + }, + + authenticationCleartextPassword: function () { + return new BufferList() + .addInt32(3) + .join(true, 'R') + }, + + authenticationMD5Password: function () { + return new BufferList() + .addInt32(5) + .add(Buffer.from([1, 2, 3, 4])) + .join(true, 'R') + }, + + authenticationSASL: function () { + return new BufferList() + .addInt32(10) + .addCString('SCRAM-SHA-256') + .addCString('') + .join(true, 'R') + }, + + authenticationSASLContinue: function () { + return new BufferList() + .addInt32(11) + .addString('data') + .join(true, 'R') + }, + + authenticationSASLFinal: function () { + return new BufferList() + .addInt32(12) + .addString('data') + .join(true, 'R') + }, + + parameterStatus: function (name: string, value: string) { + return new BufferList() + .addCString(name) + .addCString(value) + .join(true, 'S') + }, + + backendKeyData: function (processID: number, secretKey: number) { + return new BufferList() + .addInt32(processID) + .addInt32(secretKey) + .join(true, 'K') + }, + + commandComplete: function (string: string) { + return new BufferList() + .addCString(string) + .join(true, 'C') + }, + + rowDescription: function (fields: any[]) { + fields = fields || [] + var buf = new BufferList() + buf.addInt16(fields.length) + fields.forEach(function (field) { + buf.addCString(field.name) + .addInt32(field.tableID || 0) + .addInt16(field.attributeNumber || 0) + .addInt32(field.dataTypeID || 0) + .addInt16(field.dataTypeSize || 0) + .addInt32(field.typeModifier || 0) + .addInt16(field.formatCode || 0) + }) + return buf.join(true, 'T') + }, + + dataRow: function (columns: any[]) { + columns = columns || [] + var buf = new BufferList() + buf.addInt16(columns.length) + columns.forEach(function (col) { + if (col == null) { + buf.addInt32(-1) + } else { + var strBuf = Buffer.from(col, 'utf8') + buf.addInt32(strBuf.length) + buf.add(strBuf) + } + }) + return buf.join(true, 'D') + }, + + error: function (fields: any) { + return buffers.errorOrNotice(fields).join(true, 'E') + }, + + notice: function (fields: any) { + return buffers.errorOrNotice(fields).join(true, 'N') + }, + + errorOrNotice: function (fields: any) { + fields = fields || [] + var buf = new BufferList() + fields.forEach(function (field: any) { + buf.addChar(field.type) + buf.addCString(field.value) + }) + return buf.add(Buffer.from([0]))// terminator + }, + + parseComplete: function () { + return new BufferList().join(true, '1') + }, + + bindComplete: function () { + return new BufferList().join(true, '2') + }, + + notification: function (id: number, channel: string, payload: string) { + return new BufferList() + .addInt32(id) + .addCString(channel) + .addCString(payload) + .join(true, 'A') + }, + + emptyQuery: function () { + return new BufferList().join(true, 'I') + }, + + portalSuspended: function () { + return new BufferList().join(true, 's') + }, + + closeComplete: function () { + return new BufferList().join(true, '3') + } +} + +export default buffers From e500479382c12b661605b2e7f246e2474701e821 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 19 Dec 2019 14:41:05 -0600 Subject: [PATCH 0544/1037] Add streaming parser --- .gitignore | 1 + packages/pg-packet-stream/src/index.ts | 15 ++-------- packages/pg/lib/connection-fast.js | 41 +++++++++++++------------- 3 files changed, 25 insertions(+), 32 deletions(-) diff --git a/.gitignore b/.gitignore index 56eba3953..df95fda07 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ node_modules/ package-lock.json *.swp dist +.DS_Store diff --git a/packages/pg-packet-stream/src/index.ts b/packages/pg-packet-stream/src/index.ts index 4c03d9874..adc158d6d 100644 --- a/packages/pg-packet-stream/src/index.ts +++ b/packages/pg-packet-stream/src/index.ts @@ -1,11 +1,9 @@ import { Transform, TransformCallback, TransformOptions } from 'stream'; -import assert from 'assert' -export const hello = () => 'Hello world!' - -// this is a single byte +// every message is prefixed with a single bye const CODE_LENGTH = 1; -// this is a Uint32 +// every message has an int32 length which includes itself but does +// NOT include the code in the length const LEN_LENGTH = 4; export type Packet = { @@ -415,9 +413,7 @@ class DatabaseError extends Error { class Field { constructor(public readonly name: string, public readonly tableID: number, public readonly columnID: number, public readonly dataTypeID: number, public readonly dataTypeSize: number, public readonly dataTypeModifier: number, public readonly format: FieldFormat) { - } - } class RowDescriptionMessage { @@ -438,32 +434,27 @@ class ParameterStatusMessage { class BackendKeyDataMessage { public readonly name: string = 'backendKeyData'; constructor(public readonly length: number, public readonly processID: number, public readonly secretKey: number) { - } } class NotificationResponseMessage { public readonly name: string = 'notification'; constructor(public readonly length: number, public readonly processId: number, public readonly channel: string, public readonly payload: string) { - } } class ReadyForQueryMessage { public readonly name: string = 'readyForQuery'; constructor(public readonly length: number, public readonly status: string) { - } } class CommandCompleteMessage { public readonly name: string = 'commandComplete' constructor(public readonly length: number, public readonly text: string) { - } } - class DataRowMessage { public readonly fieldCount: number; public readonly name: string = 'dataRow' diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index aea9eacd4..58e63dac4 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -138,26 +138,27 @@ Connection.prototype.attachListeners = function (stream) { }) } -// Connection.prototype.attachListeners = function (stream) { -// var self = this -// const mode = this._mode === TEXT_MODE ? 'text' : 'binary'; -// const packetStream = new PacketStream.PgPacketStream({ mode }) -// packetStream.on('message', (msg) => { -// self.emit(msg.name, msg) -// }) -// stream.pipe(packetStream).on('data', (packet) => { -// // console.log('buff', packet) -// var msg = self.parseMessage(packet) -// var eventName = msg.name === 'error' ? 'errorMessage' : msg.name -// if (self._emitMessage) { -// self.emit('message', msg) -// } -// self.emit(eventName, msg) -// }) -// stream.on('end', function () { -// self.emit('end') -// }) -// } +Connection.prototype.attachListeners = function (stream) { + var self = this + const mode = this._mode === TEXT_MODE ? 'text' : 'binary'; + const packetStream = new PacketStream.PgPacketStream({ mode }) + packetStream.on('message', (msg) => { + var eventName = msg.name === 'error' ? 'errorMessage' : msg.name + self.emit(eventName, msg) + }) + stream.pipe(packetStream).on('data', (packet) => { + // console.log('buff', packet) + var msg = self.parseMessage(packet) + var eventName = msg.name === 'error' ? 'errorMessage' : msg.name + if (self._emitMessage) { + self.emit('message', msg) + } + self.emit(eventName, msg) + }) + stream.on('end', function () { + self.emit('end') + }) +} Connection.prototype.requestSsl = function () { var bodyBuffer = this.writer From 0189c958f6cb727f01c706e3115a835061ae6852 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 19 Dec 2019 16:49:38 -0600 Subject: [PATCH 0545/1037] Create FUNDING.yml --- .github/FUNDING.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 000000000..817866852 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: [brianc] From a7c70a9acf835ad1ab3eb44d476077cd6a9ec554 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 19 Dec 2019 17:44:00 -0600 Subject: [PATCH 0546/1037] All tests passing --- .../src/inbound-parser.test.ts | 41 ++++++++++++ packages/pg-packet-stream/src/index.test.ts | 2 +- packages/pg-packet-stream/src/index.ts | 66 +++++++++++++++++++ .../src/testing/buffer-list.ts | 4 ++ .../src/testing/test-buffers.ts | 32 +++++++++ 5 files changed, 144 insertions(+), 1 deletion(-) diff --git a/packages/pg-packet-stream/src/inbound-parser.test.ts b/packages/pg-packet-stream/src/inbound-parser.test.ts index bdfb8a3b1..b5f2eab6f 100644 --- a/packages/pg-packet-stream/src/inbound-parser.test.ts +++ b/packages/pg-packet-stream/src/inbound-parser.test.ts @@ -340,6 +340,47 @@ describe('PgPacketStream', function () { }) }) + describe('copy', () => { + testForMessage(buffers.copyIn(0), { + name: 'copyInResponse', + length: 7, + binary: false, + columnTypes: [] + }) + + testForMessage(buffers.copyIn(2), { + name: 'copyInResponse', + length: 11, + binary: false, + columnTypes: [0, 1] + }) + + testForMessage(buffers.copyOut(0), { + name: 'copyOutResponse', + length: 7, + binary: false, + columnTypes: [] + }) + + testForMessage(buffers.copyOut(3), { + name: 'copyOutResponse', + length: 13, + binary: false, + columnTypes: [0, 1, 2] + }) + + testForMessage(buffers.copyDone(), { + name: 'copyDone', + length: 4, + }) + + testForMessage(buffers.copyData(Buffer.from([5, 6, 7])), { + name: 'copyData', + length: 7, + chunk: Buffer.from([5, 6, 7]) + }) + }) + // since the data message on a stream can randomly divide the incomming // tcp packets anywhere, we need to make sure we can parse every single diff --git a/packages/pg-packet-stream/src/index.test.ts b/packages/pg-packet-stream/src/index.test.ts index f5be4e2a0..1962329c5 100644 --- a/packages/pg-packet-stream/src/index.test.ts +++ b/packages/pg-packet-stream/src/index.test.ts @@ -29,7 +29,7 @@ const emptyMessage = Buffer.from([0x0a, 0x00, 0x00, 0x00, 0x04]) const oneByteMessage = Buffer.from([0x0b, 0x00, 0x00, 0x00, 0x05, 0x0a]) const bigMessage = Buffer.from([0x0f, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e0, 0x0f]) -describe('PgPacketStream', () => { +describe.skip('PgPacketStream', () => { it('should chunk a perfect input packet', async () => { const stream = new PgPacketStream() stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x04])) diff --git a/packages/pg-packet-stream/src/index.ts b/packages/pg-packet-stream/src/index.ts index adc158d6d..c7baa6d0b 100644 --- a/packages/pg-packet-stream/src/index.ts +++ b/packages/pg-packet-stream/src/index.ts @@ -34,6 +34,12 @@ class BufferReader { return result; } + public byte() { + const result = this.buffer[this.offset]; + this.offset++; + return result; + } + public int32() { const result = this.buffer.readInt32BE(this.offset); this.offset += 4; @@ -102,6 +108,11 @@ const emptyQuery = { length: 4, } +const copyDone = { + name: 'copyDone', + length: 4, +} + enum MessageCodes { DataRow = 0x44, // D ParseComplete = 0x31, // 1 @@ -120,6 +131,10 @@ enum MessageCodes { PortalSuspended = 0x73, // s ReplicationStart = 0x57, // W EmptyQuery = 0x49, // I + CopyIn = 0x47, // G + CopyOut = 0x48, // H + CopyDone = 0x63, // c + CopyData = 0x64, // d } export class PgPacketStream extends Transform { @@ -187,6 +202,9 @@ export class PgPacketStream extends Transform { case MessageCodes.PortalSuspended: this.emit('message', portalSuspended); break; + case MessageCodes.CopyDone: + this.emit('message', copyDone); + break; case MessageCodes.CommandComplete: this.parseCommandCompleteMessage(offset, length, bytes); break; @@ -220,6 +238,15 @@ export class PgPacketStream extends Transform { case MessageCodes.RowDescriptionMessage: this.parseRowDescriptionMessage(offset, length, bytes); break; + case MessageCodes.CopyIn: + this.parseCopyInMessage(offset, length, bytes); + break; + case MessageCodes.CopyOut: + this.parseCopyOutMessage(offset, length, bytes); + break; + case MessageCodes.CopyData: + this.parseCopyData(offset, length, bytes); + break; default: throw new Error('unhanled code: ' + code.toString(16)) const packet = bytes.slice(offset, CODE_LENGTH + length + offset) @@ -244,6 +271,31 @@ export class PgPacketStream extends Transform { this.emit('message', message) } + private parseCopyData(offset: number, length: number, bytes: Buffer) { + const chunk = bytes.slice(offset, offset + (length - 4)); + const message = new CopyDataMessage(length, chunk); + this.emit('message', message) + } + + private parseCopyInMessage(offset: number, length: number, bytes: Buffer) { + this.parseCopyMessage(offset, length, bytes, 'copyInResponse') + } + + private parseCopyOutMessage(offset: number, length: number, bytes: Buffer) { + this.parseCopyMessage(offset, length, bytes, 'copyOutResponse') + } + + private parseCopyMessage(offset: number, length: number, bytes: Buffer, messageName: string) { + this.reader.setBuffer(offset, bytes); + const isBinary = this.reader.byte() !== 0; + const columnCount = this.reader.int16() + const message = new CopyResponse(length, messageName, isBinary, columnCount); + for (let i = 0; i < columnCount; i++) { + message.columnTypes[i] = this.reader.int16(); + } + this.emit('message', message); + } + private parseNotificationMessage(offset: number, length: number, bytes: Buffer) { this.reader.setBuffer(offset, bytes); const processId = this.reader.int32(); @@ -411,6 +463,20 @@ class DatabaseError extends Error { } } +class CopyDataMessage { + public readonly name = 'copyData'; + constructor(public readonly length: number, public readonly chunk: Buffer) { + + } +} + +class CopyResponse { + public readonly columnTypes: number[]; + constructor(public readonly length: number, public readonly name: string, public readonly binary: boolean, columnCount: number) { + this.columnTypes = new Array(columnCount); + } +} + class Field { constructor(public readonly name: string, public readonly tableID: number, public readonly columnID: number, public readonly dataTypeID: number, public readonly dataTypeSize: number, public readonly dataTypeModifier: number, public readonly format: FieldFormat) { } diff --git a/packages/pg-packet-stream/src/testing/buffer-list.ts b/packages/pg-packet-stream/src/testing/buffer-list.ts index 6487ea0b3..51812bce4 100644 --- a/packages/pg-packet-stream/src/testing/buffer-list.ts +++ b/packages/pg-packet-stream/src/testing/buffer-list.ts @@ -46,6 +46,10 @@ export default class BufferList { return this.add(Buffer.from(char, 'utf8'), first) } + public addByte(byte: number) { + return this.add(Buffer.from([byte])) + } + public join(appendLength?: boolean, char?: string): Buffer { var length = this.getByteLength() if (appendLength) { diff --git a/packages/pg-packet-stream/src/testing/test-buffers.ts b/packages/pg-packet-stream/src/testing/test-buffers.ts index e0c71e023..0594eaadc 100644 --- a/packages/pg-packet-stream/src/testing/test-buffers.ts +++ b/packages/pg-packet-stream/src/testing/test-buffers.ts @@ -145,6 +145,38 @@ const buffers = { closeComplete: function () { return new BufferList().join(true, '3') + }, + + copyIn: function (cols: number) { + const list = new BufferList() + // text mode + .addByte(0) + // column count + .addInt16(cols); + for (let i = 0; i < cols; i++) { + list.addInt16(i); + } + return list.join(true, 'G') + }, + + copyOut: function (cols: number) { + const list = new BufferList() + // text mode + .addByte(0) + // column count + .addInt16(cols); + for (let i = 0; i < cols; i++) { + list.addInt16(i); + } + return list.join(true, 'H') + }, + + copyData: function (bytes: Buffer) { + return new BufferList().add(bytes).join(true, 'd'); + }, + + copyDone: function () { + return new BufferList().join(true, 'c') } } From b0be9da9863a957f38fd3914551afa91d39bf5ff Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 19 Dec 2019 18:57:48 -0600 Subject: [PATCH 0547/1037] Cleanup --- packages/pg-packet-stream/src/BufferReader.ts | 44 +++ .../src/inbound-parser.test.ts | 66 ++-- packages/pg-packet-stream/src/index.ts | 368 ++++-------------- packages/pg-packet-stream/src/messages.ts | 134 +++++++ packages/pg/bench.js | 41 +- packages/pg/lib/connection-fast.js | 368 +----------------- packages/pg/lib/result.js | 12 +- 7 files changed, 332 insertions(+), 701 deletions(-) create mode 100644 packages/pg-packet-stream/src/BufferReader.ts create mode 100644 packages/pg-packet-stream/src/messages.ts diff --git a/packages/pg-packet-stream/src/BufferReader.ts b/packages/pg-packet-stream/src/BufferReader.ts new file mode 100644 index 000000000..9729d919f --- /dev/null +++ b/packages/pg-packet-stream/src/BufferReader.ts @@ -0,0 +1,44 @@ +const emptyBuffer = Buffer.allocUnsafe(0); + +export class BufferReader { + private buffer: Buffer = emptyBuffer; + // TODO(bmc): support non-utf8 encoding + private encoding: string = 'utf-8'; + constructor(private offset: number = 0) { + } + public setBuffer(offset: number, buffer: Buffer): void { + this.offset = offset; + this.buffer = buffer; + } + public int16() { + const result = this.buffer.readInt16BE(this.offset); + this.offset += 2; + return result; + } + public byte() { + const result = this.buffer[this.offset]; + this.offset++; + return result; + } + public int32() { + const result = this.buffer.readInt32BE(this.offset); + this.offset += 4; + return result; + } + public string(length: number): string { + const result = this.buffer.toString(this.encoding, this.offset, this.offset + length); + this.offset += length; + return result; + } + public cstring(): string { + var start = this.offset; + var end = this.buffer.indexOf(0, start); + this.offset = end + 1; + return this.buffer.toString(this.encoding, start, end); + } + public bytes(length: number): Buffer { + const result = this.buffer.slice(this.offset, this.offset + length); + this.offset += length; + return result; + } +} diff --git a/packages/pg-packet-stream/src/inbound-parser.test.ts b/packages/pg-packet-stream/src/inbound-parser.test.ts index b5f2eab6f..098f41242 100644 --- a/packages/pg-packet-stream/src/inbound-parser.test.ts +++ b/packages/pg-packet-stream/src/inbound-parser.test.ts @@ -2,6 +2,7 @@ import buffers from './testing/test-buffers' import BufferList from './testing/buffer-list' import { PgPacketStream } from './' import assert from 'assert' +import { Readable } from 'stream' var authOkBuffer = buffers.authenticationOk() var paramStatusBuffer = buffers.parameterStatus('client_encoding', 'UTF8') @@ -136,23 +137,25 @@ var expectedTwoRowMessage = { }] } +const concat = (stream: Readable): Promise => { + return new Promise((resolve) => { + const results: any[] = [] + stream.on('data', item => results.push(item)) + stream.on('end', () => resolve(results)) + }) +} + var testForMessage = function (buffer: Buffer, expectedMessage: any) { it('recieves and parses ' + expectedMessage.name, async () => { const parser = new PgPacketStream(); + parser.write(buffer); + parser.end(); + const [lastMessage] = await concat(parser); - await new Promise((resolve) => { - let lastMessage: any = {} - parser.on('message', function (msg) { - lastMessage = msg - }) - - parser.write(buffer); + for (const key in expectedMessage) { + assert.deepEqual(lastMessage[key], expectedMessage[key]) + } - for (const key in expectedMessage) { - assert.deepEqual(lastMessage[key], expectedMessage[key]) - } - resolve(); - }) }) } @@ -388,17 +391,14 @@ describe('PgPacketStream', function () { describe('split buffer, single message parsing', function () { var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']) - const parse = (buffers: Buffer[]): Promise => { - return new Promise((resolve) => { - const parser = new PgPacketStream(); - parser.once('message', (msg) => { - resolve(msg) - }) - for (const buffer of buffers) { - parser.write(buffer); - } - parser.end() - }) + const parse = async (buffers: Buffer[]): Promise => { + const parser = new PgPacketStream(); + for (const buffer of buffers) { + parser.write(buffer); + } + parser.end() + const [msg] = await concat(parser) + return msg; } it('parses when full buffer comes in', async function () { @@ -448,20 +448,12 @@ describe('PgPacketStream', function () { readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0) const parse = (buffers: Buffer[]): Promise => { - return new Promise((resolve) => { - const parser = new PgPacketStream(); - const results: any[] = [] - parser.on('message', (msg) => { - results.push(msg) - if (results.length === 2) { - resolve(results) - } - }) - for (const buffer of buffers) { - parser.write(buffer); - } - parser.end() - }) + const parser = new PgPacketStream(); + for (const buffer of buffers) { + parser.write(buffer); + } + parser.end() + return concat(parser) } var verifyMessages = function (messages: any[]) { diff --git a/packages/pg-packet-stream/src/index.ts b/packages/pg-packet-stream/src/index.ts index c7baa6d0b..dc2af4246 100644 --- a/packages/pg-packet-stream/src/index.ts +++ b/packages/pg-packet-stream/src/index.ts @@ -1,4 +1,7 @@ import { Transform, TransformCallback, TransformOptions } from 'stream'; +import { Mode, bindComplete, parseComplete, closeComplete, noData, portalSuspended, copyDone, replicationStart, emptyQuery, ReadyForQueryMessage, CommandCompleteMessage, CopyDataMessage, CopyResponse, NotificationResponseMessage, RowDescriptionMessage, Field, DataRowMessage, ParameterStatusMessage, BackendKeyDataMessage, DatabaseError, BackendMessage } from './messages'; +import { BufferReader } from './BufferReader'; +import assert from 'assert' // every message is prefixed with a single bye const CODE_LENGTH = 1; @@ -6,114 +9,20 @@ const CODE_LENGTH = 1; // NOT include the code in the length const LEN_LENGTH = 4; +const HEADER_LENGTH = CODE_LENGTH + LEN_LENGTH; + export type Packet = { code: number; packet: Buffer; } -type FieldFormat = "text" | "binary" - const emptyBuffer = Buffer.allocUnsafe(0); -class BufferReader { - private buffer: Buffer = emptyBuffer; - // TODO(bmc): support non-utf8 encoding - private encoding: string = 'utf-8'; - constructor(private offset: number = 0) { - - } - - public setBuffer(offset: number, buffer: Buffer): void { - this.offset = offset; - this.buffer = buffer; - } - - public int16() { - const result = this.buffer.readInt16BE(this.offset); - this.offset += 2; - return result; - } - - public byte() { - const result = this.buffer[this.offset]; - this.offset++; - return result; - } - - public int32() { - const result = this.buffer.readInt32BE(this.offset); - this.offset += 4; - return result; - } - - public string(length: number): string { - const result = this.buffer.toString(this.encoding, this.offset, this.offset + length) - this.offset += length; - return result; - } - - public cstring(): string { - var start = this.offset - var end = this.buffer.indexOf(0, start) - this.offset = end + 1 - return this.buffer.toString(this.encoding, start, end) - - } - - public bytes(length: number): Buffer { - const result = this.buffer.slice(this.offset, this.offset + length); - this.offset += length; - return result - } -} - -type Mode = 'text' | 'binary'; - type StreamOptions = TransformOptions & { mode: Mode } -const parseComplete = { - name: 'parseComplete', - length: 5, -}; - -const bindComplete = { - name: 'bindComplete', - length: 5, -} - -const closeComplete = { - name: 'closeComplete', - length: 5, -} - -const noData = { - name: 'noData', - length: 5 -} - -const portalSuspended = { - name: 'portalSuspended', - length: 5, -} - -const replicationStart = { - name: 'replicationStart', - length: 4, -} - -const emptyQuery = { - name: 'emptyQuery', - length: 4, -} - -const copyDone = { - name: 'copyDone', - length: 4, -} - -enum MessageCodes { +const enum MessageCodes { DataRow = 0x44, // D ParseComplete = 0x31, // 1 BindComplete = 0x32, // 2 @@ -154,9 +63,9 @@ export class PgPacketStream extends Transform { } public _transform(buffer: Buffer, encoding: string, callback: TransformCallback) { - const combinedBuffer = this.remainingBuffer.byteLength ? Buffer.concat([this.remainingBuffer, buffer], this.remainingBuffer.length + buffer.length) : buffer; + const combinedBuffer: Buffer = this.remainingBuffer.byteLength ? Buffer.concat([this.remainingBuffer, buffer], this.remainingBuffer.length + buffer.length) : buffer; let offset = 0; - while ((offset + CODE_LENGTH + LEN_LENGTH) <= combinedBuffer.byteLength) { + while ((offset + HEADER_LENGTH) <= combinedBuffer.byteLength) { // code is 1 byte long - it identifies the message type const code = combinedBuffer[offset]; @@ -166,7 +75,8 @@ export class PgPacketStream extends Transform { const fullMessageLength = CODE_LENGTH + length; if (fullMessageLength + offset <= combinedBuffer.byteLength) { - this.handlePacket(offset + CODE_LENGTH + LEN_LENGTH, code, length, combinedBuffer); + const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer); + this.push(message) offset += fullMessageLength; } else { break; @@ -182,107 +92,82 @@ export class PgPacketStream extends Transform { callback(null); } - private handlePacket(offset: number, code: number, length: number, bytes: Buffer) { + private handlePacket(offset: number, code: number, length: number, bytes: Buffer): BackendMessage { switch (code) { - case MessageCodes.DataRow: - this.parseDataRowMessage(offset, length, bytes); - break; case MessageCodes.BindComplete: - this.emit('message', bindComplete); - break; + return bindComplete; case MessageCodes.ParseComplete: - this.emit('message', parseComplete); - break; + return parseComplete; case MessageCodes.CloseComplete: - this.emit('message', closeComplete); - break; + return closeComplete; case MessageCodes.NoData: - this.emit('message', noData); - break; + return noData; case MessageCodes.PortalSuspended: - this.emit('message', portalSuspended); - break; + return portalSuspended; case MessageCodes.CopyDone: - this.emit('message', copyDone); - break; - case MessageCodes.CommandComplete: - this.parseCommandCompleteMessage(offset, length, bytes); - break; + return copyDone; case MessageCodes.ReplicationStart: - this.emit('message', replicationStart); - break; + return replicationStart; case MessageCodes.EmptyQuery: - this.emit('message', emptyQuery); - break; + return emptyQuery; + case MessageCodes.DataRow: + return this.parseDataRowMessage(offset, length, bytes); + case MessageCodes.CommandComplete: + return this.parseCommandCompleteMessage(offset, length, bytes); case MessageCodes.ReadyForQuery: - this.parseReadyForQueryMessage(offset, length, bytes); - break; + return this.parseReadyForQueryMessage(offset, length, bytes); case MessageCodes.NotificationResponse: - this.parseNotificationMessage(offset, length, bytes); - break; + return this.parseNotificationMessage(offset, length, bytes); case MessageCodes.AuthenticationResponse: - this.parseAuthenticationResponse(offset, length, bytes); - break; + return this.parseAuthenticationResponse(offset, length, bytes); case MessageCodes.ParameterStatus: - this.parseParameterStatusMessage(offset, length, bytes); - break; + return this.parseParameterStatusMessage(offset, length, bytes); case MessageCodes.BackendKeyData: - this.parseBackendKeyData(offset, length, bytes); - break; + return this.parseBackendKeyData(offset, length, bytes); case MessageCodes.ErrorMessage: - this.parseErrorMessage(offset, length, bytes, 'error'); - break; + return this.parseErrorMessage(offset, length, bytes, 'error'); case MessageCodes.NoticeMessage: - this.parseErrorMessage(offset, length, bytes, 'notice'); - break; + return this.parseErrorMessage(offset, length, bytes, 'notice'); case MessageCodes.RowDescriptionMessage: - this.parseRowDescriptionMessage(offset, length, bytes); - break; + return this.parseRowDescriptionMessage(offset, length, bytes); case MessageCodes.CopyIn: - this.parseCopyInMessage(offset, length, bytes); - break; + return this.parseCopyInMessage(offset, length, bytes); case MessageCodes.CopyOut: - this.parseCopyOutMessage(offset, length, bytes); - break; + return this.parseCopyOutMessage(offset, length, bytes); case MessageCodes.CopyData: - this.parseCopyData(offset, length, bytes); - break; + return this.parseCopyData(offset, length, bytes); default: - throw new Error('unhanled code: ' + code.toString(16)) - const packet = bytes.slice(offset, CODE_LENGTH + length + offset) - this.push({ code, length, packet, buffer: packet.slice(5) }) + assert.fail(`unknown message code: ${code.toString(16)}`) } } public _flush(callback: TransformCallback) { + this._transform(Buffer.alloc(0), 'utf-i', callback) } private parseReadyForQueryMessage(offset: number, length: number, bytes: Buffer) { this.reader.setBuffer(offset, bytes); const status = this.reader.string(1); - const message = new ReadyForQueryMessage(length, status) - this.emit('message', message) + return new ReadyForQueryMessage(length, status) } private parseCommandCompleteMessage(offset: number, length: number, bytes: Buffer) { this.reader.setBuffer(offset, bytes); const text = this.reader.cstring(); - const message = new CommandCompleteMessage(length, text); - this.emit('message', message) + return new CommandCompleteMessage(length, text); } private parseCopyData(offset: number, length: number, bytes: Buffer) { const chunk = bytes.slice(offset, offset + (length - 4)); - const message = new CopyDataMessage(length, chunk); - this.emit('message', message) + return new CopyDataMessage(length, chunk); } private parseCopyInMessage(offset: number, length: number, bytes: Buffer) { - this.parseCopyMessage(offset, length, bytes, 'copyInResponse') + return this.parseCopyMessage(offset, length, bytes, 'copyInResponse') } private parseCopyOutMessage(offset: number, length: number, bytes: Buffer) { - this.parseCopyMessage(offset, length, bytes, 'copyOutResponse') + return this.parseCopyMessage(offset, length, bytes, 'copyOutResponse') } private parseCopyMessage(offset: number, length: number, bytes: Buffer, messageName: string) { @@ -293,7 +178,7 @@ export class PgPacketStream extends Transform { for (let i = 0; i < columnCount; i++) { message.columnTypes[i] = this.reader.int16(); } - this.emit('message', message); + return message; } private parseNotificationMessage(offset: number, length: number, bytes: Buffer) { @@ -301,8 +186,7 @@ export class PgPacketStream extends Transform { const processId = this.reader.int32(); const channel = this.reader.cstring(); const payload = this.reader.cstring(); - const message = new NotificationResponseMessage(length, processId, channel, payload); - this.emit('message', message) + return new NotificationResponseMessage(length, processId, channel, payload); } private parseRowDescriptionMessage(offset: number, length: number, bytes: Buffer) { @@ -312,7 +196,7 @@ export class PgPacketStream extends Transform { for (let i = 0; i < fieldCount; i++) { message.fields[i] = this.parseField() } - this.emit('message', message); + return message; } private parseField(): Field { @@ -338,24 +222,21 @@ export class PgPacketStream extends Transform { fields[i] = this.reader.string(len) } } - const message = new DataRowMessage(length, fields); - this.emit('message', message); + return new DataRowMessage(length, fields); } private parseParameterStatusMessage(offset: number, length: number, bytes: Buffer) { this.reader.setBuffer(offset, bytes); const name = this.reader.cstring(); const value = this.reader.cstring() - const msg = new ParameterStatusMessage(length, name, value) - this.emit('message', msg) + return new ParameterStatusMessage(length, name, value) } private parseBackendKeyData(offset: number, length: number, bytes: Buffer) { this.reader.setBuffer(offset, bytes); const processID = this.reader.int32() const secretKey = this.reader.int32() - const msg = new BackendKeyDataMessage(length, processID, secretKey) - this.emit('message', msg) + return new BackendKeyDataMessage(length, processID, secretKey) } @@ -363,7 +244,7 @@ export class PgPacketStream extends Transform { this.reader.setBuffer(offset, bytes); const code = this.reader.int32() // TODO(bmc): maybe better types here - const msg: any = { + const message: any = { name: 'authenticationOk', length, }; @@ -372,40 +253,40 @@ export class PgPacketStream extends Transform { case 0: // AuthenticationOk break; case 3: // AuthenticationCleartextPassword - if (msg.length === 8) { - msg.name = 'authenticationCleartextPassword' + if (message.length === 8) { + message.name = 'authenticationCleartextPassword' } break case 5: // AuthenticationMD5Password - if (msg.length === 12) { - msg.name = 'authenticationMD5Password' - msg.salt = this.reader.bytes(4); + if (message.length === 12) { + message.name = 'authenticationMD5Password' + message.salt = this.reader.bytes(4); } break case 10: // AuthenticationSASL - msg.name = 'authenticationSASL' - msg.mechanisms = [] + message.name = 'authenticationSASL' + message.mechanisms = [] let mechanism: string; do { mechanism = this.reader.cstring() if (mechanism) { - msg.mechanisms.push(mechanism) + message.mechanisms.push(mechanism) } } while (mechanism) break; case 11: // AuthenticationSASLContinue - msg.name = 'authenticationSASLContinue' - msg.data = this.reader.string(length - 4) + message.name = 'authenticationSASLContinue' + message.data = this.reader.string(length - 4) break; case 12: // AuthenticationSASLFinal - msg.name = 'authenticationSASLFinal' - msg.data = this.reader.string(length - 4) + message.name = 'authenticationSASLFinal' + message.data = this.reader.string(length - 4) break; default: throw new Error('Unknown authenticationOk message type ' + code) } - this.emit('message', msg) + return message; } private parseErrorMessage(offset: number, length: number, bytes: Buffer, name: string) { @@ -418,113 +299,24 @@ export class PgPacketStream extends Transform { } // the msg is an Error instance - var msg = new DatabaseError(fields.M, length, name) - - msg.severity = fields.S - msg.code = fields.C - msg.detail = fields.D - msg.hint = fields.H - msg.position = fields.P - msg.internalPosition = fields.p - msg.internalQuery = fields.q - msg.where = fields.W - msg.schema = fields.s - msg.table = fields.t - msg.column = fields.c - msg.dataType = fields.d - msg.constraint = fields.n - msg.file = fields.F - msg.line = fields.L - msg.routine = fields.R - this.emit('message', msg); - - } -} - -class DatabaseError extends Error { - public severity: string | undefined; - public code: string | undefined; - public detail: string | undefined; - public hint: string | undefined; - public position: string | undefined; - public internalPosition: string | undefined; - public internalQuery: string | undefined; - public where: string | undefined; - public schema: string | undefined; - public table: string | undefined; - public column: string | undefined; - public dataType: string | undefined; - public constraint: string | undefined; - public file: string | undefined; - public line: string | undefined; - public routine: string | undefined; - constructor(message: string, public readonly length: number, public readonly name: string) { - super(message) - } -} - -class CopyDataMessage { - public readonly name = 'copyData'; - constructor(public readonly length: number, public readonly chunk: Buffer) { - - } -} - -class CopyResponse { - public readonly columnTypes: number[]; - constructor(public readonly length: number, public readonly name: string, public readonly binary: boolean, columnCount: number) { - this.columnTypes = new Array(columnCount); - } -} - -class Field { - constructor(public readonly name: string, public readonly tableID: number, public readonly columnID: number, public readonly dataTypeID: number, public readonly dataTypeSize: number, public readonly dataTypeModifier: number, public readonly format: FieldFormat) { - } -} - -class RowDescriptionMessage { - public readonly name: string = 'rowDescription'; - public readonly fields: Field[]; - constructor(public readonly length: number, public readonly fieldCount: number) { - this.fields = new Array(this.fieldCount) - } -} - -class ParameterStatusMessage { - public readonly name: string = 'parameterStatus'; - constructor(public readonly length: number, public readonly parameterName: string, public readonly parameterValue: string) { - - } -} - -class BackendKeyDataMessage { - public readonly name: string = 'backendKeyData'; - constructor(public readonly length: number, public readonly processID: number, public readonly secretKey: number) { - } -} - -class NotificationResponseMessage { - public readonly name: string = 'notification'; - constructor(public readonly length: number, public readonly processId: number, public readonly channel: string, public readonly payload: string) { - } -} - -class ReadyForQueryMessage { - public readonly name: string = 'readyForQuery'; - constructor(public readonly length: number, public readonly status: string) { - } -} - -class CommandCompleteMessage { - public readonly name: string = 'commandComplete' - constructor(public readonly length: number, public readonly text: string) { - } -} - -class DataRowMessage { - public readonly fieldCount: number; - public readonly name: string = 'dataRow' - constructor(public length: number, public fields: any[]) { - this.fieldCount = fields.length; + var message = new DatabaseError(fields.M, length, name) + + message.severity = fields.S + message.code = fields.C + message.detail = fields.D + message.hint = fields.H + message.position = fields.P + message.internalPosition = fields.p + message.internalQuery = fields.q + message.where = fields.W + message.schema = fields.s + message.table = fields.t + message.column = fields.c + message.dataType = fields.d + message.constraint = fields.n + message.file = fields.F + message.line = fields.L + message.routine = fields.R + return message; } } diff --git a/packages/pg-packet-stream/src/messages.ts b/packages/pg-packet-stream/src/messages.ts new file mode 100644 index 000000000..26013cf13 --- /dev/null +++ b/packages/pg-packet-stream/src/messages.ts @@ -0,0 +1,134 @@ +export type Mode = 'text' | 'binary'; + +export type BackendMessage = { + name: string; + length: number; +} + +export const parseComplete: BackendMessage = { + name: 'parseComplete', + length: 5, +}; + +export const bindComplete: BackendMessage = { + name: 'bindComplete', + length: 5, +} + +export const closeComplete: BackendMessage = { + name: 'closeComplete', + length: 5, +} + +export const noData: BackendMessage = { + name: 'noData', + length: 5 +} + +export const portalSuspended: BackendMessage = { + name: 'portalSuspended', + length: 5, +} + +export const replicationStart: BackendMessage = { + name: 'replicationStart', + length: 4, +} + +export const emptyQuery: BackendMessage = { + name: 'emptyQuery', + length: 4, +} + +export const copyDone: BackendMessage = { + name: 'copyDone', + length: 4, +} + +export class DatabaseError extends Error { + public severity: string | undefined; + public code: string | undefined; + public detail: string | undefined; + public hint: string | undefined; + public position: string | undefined; + public internalPosition: string | undefined; + public internalQuery: string | undefined; + public where: string | undefined; + public schema: string | undefined; + public table: string | undefined; + public column: string | undefined; + public dataType: string | undefined; + public constraint: string | undefined; + public file: string | undefined; + public line: string | undefined; + public routine: string | undefined; + constructor(message: string, public readonly length: number, public readonly name: string) { + super(message) + } +} + +export class CopyDataMessage { + public readonly name = 'copyData'; + constructor(public readonly length: number, public readonly chunk: Buffer) { + + } +} + +export class CopyResponse { + public readonly columnTypes: number[]; + constructor(public readonly length: number, public readonly name: string, public readonly binary: boolean, columnCount: number) { + this.columnTypes = new Array(columnCount); + } +} + +export class Field { + constructor(public readonly name: string, public readonly tableID: number, public readonly columnID: number, public readonly dataTypeID: number, public readonly dataTypeSize: number, public readonly dataTypeModifier: number, public readonly format: Mode) { + } +} + +export class RowDescriptionMessage { + public readonly name: string = 'rowDescription'; + public readonly fields: Field[]; + constructor(public readonly length: number, public readonly fieldCount: number) { + this.fields = new Array(this.fieldCount) + } +} + +export class ParameterStatusMessage { + public readonly name: string = 'parameterStatus'; + constructor(public readonly length: number, public readonly parameterName: string, public readonly parameterValue: string) { + + } +} + +export class BackendKeyDataMessage { + public readonly name: string = 'backendKeyData'; + constructor(public readonly length: number, public readonly processID: number, public readonly secretKey: number) { + } +} + +export class NotificationResponseMessage { + public readonly name: string = 'notification'; + constructor(public readonly length: number, public readonly processId: number, public readonly channel: string, public readonly payload: string) { + } +} + +export class ReadyForQueryMessage { + public readonly name: string = 'readyForQuery'; + constructor(public readonly length: number, public readonly status: string) { + } +} + +export class CommandCompleteMessage { + public readonly name: string = 'commandComplete' + constructor(public readonly length: number, public readonly text: string) { + } +} + +export class DataRowMessage { + public readonly fieldCount: number; + public readonly name: string = 'dataRow' + constructor(public length: number, public fields: any[]) { + this.fieldCount = fields.length; + } +} diff --git a/packages/pg/bench.js b/packages/pg/bench.js index 7a7084aee..3c12fa683 100644 --- a/packages/pg/bench.js +++ b/packages/pg/bench.js @@ -1,13 +1,22 @@ const pg = require("./lib"); const pool = new pg.Pool() -const q = { +const params = { text: "select typname, typnamespace, typowner, typlen, typbyval, typcategory, typispreferred, typisdefined, typdelim, typrelid, typelem, typarray from pg_type where typtypmod = $1 and typisdefined = $2", values: [-1, true] }; -const exec = async client => { +const insert = { + text: 'INSERT INTO foobar(name, age) VALUES ($1, $2)', + values: ['brian', 100] +} + +const seq = { + text: 'SELECT * FROM generate_series(1, 1000)' +} + +const exec = async (client, q) => { const result = await client.query({ text: q.text, values: q.values, @@ -15,11 +24,11 @@ const exec = async client => { }); }; -const bench = async (client, time) => { +const bench = async (client, q, time) => { let start = Date.now(); let count = 0; while (true) { - await exec(client); + await exec(client, q); count++; if (Date.now() - start > time) { return count; @@ -30,13 +39,29 @@ const bench = async (client, time) => { const run = async () => { const client = new pg.Client(); await client.connect(); - await bench(client, 1000); + await client.query('CREATE TEMP TABLE foobar(name TEXT, age NUMERIC)') + await bench(client, params, 1000); console.log("warmup done"); const seconds = 5; - const queries = await bench(client, seconds * 1000); - console.log("queries:", queries); + + let queries = await bench(client, params, seconds * 1000); + console.log('') + console.log("little queries:", queries); + console.log("qps", queries / seconds); + console.log("on my laptop best so far seen 733 qps") + + console.log('') + queries = await bench(client, seq, seconds * 1000); + console.log("sequence queries:", queries); + console.log("qps", queries / seconds); + console.log("on my laptop best so far seen 1192 qps") + + console.log('') + queries = await bench(client, insert, seconds * 1000); + console.log("insert queries:", queries); console.log("qps", queries / seconds); - console.log("on my laptop best so far seen 713 qps") + console.log("on my laptop best so far seen 5600 qps") + await client.end(); await client.end(); }; diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index 58e63dac4..29752df72 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -12,11 +12,12 @@ var EventEmitter = require('events').EventEmitter var util = require('util') var Writer = require('buffer-writer') -var Reader = require('packet-reader') var PacketStream = require('pg-packet-stream') var TEXT_MODE = 0 -var BINARY_MODE = 1 + +// TODO(bmc) support binary mode here +// var BINARY_MODE = 1 console.log('using faster connection') var Connection = function (config) { EventEmitter.call(this) @@ -36,10 +37,6 @@ var Connection = function (config) { this._ending = false this._mode = TEXT_MODE this._emitMessage = false - this._reader = new Reader({ - headerSize: 1, - lengthPadding: -4 - }) var self = this this.on('newListener', function (eventName) { if (eventName === 'message') { @@ -120,35 +117,10 @@ Connection.prototype.connect = function (port, host) { Connection.prototype.attachListeners = function (stream) { var self = this - stream.on('data', function (buff) { - self._reader.addChunk(buff) - var packet = self._reader.read() - while (packet) { - var msg = self.parseMessage({ code: self._reader.header, length: packet.length + 4, buffer: packet }) - var eventName = msg.name === 'error' ? 'errorMessage' : msg.name - if (self._emitMessage) { - self.emit('message', msg) - } - self.emit(eventName, msg) - packet = self._reader.read() - } - }) - stream.on('end', function () { - self.emit('end') - }) -} - -Connection.prototype.attachListeners = function (stream) { - var self = this - const mode = this._mode === TEXT_MODE ? 'text' : 'binary'; + const mode = this._mode === TEXT_MODE ? 'text' : 'binary' const packetStream = new PacketStream.PgPacketStream({ mode }) - packetStream.on('message', (msg) => { - var eventName = msg.name === 'error' ? 'errorMessage' : msg.name - self.emit(eventName, msg) - }) - stream.pipe(packetStream).on('data', (packet) => { - // console.log('buff', packet) - var msg = self.parseMessage(packet) + this.stream.pipe(packetStream) + packetStream.on('data', (msg) => { var eventName = msg.name === 'error' ? 'errorMessage' : msg.name if (self._emitMessage) { self.emit('message', msg) @@ -397,332 +369,4 @@ Connection.prototype.sendCopyFail = function (msg) { this._send(0x66) } -var Message = function (name, length) { - this.name = name - this.length = length -} - -Connection.prototype.parseMessage = function (packet) { - this.offset = 0 - const { code, length, buffer } = packet - switch (code) { - case 0x52: // R - return this.parseR(buffer, length) - - case 0x53: // S - return this.parseS(buffer, length) - - case 0x4b: // K - return this.parseK(buffer, length) - - case 0x43: // C - return this.parseC(buffer, length) - - case 0x5a: // Z - return this.parseZ(buffer, length) - - case 0x54: // T - return this.parseT(buffer, length) - - case 0x44: // D - return this.parseD(buffer, length) - - case 0x45: // E - return this.parseE(buffer, length) - - case 0x4e: // N - return this.parseN(buffer, length) - - case 0x31: // 1 - return new Message('parseComplete', length) - - case 0x32: // 2 - return new Message('bindComplete', length) - - case 0x33: // 3 - return new Message('closeComplete', length) - - case 0x41: // A - return this.parseA(buffer, length) - - case 0x6e: // n - return new Message('noData', length) - - case 0x49: // I - return new Message('emptyQuery', length) - - case 0x73: // s - return new Message('portalSuspended', length) - - case 0x47: // G - return this.parseG(buffer, length) - - case 0x48: // H - return this.parseH(buffer, length) - - case 0x57: // W - return new Message('replicationStart', length) - - case 0x63: // c - return new Message('copyDone', length) - - case 0x64: // d - return this.parsed(buffer, length) - } - console.log('could not parse', packet) -} - -Connection.prototype.parseR = function (buffer, length) { - var code = this.parseInt32(buffer) - - var msg = new Message('authenticationOk', length) - - switch (code) { - case 0: // AuthenticationOk - return msg - case 3: // AuthenticationCleartextPassword - if (msg.length === 8) { - msg.name = 'authenticationCleartextPassword' - return msg - } - break - case 5: // AuthenticationMD5Password - if (msg.length === 12) { - msg.name = 'authenticationMD5Password' - msg.salt = Buffer.alloc(4) - buffer.copy(msg.salt, 0, this.offset, this.offset + 4) - this.offset += 4 - return msg - } - - break - case 10: // AuthenticationSASL - msg.name = 'authenticationSASL' - msg.mechanisms = [] - do { - var mechanism = this.parseCString(buffer) - - if (mechanism) { - msg.mechanisms.push(mechanism) - } - } while (mechanism) - - return msg - case 11: // AuthenticationSASLContinue - msg.name = 'authenticationSASLContinue' - msg.data = this.readString(buffer, length - 4) - - return msg - case 12: // AuthenticationSASLFinal - msg.name = 'authenticationSASLFinal' - msg.data = this.readString(buffer, length - 4) - - return msg - } - - throw new Error('Unknown authenticationOk message type' + util.inspect(msg)) -} - -Connection.prototype.parseS = function (buffer, length) { - var msg = new Message('parameterStatus', length) - msg.parameterName = this.parseCString(buffer) - msg.parameterValue = this.parseCString(buffer) - return msg -} - -Connection.prototype.parseK = function (buffer, length) { - var msg = new Message('backendKeyData', length) - msg.processID = this.parseInt32(buffer) - msg.secretKey = this.parseInt32(buffer) - return msg -} - -Connection.prototype.parseC = function (buffer, length) { - var msg = new Message('commandComplete', length) - msg.text = this.parseCString(buffer) - return msg -} - -Connection.prototype.parseZ = function (buffer, length) { - var msg = new Message('readyForQuery', length) - msg.name = 'readyForQuery' - msg.status = this.readString(buffer, 1) - return msg -} - -var ROW_DESCRIPTION = 'rowDescription' -Connection.prototype.parseT = function (buffer, length) { - var msg = new Message(ROW_DESCRIPTION, length) - msg.fieldCount = this.parseInt16(buffer) - var fields = [] - for (var i = 0; i < msg.fieldCount; i++) { - fields.push(this.parseField(buffer)) - } - msg.fields = fields - return msg -} - -var Field = function () { - this.name = null - this.tableID = null - this.columnID = null - this.dataTypeID = null - this.dataTypeSize = null - this.dataTypeModifier = null - this.format = null -} - -var FORMAT_TEXT = 'text' -var FORMAT_BINARY = 'binary' -Connection.prototype.parseField = function (buffer) { - var field = new Field() - field.name = this.parseCString(buffer) - field.tableID = this.parseInt32(buffer) - field.columnID = this.parseInt16(buffer) - field.dataTypeID = this.parseInt32(buffer) - field.dataTypeSize = this.parseInt16(buffer) - field.dataTypeModifier = this.parseInt32(buffer) - if (this.parseInt16(buffer) === TEXT_MODE) { - this._mode = TEXT_MODE - field.format = FORMAT_TEXT - } else { - this._mode = BINARY_MODE - field.format = FORMAT_BINARY - } - return field -} - -var DATA_ROW = 'dataRow' -var DataRowMessage = function (length, fieldCount) { - this.name = DATA_ROW - this.length = length - this.fieldCount = fieldCount - this.fields = [] -} - -// extremely hot-path code -Connection.prototype.parseD = function (buffer, length) { - var fieldCount = this.parseInt16(buffer) - var msg = new DataRowMessage(length, fieldCount) - for (var i = 0; i < fieldCount; i++) { - msg.fields.push(this._readValue(buffer)) - } - return msg -} - -// extremely hot-path code -Connection.prototype._readValue = function (buffer) { - var length = this.parseInt32(buffer) - if (length === -1) return null - if (this._mode === TEXT_MODE) { - return this.readString(buffer, length) - } - return this.readBytes(buffer, length) -} - -// parses error -Connection.prototype.parseE = function (buffer, length) { - var fields = {} - var fieldType = this.readString(buffer, 1) - while (fieldType !== '\0') { - fields[fieldType] = this.parseCString(buffer) - fieldType = this.readString(buffer, 1) - } - - // the msg is an Error instance - var msg = new Error(fields.M) - - // for compatibility with Message - msg.name = 'error' - msg.length = length - - msg.severity = fields.S - msg.code = fields.C - msg.detail = fields.D - msg.hint = fields.H - msg.position = fields.P - msg.internalPosition = fields.p - msg.internalQuery = fields.q - msg.where = fields.W - msg.schema = fields.s - msg.table = fields.t - msg.column = fields.c - msg.dataType = fields.d - msg.constraint = fields.n - msg.file = fields.F - msg.line = fields.L - msg.routine = fields.R - return msg -} - -// same thing, different name -Connection.prototype.parseN = function (buffer, length) { - var msg = this.parseE(buffer, length) - msg.name = 'notice' - return msg -} - -Connection.prototype.parseA = function (buffer, length) { - var msg = new Message('notification', length) - msg.processId = this.parseInt32(buffer) - msg.channel = this.parseCString(buffer) - msg.payload = this.parseCString(buffer) - return msg -} - -Connection.prototype.parseG = function (buffer, length) { - var msg = new Message('copyInResponse', length) - return this.parseGH(buffer, msg) -} - -Connection.prototype.parseH = function (buffer, length) { - var msg = new Message('copyOutResponse', length) - return this.parseGH(buffer, msg) -} - -Connection.prototype.parseGH = function (buffer, msg) { - var isBinary = buffer[this.offset] !== 0 - this.offset++ - msg.binary = isBinary - var columnCount = this.parseInt16(buffer) - msg.columnTypes = [] - for (var i = 0; i < columnCount; i++) { - msg.columnTypes.push(this.parseInt16(buffer)) - } - return msg -} - -Connection.prototype.parsed = function (buffer, length) { - var msg = new Message('copyData', length) - msg.chunk = this.readBytes(buffer, msg.length - 4) - return msg -} - -Connection.prototype.parseInt32 = function (buffer) { - var value = buffer.readInt32BE(this.offset) - this.offset += 4 - return value -} - -Connection.prototype.parseInt16 = function (buffer) { - var value = buffer.readInt16BE(this.offset) - this.offset += 2 - return value -} - -Connection.prototype.readString = function (buffer, length) { - return buffer.toString(this.encoding, this.offset, (this.offset += length)) -} - -Connection.prototype.readBytes = function (buffer, length) { - return buffer.slice(this.offset, (this.offset += length)) -} - -Connection.prototype.parseCString = function (buffer) { - var start = this.offset - var end = buffer.indexOf(0, start) - this.offset = end + 1 - return buffer.toString(this.encoding, start, end) -} -// end parsing methods module.exports = Connection diff --git a/packages/pg/lib/result.js b/packages/pg/lib/result.js index 7e59a413e..d959e808a 100644 --- a/packages/pg/lib/result.js +++ b/packages/pg/lib/result.js @@ -16,9 +16,9 @@ var Result = function (rowMode, types) { this.command = null this.rowCount = null this.oid = null - this.rows = []; - this.fields = undefined; - this._parsers = undefined; + this.rows = [] + this.fields = undefined + this._parsers = undefined this._types = types this.RowCtor = null this.rowAsArray = rowMode === 'array' @@ -88,14 +88,14 @@ Result.prototype.addFields = function (fieldDescriptions) { // multiple query statements in 1 action can result in multiple sets // of rowDescriptions...eg: 'select NOW(); select 1::int;' // you need to reset the fields - this.fields = fieldDescriptions; + this.fields = fieldDescriptions if (this.fields.length) { - this._parsers = new Array(fieldDescriptions.length); + this._parsers = new Array(fieldDescriptions.length) } for (var i = 0; i < fieldDescriptions.length; i++) { var desc = fieldDescriptions[i] if (this._types) { - this._parsers[i] = this._types.getTypeParser(desc.dataTypeID, desc.format || 'text'); + this._parsers[i] = this._types.getTypeParser(desc.dataTypeID, desc.format || 'text') } else { this._parsers[i] = types.getTypeParser(desc.dataTypeID, desc.format || 'text') } From 86073026eeec58b28d03ae971e11562bc4560524 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 20 Dec 2019 12:09:22 -0600 Subject: [PATCH 0548/1037] Run gitsubtree merge --- .../pg-packet-stream/dist/BufferReader.js | 48 ++ .../pg-packet-stream/dist/BufferReader.js.map | 1 + .../dist/inbound-parser.test.js | 469 ++++++++++++++++ .../dist/inbound-parser.test.js.map | 1 + packages/pg-packet-stream/dist/index.js | 264 +++++++++ packages/pg-packet-stream/dist/index.js.map | 1 + packages/pg-packet-stream/dist/index.test.js | 109 ++++ .../pg-packet-stream/dist/index.test.js.map | 1 + packages/pg-packet-stream/dist/messages.js | 134 +++++ .../pg-packet-stream/dist/messages.js.map | 1 + .../dist/testing/buffer-list.js | 73 +++ .../dist/testing/buffer-list.js.map | 1 + .../dist/testing/test-buffers.js | 164 ++++++ .../dist/testing/test-buffers.js.map | 1 + yarn.lock | 511 +++++++++++++++++- 15 files changed, 1760 insertions(+), 19 deletions(-) create mode 100644 packages/pg-packet-stream/dist/BufferReader.js create mode 100644 packages/pg-packet-stream/dist/BufferReader.js.map create mode 100644 packages/pg-packet-stream/dist/inbound-parser.test.js create mode 100644 packages/pg-packet-stream/dist/inbound-parser.test.js.map create mode 100644 packages/pg-packet-stream/dist/index.js create mode 100644 packages/pg-packet-stream/dist/index.js.map create mode 100644 packages/pg-packet-stream/dist/index.test.js create mode 100644 packages/pg-packet-stream/dist/index.test.js.map create mode 100644 packages/pg-packet-stream/dist/messages.js create mode 100644 packages/pg-packet-stream/dist/messages.js.map create mode 100644 packages/pg-packet-stream/dist/testing/buffer-list.js create mode 100644 packages/pg-packet-stream/dist/testing/buffer-list.js.map create mode 100644 packages/pg-packet-stream/dist/testing/test-buffers.js create mode 100644 packages/pg-packet-stream/dist/testing/test-buffers.js.map diff --git a/packages/pg-packet-stream/dist/BufferReader.js b/packages/pg-packet-stream/dist/BufferReader.js new file mode 100644 index 000000000..60186a51c --- /dev/null +++ b/packages/pg-packet-stream/dist/BufferReader.js @@ -0,0 +1,48 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const emptyBuffer = Buffer.allocUnsafe(0); +class BufferReader { + constructor(offset = 0) { + this.offset = offset; + this.buffer = emptyBuffer; + // TODO(bmc): support non-utf8 encoding + this.encoding = 'utf-8'; + } + setBuffer(offset, buffer) { + this.offset = offset; + this.buffer = buffer; + } + int16() { + const result = this.buffer.readInt16BE(this.offset); + this.offset += 2; + return result; + } + byte() { + const result = this.buffer[this.offset]; + this.offset++; + return result; + } + int32() { + const result = this.buffer.readInt32BE(this.offset); + this.offset += 4; + return result; + } + string(length) { + const result = this.buffer.toString(this.encoding, this.offset, this.offset + length); + this.offset += length; + return result; + } + cstring() { + var start = this.offset; + var end = this.buffer.indexOf(0, start); + this.offset = end + 1; + return this.buffer.toString(this.encoding, start, end); + } + bytes(length) { + const result = this.buffer.slice(this.offset, this.offset + length); + this.offset += length; + return result; + } +} +exports.BufferReader = BufferReader; +//# sourceMappingURL=BufferReader.js.map \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/BufferReader.js.map b/packages/pg-packet-stream/dist/BufferReader.js.map new file mode 100644 index 000000000..a4c367c7d --- /dev/null +++ b/packages/pg-packet-stream/dist/BufferReader.js.map @@ -0,0 +1 @@ +{"version":3,"file":"BufferReader.js","sourceRoot":"","sources":["../src/BufferReader.ts"],"names":[],"mappings":";;AAAA,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAE1C,MAAa,YAAY;IAIvB,YAAoB,SAAiB,CAAC;QAAlB,WAAM,GAAN,MAAM,CAAY;QAH9B,WAAM,GAAW,WAAW,CAAC;QACrC,uCAAuC;QAC/B,aAAQ,GAAW,OAAO,CAAC;IAEnC,CAAC;IACM,SAAS,CAAC,MAAc,EAAE,MAAc;QAC7C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IACM,KAAK;QACV,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;QACjB,OAAO,MAAM,CAAC;IAChB,CAAC;IACM,IAAI;QACT,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,MAAM,CAAC;IAChB,CAAC;IACM,KAAK;QACV,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;QACjB,OAAO,MAAM,CAAC;IAChB,CAAC;IACM,MAAM,CAAC,MAAc;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QACtF,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC;QACtB,OAAO,MAAM,CAAC;IAChB,CAAC;IACM,OAAO;QACZ,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;QACxB,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IACzD,CAAC;IACM,KAAK,CAAC,MAAc;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QACpE,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC;QACtB,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAzCD,oCAyCC"} \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/inbound-parser.test.js b/packages/pg-packet-stream/dist/inbound-parser.test.js new file mode 100644 index 000000000..288ea9656 --- /dev/null +++ b/packages/pg-packet-stream/dist/inbound-parser.test.js @@ -0,0 +1,469 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const test_buffers_1 = __importDefault(require("./testing/test-buffers")); +const buffer_list_1 = __importDefault(require("./testing/buffer-list")); +const _1 = require("./"); +const assert_1 = __importDefault(require("assert")); +var authOkBuffer = test_buffers_1.default.authenticationOk(); +var paramStatusBuffer = test_buffers_1.default.parameterStatus('client_encoding', 'UTF8'); +var readyForQueryBuffer = test_buffers_1.default.readyForQuery(); +var backendKeyDataBuffer = test_buffers_1.default.backendKeyData(1, 2); +var commandCompleteBuffer = test_buffers_1.default.commandComplete('SELECT 3'); +var parseCompleteBuffer = test_buffers_1.default.parseComplete(); +var bindCompleteBuffer = test_buffers_1.default.bindComplete(); +var portalSuspendedBuffer = test_buffers_1.default.portalSuspended(); +var addRow = function (bufferList, name, offset) { + return bufferList.addCString(name) // field name + .addInt32(offset++) // table id + .addInt16(offset++) // attribute of column number + .addInt32(offset++) // objectId of field's data type + .addInt16(offset++) // datatype size + .addInt32(offset++) // type modifier + .addInt16(0); // format code, 0 => text +}; +var row1 = { + name: 'id', + tableID: 1, + attributeNumber: 2, + dataTypeID: 3, + dataTypeSize: 4, + typeModifier: 5, + formatCode: 0 +}; +var oneRowDescBuff = test_buffers_1.default.rowDescription([row1]); +row1.name = 'bang'; +var twoRowBuf = test_buffers_1.default.rowDescription([row1, { + name: 'whoah', + tableID: 10, + attributeNumber: 11, + dataTypeID: 12, + dataTypeSize: 13, + typeModifier: 14, + formatCode: 0 + }]); +var emptyRowFieldBuf = new buffer_list_1.default() + .addInt16(0) + .join(true, 'D'); +var emptyRowFieldBuf = test_buffers_1.default.dataRow([]); +var oneFieldBuf = new buffer_list_1.default() + .addInt16(1) // number of fields + .addInt32(5) // length of bytes of fields + .addCString('test') + .join(true, 'D'); +var oneFieldBuf = test_buffers_1.default.dataRow(['test']); +var expectedAuthenticationOkayMessage = { + name: 'authenticationOk', + length: 8 +}; +var expectedParameterStatusMessage = { + name: 'parameterStatus', + parameterName: 'client_encoding', + parameterValue: 'UTF8', + length: 25 +}; +var expectedBackendKeyDataMessage = { + name: 'backendKeyData', + processID: 1, + secretKey: 2 +}; +var expectedReadyForQueryMessage = { + name: 'readyForQuery', + length: 5, + status: 'I' +}; +var expectedCommandCompleteMessage = { + name: 'commandComplete', + length: 13, + text: 'SELECT 3' +}; +var emptyRowDescriptionBuffer = new buffer_list_1.default() + .addInt16(0) // number of fields + .join(true, 'T'); +var expectedEmptyRowDescriptionMessage = { + name: 'rowDescription', + length: 6, + fieldCount: 0, + fields: [], +}; +var expectedOneRowMessage = { + name: 'rowDescription', + length: 27, + fieldCount: 1, + fields: [{ + name: 'id', + tableID: 1, + columnID: 2, + dataTypeID: 3, + dataTypeSize: 4, + dataTypeModifier: 5, + format: 'text' + }] +}; +var expectedTwoRowMessage = { + name: 'rowDescription', + length: 53, + fieldCount: 2, + fields: [{ + name: 'bang', + tableID: 1, + columnID: 2, + dataTypeID: 3, + dataTypeSize: 4, + dataTypeModifier: 5, + format: 'text' + }, + { + name: 'whoah', + tableID: 10, + columnID: 11, + dataTypeID: 12, + dataTypeSize: 13, + dataTypeModifier: 14, + format: 'text' + }] +}; +const concat = (stream) => { + return new Promise((resolve) => { + const results = []; + stream.on('data', item => results.push(item)); + stream.on('end', () => resolve(results)); + }); +}; +var testForMessage = function (buffer, expectedMessage) { + it('recieves and parses ' + expectedMessage.name, () => __awaiter(this, void 0, void 0, function* () { + const parser = new _1.PgPacketStream(); + parser.write(buffer); + parser.end(); + const [lastMessage] = yield concat(parser); + for (const key in expectedMessage) { + assert_1.default.deepEqual(lastMessage[key], expectedMessage[key]); + } + })); +}; +var plainPasswordBuffer = test_buffers_1.default.authenticationCleartextPassword(); +var md5PasswordBuffer = test_buffers_1.default.authenticationMD5Password(); +var SASLBuffer = test_buffers_1.default.authenticationSASL(); +var SASLContinueBuffer = test_buffers_1.default.authenticationSASLContinue(); +var SASLFinalBuffer = test_buffers_1.default.authenticationSASLFinal(); +var expectedPlainPasswordMessage = { + name: 'authenticationCleartextPassword' +}; +var expectedMD5PasswordMessage = { + name: 'authenticationMD5Password', + salt: Buffer.from([1, 2, 3, 4]) +}; +var expectedSASLMessage = { + name: 'authenticationSASL', + mechanisms: ['SCRAM-SHA-256'] +}; +var expectedSASLContinueMessage = { + name: 'authenticationSASLContinue', + data: 'data', +}; +var expectedSASLFinalMessage = { + name: 'authenticationSASLFinal', + data: 'data', +}; +var notificationResponseBuffer = test_buffers_1.default.notification(4, 'hi', 'boom'); +var expectedNotificationResponseMessage = { + name: 'notification', + processId: 4, + channel: 'hi', + payload: 'boom' +}; +describe('PgPacketStream', function () { + testForMessage(authOkBuffer, expectedAuthenticationOkayMessage); + testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage); + testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage); + testForMessage(SASLBuffer, expectedSASLMessage); + testForMessage(SASLContinueBuffer, expectedSASLContinueMessage); + testForMessage(SASLFinalBuffer, expectedSASLFinalMessage); + testForMessage(paramStatusBuffer, expectedParameterStatusMessage); + testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage); + testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage); + testForMessage(commandCompleteBuffer, expectedCommandCompleteMessage); + testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage); + testForMessage(test_buffers_1.default.emptyQuery(), { + name: 'emptyQuery', + length: 4, + }); + testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), { + name: 'noData' + }); + describe('rowDescription messages', function () { + testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage); + testForMessage(oneRowDescBuff, expectedOneRowMessage); + testForMessage(twoRowBuf, expectedTwoRowMessage); + }); + describe('parsing rows', function () { + describe('parsing empty row', function () { + testForMessage(emptyRowFieldBuf, { + name: 'dataRow', + fieldCount: 0 + }); + }); + describe('parsing data row with fields', function () { + testForMessage(oneFieldBuf, { + name: 'dataRow', + fieldCount: 1, + fields: ['test'] + }); + }); + }); + describe('notice message', function () { + // this uses the same logic as error message + var buff = test_buffers_1.default.notice([{ type: 'C', value: 'code' }]); + testForMessage(buff, { + name: 'notice', + code: 'code' + }); + }); + testForMessage(test_buffers_1.default.error([]), { + name: 'error' + }); + describe('with all the fields', function () { + var buffer = test_buffers_1.default.error([{ + type: 'S', + value: 'ERROR' + }, { + type: 'C', + value: 'code' + }, { + type: 'M', + value: 'message' + }, { + type: 'D', + value: 'details' + }, { + type: 'H', + value: 'hint' + }, { + type: 'P', + value: '100' + }, { + type: 'p', + value: '101' + }, { + type: 'q', + value: 'query' + }, { + type: 'W', + value: 'where' + }, { + type: 'F', + value: 'file' + }, { + type: 'L', + value: 'line' + }, { + type: 'R', + value: 'routine' + }, { + type: 'Z', + value: 'alsdkf' + }]); + testForMessage(buffer, { + name: 'error', + severity: 'ERROR', + code: 'code', + message: 'message', + detail: 'details', + hint: 'hint', + position: '100', + internalPosition: '101', + internalQuery: 'query', + where: 'where', + file: 'file', + line: 'line', + routine: 'routine' + }); + }); + testForMessage(parseCompleteBuffer, { + name: 'parseComplete' + }); + testForMessage(bindCompleteBuffer, { + name: 'bindComplete' + }); + testForMessage(bindCompleteBuffer, { + name: 'bindComplete' + }); + testForMessage(test_buffers_1.default.closeComplete(), { + name: 'closeComplete' + }); + describe('parses portal suspended message', function () { + testForMessage(portalSuspendedBuffer, { + name: 'portalSuspended' + }); + }); + describe('parses replication start message', function () { + testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { + name: 'replicationStart', + length: 4 + }); + }); + describe('copy', () => { + testForMessage(test_buffers_1.default.copyIn(0), { + name: 'copyInResponse', + length: 7, + binary: false, + columnTypes: [] + }); + testForMessage(test_buffers_1.default.copyIn(2), { + name: 'copyInResponse', + length: 11, + binary: false, + columnTypes: [0, 1] + }); + testForMessage(test_buffers_1.default.copyOut(0), { + name: 'copyOutResponse', + length: 7, + binary: false, + columnTypes: [] + }); + testForMessage(test_buffers_1.default.copyOut(3), { + name: 'copyOutResponse', + length: 13, + binary: false, + columnTypes: [0, 1, 2] + }); + testForMessage(test_buffers_1.default.copyDone(), { + name: 'copyDone', + length: 4, + }); + testForMessage(test_buffers_1.default.copyData(Buffer.from([5, 6, 7])), { + name: 'copyData', + length: 7, + chunk: Buffer.from([5, 6, 7]) + }); + }); + // since the data message on a stream can randomly divide the incomming + // tcp packets anywhere, we need to make sure we can parse every single + // split on a tcp message + describe('split buffer, single message parsing', function () { + var fullBuffer = test_buffers_1.default.dataRow([null, 'bang', 'zug zug', null, '!']); + const parse = (buffers) => __awaiter(this, void 0, void 0, function* () { + const parser = new _1.PgPacketStream(); + for (const buffer of buffers) { + parser.write(buffer); + } + parser.end(); + const [msg] = yield concat(parser); + return msg; + }); + it('parses when full buffer comes in', function () { + return __awaiter(this, void 0, void 0, function* () { + const message = yield parse([fullBuffer]); + assert_1.default.equal(message.fields.length, 5); + assert_1.default.equal(message.fields[0], null); + assert_1.default.equal(message.fields[1], 'bang'); + assert_1.default.equal(message.fields[2], 'zug zug'); + assert_1.default.equal(message.fields[3], null); + assert_1.default.equal(message.fields[4], '!'); + }); + }); + var testMessageRecievedAfterSpiltAt = function (split) { + return __awaiter(this, void 0, void 0, function* () { + var firstBuffer = Buffer.alloc(fullBuffer.length - split); + var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length); + fullBuffer.copy(firstBuffer, 0, 0); + fullBuffer.copy(secondBuffer, 0, firstBuffer.length); + const message = yield parse([firstBuffer, secondBuffer]); + assert_1.default.equal(message.fields.length, 5); + assert_1.default.equal(message.fields[0], null); + assert_1.default.equal(message.fields[1], 'bang'); + assert_1.default.equal(message.fields[2], 'zug zug'); + assert_1.default.equal(message.fields[3], null); + assert_1.default.equal(message.fields[4], '!'); + }); + }; + it('parses when split in the middle', function () { + testMessageRecievedAfterSpiltAt(6); + }); + it('parses when split at end', function () { + testMessageRecievedAfterSpiltAt(2); + }); + it('parses when split at beginning', function () { + testMessageRecievedAfterSpiltAt(fullBuffer.length - 2); + testMessageRecievedAfterSpiltAt(fullBuffer.length - 1); + testMessageRecievedAfterSpiltAt(fullBuffer.length - 5); + }); + }); + describe('split buffer, multiple message parsing', function () { + var dataRowBuffer = test_buffers_1.default.dataRow(['!']); + var readyForQueryBuffer = test_buffers_1.default.readyForQuery(); + var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length); + dataRowBuffer.copy(fullBuffer, 0, 0); + readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0); + const parse = (buffers) => { + const parser = new _1.PgPacketStream(); + for (const buffer of buffers) { + parser.write(buffer); + } + parser.end(); + return concat(parser); + }; + var verifyMessages = function (messages) { + assert_1.default.strictEqual(messages.length, 2); + assert_1.default.deepEqual(messages[0], { + name: 'dataRow', + fieldCount: 1, + length: 11, + fields: ['!'] + }); + assert_1.default.equal(messages[0].fields[0], '!'); + assert_1.default.deepEqual(messages[1], { + name: 'readyForQuery', + length: 5, + status: 'I' + }); + }; + // sanity check + it('recieves both messages when packet is not split', function () { + return __awaiter(this, void 0, void 0, function* () { + const messages = yield parse([fullBuffer]); + verifyMessages(messages); + }); + }); + var splitAndVerifyTwoMessages = function (split) { + return __awaiter(this, void 0, void 0, function* () { + var firstBuffer = Buffer.alloc(fullBuffer.length - split); + var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length); + fullBuffer.copy(firstBuffer, 0, 0); + fullBuffer.copy(secondBuffer, 0, firstBuffer.length); + const messages = yield parse([firstBuffer, secondBuffer]); + verifyMessages(messages); + }); + }; + describe('recieves both messages when packet is split', function () { + it('in the middle', function () { + return splitAndVerifyTwoMessages(11); + }); + it('at the front', function () { + return Promise.all([ + splitAndVerifyTwoMessages(fullBuffer.length - 1), + splitAndVerifyTwoMessages(fullBuffer.length - 4), + splitAndVerifyTwoMessages(fullBuffer.length - 6) + ]); + }); + it('at the end', function () { + return Promise.all([ + splitAndVerifyTwoMessages(8), + splitAndVerifyTwoMessages(1) + ]); + }); + }); + }); +}); +//# sourceMappingURL=inbound-parser.test.js.map \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/inbound-parser.test.js.map b/packages/pg-packet-stream/dist/inbound-parser.test.js.map new file mode 100644 index 000000000..8689edf67 --- /dev/null +++ b/packages/pg-packet-stream/dist/inbound-parser.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"inbound-parser.test.js","sourceRoot":"","sources":["../src/inbound-parser.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,0EAA4C;AAC5C,wEAA8C;AAC9C,yBAAmC;AACnC,oDAA2B;AAG3B,IAAI,YAAY,GAAG,sBAAO,CAAC,gBAAgB,EAAE,CAAA;AAC7C,IAAI,iBAAiB,GAAG,sBAAO,CAAC,eAAe,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAA;AAC1E,IAAI,mBAAmB,GAAG,sBAAO,CAAC,aAAa,EAAE,CAAA;AACjD,IAAI,oBAAoB,GAAG,sBAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AACvD,IAAI,qBAAqB,GAAG,sBAAO,CAAC,eAAe,CAAC,UAAU,CAAC,CAAA;AAC/D,IAAI,mBAAmB,GAAG,sBAAO,CAAC,aAAa,EAAE,CAAA;AACjD,IAAI,kBAAkB,GAAG,sBAAO,CAAC,YAAY,EAAE,CAAA;AAC/C,IAAI,qBAAqB,GAAG,sBAAO,CAAC,eAAe,EAAE,CAAA;AAErD,IAAI,MAAM,GAAG,UAAU,UAAsB,EAAE,IAAY,EAAE,MAAc;IACzE,OAAO,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,aAAa;SAC7C,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,WAAW;SAC9B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,6BAA6B;SAChD,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,gCAAgC;SACnD,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,gBAAgB;SACnC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,gBAAgB;SACnC,QAAQ,CAAC,CAAC,CAAC,CAAA,CAAC,yBAAyB;AAC1C,CAAC,CAAA;AAED,IAAI,IAAI,GAAG;IACT,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,CAAC;IACV,eAAe,EAAE,CAAC;IAClB,UAAU,EAAE,CAAC;IACb,YAAY,EAAE,CAAC;IACf,YAAY,EAAE,CAAC;IACf,UAAU,EAAE,CAAC;CACd,CAAA;AACD,IAAI,cAAc,GAAG,sBAAO,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;AACnD,IAAI,CAAC,IAAI,GAAG,MAAM,CAAA;AAElB,IAAI,SAAS,GAAG,sBAAO,CAAC,cAAc,CAAC,CAAC,IAAI,EAAE;QAC5C,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,EAAE;QACX,eAAe,EAAE,EAAE;QACnB,UAAU,EAAE,EAAE;QACd,YAAY,EAAE,EAAE;QAChB,YAAY,EAAE,EAAE;QAChB,UAAU,EAAE,CAAC;KACd,CAAC,CAAC,CAAA;AAEH,IAAI,gBAAgB,GAAG,IAAI,qBAAU,EAAE;KACpC,QAAQ,CAAC,CAAC,CAAC;KACX,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAElB,IAAI,gBAAgB,GAAG,sBAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;AAE1C,IAAI,WAAW,GAAG,IAAI,qBAAU,EAAE;KAC/B,QAAQ,CAAC,CAAC,CAAC,CAAC,mBAAmB;KAC/B,QAAQ,CAAC,CAAC,CAAC,CAAC,4BAA4B;KACxC,UAAU,CAAC,MAAM,CAAC;KAClB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAElB,IAAI,WAAW,GAAG,sBAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AAE3C,IAAI,iCAAiC,GAAG;IACtC,IAAI,EAAE,kBAAkB;IACxB,MAAM,EAAE,CAAC;CACV,CAAA;AAED,IAAI,8BAA8B,GAAG;IACnC,IAAI,EAAE,iBAAiB;IACvB,aAAa,EAAE,iBAAiB;IAChC,cAAc,EAAE,MAAM;IACtB,MAAM,EAAE,EAAE;CACX,CAAA;AAED,IAAI,6BAA6B,GAAG;IAClC,IAAI,EAAE,gBAAgB;IACtB,SAAS,EAAE,CAAC;IACZ,SAAS,EAAE,CAAC;CACb,CAAA;AAED,IAAI,4BAA4B,GAAG;IACjC,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,GAAG;CACZ,CAAA;AAED,IAAI,8BAA8B,GAAG;IACnC,IAAI,EAAE,iBAAiB;IACvB,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,UAAU;CACjB,CAAA;AACD,IAAI,yBAAyB,GAAG,IAAI,qBAAU,EAAE;KAC7C,QAAQ,CAAC,CAAC,CAAC,CAAC,mBAAmB;KAC/B,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAElB,IAAI,kCAAkC,GAAG;IACvC,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,CAAC;IACT,UAAU,EAAE,CAAC;IACb,MAAM,EAAE,EAAE;CACX,CAAA;AACD,IAAI,qBAAqB,GAAG;IAC1B,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,EAAE;IACV,UAAU,EAAE,CAAC;IACb,MAAM,EAAE,CAAC;YACP,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,CAAC;YACX,UAAU,EAAE,CAAC;YACb,YAAY,EAAE,CAAC;YACf,gBAAgB,EAAE,CAAC;YACnB,MAAM,EAAE,MAAM;SACf,CAAC;CACH,CAAA;AAED,IAAI,qBAAqB,GAAG;IAC1B,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,EAAE;IACV,UAAU,EAAE,CAAC;IACb,MAAM,EAAE,CAAC;YACP,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,CAAC;YACX,UAAU,EAAE,CAAC;YACb,YAAY,EAAE,CAAC;YACf,gBAAgB,EAAE,CAAC;YACnB,MAAM,EAAE,MAAM;SACf;QACD;YACE,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,EAAE;YACZ,UAAU,EAAE,EAAE;YACd,YAAY,EAAE,EAAE;YAChB,gBAAgB,EAAE,EAAE;YACpB,MAAM,EAAE,MAAM;SACf,CAAC;CACH,CAAA;AAED,MAAM,MAAM,GAAG,CAAC,MAAgB,EAAkB,EAAE;IAClD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,OAAO,GAAU,EAAE,CAAA;QACzB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;QAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AAED,IAAI,cAAc,GAAG,UAAU,MAAc,EAAE,eAAoB;IACjE,EAAE,CAAC,sBAAsB,GAAG,eAAe,CAAC,IAAI,EAAE,GAAS,EAAE;QAC3D,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACrB,MAAM,CAAC,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,WAAW,CAAC,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QAE3C,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE;YACjC,gBAAM,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,CAAA;SACzD;IAEH,CAAC,CAAA,CAAC,CAAA;AACJ,CAAC,CAAA;AAED,IAAI,mBAAmB,GAAG,sBAAO,CAAC,+BAA+B,EAAE,CAAA;AACnE,IAAI,iBAAiB,GAAG,sBAAO,CAAC,yBAAyB,EAAE,CAAA;AAC3D,IAAI,UAAU,GAAG,sBAAO,CAAC,kBAAkB,EAAE,CAAA;AAC7C,IAAI,kBAAkB,GAAG,sBAAO,CAAC,0BAA0B,EAAE,CAAA;AAC7D,IAAI,eAAe,GAAG,sBAAO,CAAC,uBAAuB,EAAE,CAAA;AAEvD,IAAI,4BAA4B,GAAG;IACjC,IAAI,EAAE,iCAAiC;CACxC,CAAA;AAED,IAAI,0BAA0B,GAAG;IAC/B,IAAI,EAAE,2BAA2B;IACjC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;CAChC,CAAA;AAED,IAAI,mBAAmB,GAAG;IACxB,IAAI,EAAE,oBAAoB;IAC1B,UAAU,EAAE,CAAC,eAAe,CAAC;CAC9B,CAAA;AAED,IAAI,2BAA2B,GAAG;IAChC,IAAI,EAAE,4BAA4B;IAClC,IAAI,EAAE,MAAM;CACb,CAAA;AAED,IAAI,wBAAwB,GAAG;IAC7B,IAAI,EAAE,yBAAyB;IAC/B,IAAI,EAAE,MAAM;CACb,CAAA;AAED,IAAI,0BAA0B,GAAG,sBAAO,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;AACtE,IAAI,mCAAmC,GAAG;IACxC,IAAI,EAAE,cAAc;IACpB,SAAS,EAAE,CAAC;IACZ,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,MAAM;CAChB,CAAA;AAED,QAAQ,CAAC,gBAAgB,EAAE;IACzB,cAAc,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAA;IAC/D,cAAc,CAAC,mBAAmB,EAAE,4BAA4B,CAAC,CAAA;IACjE,cAAc,CAAC,iBAAiB,EAAE,0BAA0B,CAAC,CAAA;IAC7D,cAAc,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAA;IAC/C,cAAc,CAAC,kBAAkB,EAAE,2BAA2B,CAAC,CAAA;IAC/D,cAAc,CAAC,eAAe,EAAE,wBAAwB,CAAC,CAAA;IAEzD,cAAc,CAAC,iBAAiB,EAAE,8BAA8B,CAAC,CAAA;IACjE,cAAc,CAAC,oBAAoB,EAAE,6BAA6B,CAAC,CAAA;IACnE,cAAc,CAAC,mBAAmB,EAAE,4BAA4B,CAAC,CAAA;IACjE,cAAc,CAAC,qBAAqB,EAAE,8BAA8B,CAAC,CAAA;IACrE,cAAc,CAAC,0BAA0B,EAAE,mCAAmC,CAAC,CAAA;IAC/E,cAAc,CAAC,sBAAO,CAAC,UAAU,EAAE,EAAE;QACnC,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,CAAC;KACV,CAAC,CAAA;IAEF,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;QAC9C,IAAI,EAAE,QAAQ;KACf,CAAC,CAAA;IAEF,QAAQ,CAAC,yBAAyB,EAAE;QAClC,cAAc,CAAC,yBAAyB,EAAE,kCAAkC,CAAC,CAAA;QAC7E,cAAc,CAAC,cAAc,EAAE,qBAAqB,CAAC,CAAA;QACrD,cAAc,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,cAAc,EAAE;QACvB,QAAQ,CAAC,mBAAmB,EAAE;YAC5B,cAAc,CAAC,gBAAgB,EAAE;gBAC/B,IAAI,EAAE,SAAS;gBACf,UAAU,EAAE,CAAC;aACd,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;QAEF,QAAQ,CAAC,8BAA8B,EAAE;YACvC,cAAc,CAAC,WAAW,EAAE;gBAC1B,IAAI,EAAE,SAAS;gBACf,UAAU,EAAE,CAAC;gBACb,MAAM,EAAE,CAAC,MAAM,CAAC;aACjB,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,gBAAgB,EAAE;QACzB,4CAA4C;QAC5C,IAAI,IAAI,GAAG,sBAAO,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;QACzD,cAAc,CAAC,IAAI,EAAE;YACnB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,MAAM;SACb,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,cAAc,CAAC,sBAAO,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE;QAChC,IAAI,EAAE,OAAO;KACd,CAAC,CAAA;IAEF,QAAQ,CAAC,qBAAqB,EAAE;QAC9B,IAAI,MAAM,GAAG,sBAAO,CAAC,KAAK,CAAC,CAAC;gBAC1B,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,OAAO;aACf,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,MAAM;aACd,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,SAAS;aACjB,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,SAAS;aACjB,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,MAAM;aACd,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,KAAK;aACb,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,KAAK;aACb,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,OAAO;aACf,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,OAAO;aACf,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,MAAM;aACd,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,MAAM;aACd,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,SAAS;aACjB,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,QAAQ;aAChB,CAAC,CAAC,CAAA;QAEH,cAAc,CAAC,MAAM,EAAE;YACrB,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,SAAS;YAClB,MAAM,EAAE,SAAS;YACjB,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,KAAK;YACf,gBAAgB,EAAE,KAAK;YACvB,aAAa,EAAE,OAAO;YACtB,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,SAAS;SACnB,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,cAAc,CAAC,mBAAmB,EAAE;QAClC,IAAI,EAAE,eAAe;KACtB,CAAC,CAAA;IAEF,cAAc,CAAC,kBAAkB,EAAE;QACjC,IAAI,EAAE,cAAc;KACrB,CAAC,CAAA;IAEF,cAAc,CAAC,kBAAkB,EAAE;QACjC,IAAI,EAAE,cAAc;KACrB,CAAC,CAAA;IAEF,cAAc,CAAC,sBAAO,CAAC,aAAa,EAAE,EAAE;QACtC,IAAI,EAAE,eAAe;KACtB,CAAC,CAAA;IAEF,QAAQ,CAAC,iCAAiC,EAAE;QAC1C,cAAc,CAAC,qBAAqB,EAAE;YACpC,IAAI,EAAE,iBAAiB;SACxB,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,kCAAkC,EAAE;QAC3C,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE;YAC1D,IAAI,EAAE,kBAAkB;YACxB,MAAM,EAAE,CAAC;SACV,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;QACpB,cAAc,CAAC,sBAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;YAChC,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,KAAK;YACb,WAAW,EAAE,EAAE;SAChB,CAAC,CAAA;QAEF,cAAc,CAAC,sBAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;YAChC,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,KAAK;YACb,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;SACpB,CAAC,CAAA;QAEF,cAAc,CAAC,sBAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YACjC,IAAI,EAAE,iBAAiB;YACvB,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,KAAK;YACb,WAAW,EAAE,EAAE;SAChB,CAAC,CAAA;QAEF,cAAc,CAAC,sBAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YACjC,IAAI,EAAE,iBAAiB;YACvB,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,KAAK;YACb,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;SACvB,CAAC,CAAA;QAEF,cAAc,CAAC,sBAAO,CAAC,QAAQ,EAAE,EAAE;YACjC,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,CAAC;SACV,CAAC,CAAA;QAEF,cAAc,CAAC,sBAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;YACvD,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;SAC9B,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAGF,uEAAuE;IACvE,uEAAuE;IACvE,yBAAyB;IACzB,QAAQ,CAAC,sCAAsC,EAAE;QAC/C,IAAI,UAAU,GAAG,sBAAO,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAA;QAEtE,MAAM,KAAK,GAAG,CAAO,OAAiB,EAAgB,EAAE;YACtD,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAC;YACpC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;gBAC5B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;aACtB;YACD,MAAM,CAAC,GAAG,EAAE,CAAA;YACZ,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAA;YAClC,OAAO,GAAG,CAAC;QACb,CAAC,CAAA,CAAA;QAED,EAAE,CAAC,kCAAkC,EAAE;;gBACrC,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;gBAC1C,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;gBACtC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;gBACrC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;gBACvC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;gBAC1C,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;gBACrC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;YACtC,CAAC;SAAA,CAAC,CAAA;QAEF,IAAI,+BAA+B,GAAG,UAAgB,KAAa;;gBACjE,IAAI,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,KAAK,CAAC,CAAA;gBACzD,IAAI,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;gBACvE,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;gBAClC,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;gBACpD,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC;gBACzD,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;gBACtC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;gBACrC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;gBACvC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;gBAC1C,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;gBACrC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;YACtC,CAAC;SAAA,CAAA;QAED,EAAE,CAAC,iCAAiC,EAAE;YACpC,+BAA+B,CAAC,CAAC,CAAC,CAAA;QACpC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,0BAA0B,EAAE;YAC7B,+BAA+B,CAAC,CAAC,CAAC,CAAA;QACpC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,gCAAgC,EAAE;YACnC,+BAA+B,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;YACtD,+BAA+B,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;YACtD,+BAA+B,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QACxD,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,wCAAwC,EAAE;QACjD,IAAI,aAAa,GAAG,sBAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QAC1C,IAAI,mBAAmB,GAAG,sBAAO,CAAC,aAAa,EAAE,CAAA;QACjD,IAAI,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAA;QAChF,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QACpC,mBAAmB,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QAE7D,MAAM,KAAK,GAAG,CAAC,OAAiB,EAAkB,EAAE;YAClD,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAC;YACpC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;gBAC5B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;aACtB;YACD,MAAM,CAAC,GAAG,EAAE,CAAA;YACZ,OAAO,MAAM,CAAC,MAAM,CAAC,CAAA;QACvB,CAAC,CAAA;QAED,IAAI,cAAc,GAAG,UAAU,QAAe;YAC5C,gBAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;YACtC,gBAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;gBAC5B,IAAI,EAAE,SAAS;gBACf,UAAU,EAAE,CAAC;gBACb,MAAM,EAAE,EAAE;gBACV,MAAM,EAAE,CAAC,GAAG,CAAC;aACd,CAAC,CAAA;YACF,gBAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;YACxC,gBAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;gBAC5B,IAAI,EAAE,eAAe;gBACrB,MAAM,EAAE,CAAC;gBACT,MAAM,EAAE,GAAG;aACZ,CAAC,CAAA;QACJ,CAAC,CAAA;QACD,eAAe;QACf,EAAE,CAAC,iDAAiD,EAAE;;gBACpD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;gBAC1C,cAAc,CAAC,QAAQ,CAAC,CAAA;YAC1B,CAAC;SAAA,CAAC,CAAA;QAEF,IAAI,yBAAyB,GAAG,UAAgB,KAAa;;gBAC3D,IAAI,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,KAAK,CAAC,CAAA;gBACzD,IAAI,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;gBACvE,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;gBAClC,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;gBACpD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAA;gBACzD,cAAc,CAAC,QAAQ,CAAC,CAAA;YAC1B,CAAC;SAAA,CAAA;QAED,QAAQ,CAAC,6CAA6C,EAAE;YACtD,EAAE,CAAC,eAAe,EAAE;gBAClB,OAAO,yBAAyB,CAAC,EAAE,CAAC,CAAA;YACtC,CAAC,CAAC,CAAA;YACF,EAAE,CAAC,cAAc,EAAE;gBACjB,OAAO,OAAO,CAAC,GAAG,CAAC;oBACjB,yBAAyB,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;oBAChD,yBAAyB,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;oBAChD,yBAAyB,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;iBACjD,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;YAEF,EAAE,CAAC,YAAY,EAAE;gBACf,OAAO,OAAO,CAAC,GAAG,CAAC;oBACjB,yBAAyB,CAAC,CAAC,CAAC;oBAC5B,yBAAyB,CAAC,CAAC,CAAC;iBAC7B,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AAEJ,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/index.js b/packages/pg-packet-stream/dist/index.js new file mode 100644 index 000000000..48527f2ed --- /dev/null +++ b/packages/pg-packet-stream/dist/index.js @@ -0,0 +1,264 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const stream_1 = require("stream"); +const messages_1 = require("./messages"); +const BufferReader_1 = require("./BufferReader"); +const assert_1 = __importDefault(require("assert")); +// every message is prefixed with a single bye +const CODE_LENGTH = 1; +// every message has an int32 length which includes itself but does +// NOT include the code in the length +const LEN_LENGTH = 4; +const HEADER_LENGTH = CODE_LENGTH + LEN_LENGTH; +const emptyBuffer = Buffer.allocUnsafe(0); +class PgPacketStream extends stream_1.Transform { + constructor(opts) { + var _a, _b; + super(Object.assign(Object.assign({}, opts), { readableObjectMode: true })); + this.remainingBuffer = emptyBuffer; + this.reader = new BufferReader_1.BufferReader(); + if (((_a = opts) === null || _a === void 0 ? void 0 : _a.mode) === 'binary') { + throw new Error('Binary mode not supported yet'); + } + this.mode = ((_b = opts) === null || _b === void 0 ? void 0 : _b.mode) || 'text'; + } + _transform(buffer, encoding, callback) { + const combinedBuffer = this.remainingBuffer.byteLength ? Buffer.concat([this.remainingBuffer, buffer], this.remainingBuffer.length + buffer.length) : buffer; + let offset = 0; + while ((offset + HEADER_LENGTH) <= combinedBuffer.byteLength) { + // code is 1 byte long - it identifies the message type + const code = combinedBuffer[offset]; + // length is 1 Uint32BE - it is the length of the message EXCLUDING the code + const length = combinedBuffer.readUInt32BE(offset + CODE_LENGTH); + const fullMessageLength = CODE_LENGTH + length; + if (fullMessageLength + offset <= combinedBuffer.byteLength) { + const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer); + this.push(message); + offset += fullMessageLength; + } + else { + break; + } + } + if (offset === combinedBuffer.byteLength) { + this.remainingBuffer = emptyBuffer; + } + else { + this.remainingBuffer = combinedBuffer.slice(offset); + } + callback(null); + } + handlePacket(offset, code, length, bytes) { + switch (code) { + case 50 /* BindComplete */: + return messages_1.bindComplete; + case 49 /* ParseComplete */: + return messages_1.parseComplete; + case 51 /* CloseComplete */: + return messages_1.closeComplete; + case 110 /* NoData */: + return messages_1.noData; + case 115 /* PortalSuspended */: + return messages_1.portalSuspended; + case 99 /* CopyDone */: + return messages_1.copyDone; + case 87 /* ReplicationStart */: + return messages_1.replicationStart; + case 73 /* EmptyQuery */: + return messages_1.emptyQuery; + case 68 /* DataRow */: + return this.parseDataRowMessage(offset, length, bytes); + case 67 /* CommandComplete */: + return this.parseCommandCompleteMessage(offset, length, bytes); + case 90 /* ReadyForQuery */: + return this.parseReadyForQueryMessage(offset, length, bytes); + case 65 /* NotificationResponse */: + return this.parseNotificationMessage(offset, length, bytes); + case 82 /* AuthenticationResponse */: + return this.parseAuthenticationResponse(offset, length, bytes); + case 83 /* ParameterStatus */: + return this.parseParameterStatusMessage(offset, length, bytes); + case 75 /* BackendKeyData */: + return this.parseBackendKeyData(offset, length, bytes); + case 69 /* ErrorMessage */: + return this.parseErrorMessage(offset, length, bytes, 'error'); + case 78 /* NoticeMessage */: + return this.parseErrorMessage(offset, length, bytes, 'notice'); + case 84 /* RowDescriptionMessage */: + return this.parseRowDescriptionMessage(offset, length, bytes); + case 71 /* CopyIn */: + return this.parseCopyInMessage(offset, length, bytes); + case 72 /* CopyOut */: + return this.parseCopyOutMessage(offset, length, bytes); + case 100 /* CopyData */: + return this.parseCopyData(offset, length, bytes); + default: + assert_1.default.fail(`unknown message code: ${code.toString(16)}`); + } + } + _flush(callback) { + this._transform(Buffer.alloc(0), 'utf-i', callback); + } + parseReadyForQueryMessage(offset, length, bytes) { + this.reader.setBuffer(offset, bytes); + const status = this.reader.string(1); + return new messages_1.ReadyForQueryMessage(length, status); + } + parseCommandCompleteMessage(offset, length, bytes) { + this.reader.setBuffer(offset, bytes); + const text = this.reader.cstring(); + return new messages_1.CommandCompleteMessage(length, text); + } + parseCopyData(offset, length, bytes) { + const chunk = bytes.slice(offset, offset + (length - 4)); + return new messages_1.CopyDataMessage(length, chunk); + } + parseCopyInMessage(offset, length, bytes) { + return this.parseCopyMessage(offset, length, bytes, 'copyInResponse'); + } + parseCopyOutMessage(offset, length, bytes) { + return this.parseCopyMessage(offset, length, bytes, 'copyOutResponse'); + } + parseCopyMessage(offset, length, bytes, messageName) { + this.reader.setBuffer(offset, bytes); + const isBinary = this.reader.byte() !== 0; + const columnCount = this.reader.int16(); + const message = new messages_1.CopyResponse(length, messageName, isBinary, columnCount); + for (let i = 0; i < columnCount; i++) { + message.columnTypes[i] = this.reader.int16(); + } + return message; + } + parseNotificationMessage(offset, length, bytes) { + this.reader.setBuffer(offset, bytes); + const processId = this.reader.int32(); + const channel = this.reader.cstring(); + const payload = this.reader.cstring(); + return new messages_1.NotificationResponseMessage(length, processId, channel, payload); + } + parseRowDescriptionMessage(offset, length, bytes) { + this.reader.setBuffer(offset, bytes); + const fieldCount = this.reader.int16(); + const message = new messages_1.RowDescriptionMessage(length, fieldCount); + for (let i = 0; i < fieldCount; i++) { + message.fields[i] = this.parseField(); + } + return message; + } + parseField() { + const name = this.reader.cstring(); + const tableID = this.reader.int32(); + const columnID = this.reader.int16(); + const dataTypeID = this.reader.int32(); + const dataTypeSize = this.reader.int16(); + const dataTypeModifier = this.reader.int32(); + const mode = this.reader.int16() === 0 ? 'text' : 'binary'; + return new messages_1.Field(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, mode); + } + parseDataRowMessage(offset, length, bytes) { + this.reader.setBuffer(offset, bytes); + const fieldCount = this.reader.int16(); + const fields = new Array(fieldCount); + for (let i = 0; i < fieldCount; i++) { + const len = this.reader.int32(); + if (len === -1) { + fields[i] = null; + } + else if (this.mode === 'text') { + fields[i] = this.reader.string(len); + } + } + return new messages_1.DataRowMessage(length, fields); + } + parseParameterStatusMessage(offset, length, bytes) { + this.reader.setBuffer(offset, bytes); + const name = this.reader.cstring(); + const value = this.reader.cstring(); + return new messages_1.ParameterStatusMessage(length, name, value); + } + parseBackendKeyData(offset, length, bytes) { + this.reader.setBuffer(offset, bytes); + const processID = this.reader.int32(); + const secretKey = this.reader.int32(); + return new messages_1.BackendKeyDataMessage(length, processID, secretKey); + } + parseAuthenticationResponse(offset, length, bytes) { + this.reader.setBuffer(offset, bytes); + const code = this.reader.int32(); + // TODO(bmc): maybe better types here + const message = { + name: 'authenticationOk', + length, + }; + switch (code) { + case 0: // AuthenticationOk + break; + case 3: // AuthenticationCleartextPassword + if (message.length === 8) { + message.name = 'authenticationCleartextPassword'; + } + break; + case 5: // AuthenticationMD5Password + if (message.length === 12) { + message.name = 'authenticationMD5Password'; + message.salt = this.reader.bytes(4); + } + break; + case 10: // AuthenticationSASL + message.name = 'authenticationSASL'; + message.mechanisms = []; + let mechanism; + do { + mechanism = this.reader.cstring(); + if (mechanism) { + message.mechanisms.push(mechanism); + } + } while (mechanism); + break; + case 11: // AuthenticationSASLContinue + message.name = 'authenticationSASLContinue'; + message.data = this.reader.string(length - 4); + break; + case 12: // AuthenticationSASLFinal + message.name = 'authenticationSASLFinal'; + message.data = this.reader.string(length - 4); + break; + default: + throw new Error('Unknown authenticationOk message type ' + code); + } + return message; + } + parseErrorMessage(offset, length, bytes, name) { + this.reader.setBuffer(offset, bytes); + var fields = {}; + var fieldType = this.reader.string(1); + while (fieldType !== '\0') { + fields[fieldType] = this.reader.cstring(); + fieldType = this.reader.string(1); + } + // the msg is an Error instance + var message = new messages_1.DatabaseError(fields.M, length, name); + message.severity = fields.S; + message.code = fields.C; + message.detail = fields.D; + message.hint = fields.H; + message.position = fields.P; + message.internalPosition = fields.p; + message.internalQuery = fields.q; + message.where = fields.W; + message.schema = fields.s; + message.table = fields.t; + message.column = fields.c; + message.dataType = fields.d; + message.constraint = fields.n; + message.file = fields.F; + message.line = fields.L; + message.routine = fields.R; + return message; + } +} +exports.PgPacketStream = PgPacketStream; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/index.js.map b/packages/pg-packet-stream/dist/index.js.map new file mode 100644 index 000000000..878db40a3 --- /dev/null +++ b/packages/pg-packet-stream/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;AAAA,mCAAwE;AACxE,yCAAqX;AACrX,iDAA8C;AAC9C,oDAA2B;AAE3B,8CAA8C;AAC9C,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,mEAAmE;AACnE,qCAAqC;AACrC,MAAM,UAAU,GAAG,CAAC,CAAC;AAErB,MAAM,aAAa,GAAG,WAAW,GAAG,UAAU,CAAC;AAO/C,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AA8B1C,MAAa,cAAe,SAAQ,kBAAS;IAK3C,YAAY,IAAoB;;QAC9B,KAAK,iCACA,IAAI,KACP,kBAAkB,EAAE,IAAI,IACxB,CAAA;QARI,oBAAe,GAAW,WAAW,CAAC;QACtC,WAAM,GAAG,IAAI,2BAAY,EAAE,CAAC;QAQlC,IAAI,OAAA,IAAI,0CAAE,IAAI,MAAK,QAAQ,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;SACjD;QACD,IAAI,CAAC,IAAI,GAAG,OAAA,IAAI,0CAAE,IAAI,KAAI,MAAM,CAAC;IACnC,CAAC;IAEM,UAAU,CAAC,MAAc,EAAE,QAAgB,EAAE,QAA2B;QAC7E,MAAM,cAAc,GAAW,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACrK,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,OAAO,CAAC,MAAM,GAAG,aAAa,CAAC,IAAI,cAAc,CAAC,UAAU,EAAE;YAC5D,uDAAuD;YACvD,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YAEpC,4EAA4E;YAC5E,MAAM,MAAM,GAAG,cAAc,CAAC,YAAY,CAAC,MAAM,GAAG,WAAW,CAAC,CAAC;YAEjE,MAAM,iBAAiB,GAAG,WAAW,GAAG,MAAM,CAAC;YAE/C,IAAI,iBAAiB,GAAG,MAAM,IAAI,cAAc,CAAC,UAAU,EAAE;gBAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;gBACxF,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAClB,MAAM,IAAI,iBAAiB,CAAC;aAC7B;iBAAM;gBACL,MAAM;aACP;SACF;QAED,IAAI,MAAM,KAAK,cAAc,CAAC,UAAU,EAAE;YACxC,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC;SACpC;aAAM;YACL,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;SACpD;QAED,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAEO,YAAY,CAAC,MAAc,EAAE,IAAY,EAAE,MAAc,EAAE,KAAa;QAC9E,QAAQ,IAAI,EAAE;YACZ;gBACE,OAAO,uBAAY,CAAC;YACtB;gBACE,OAAO,wBAAa,CAAC;YACvB;gBACE,OAAO,wBAAa,CAAC;YACvB;gBACE,OAAO,iBAAM,CAAC;YAChB;gBACE,OAAO,0BAAe,CAAC;YACzB;gBACE,OAAO,mBAAQ,CAAC;YAClB;gBACE,OAAO,2BAAgB,CAAC;YAC1B;gBACE,OAAO,qBAAU,CAAC;YACpB;gBACE,OAAO,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACzD;gBACE,OAAO,IAAI,CAAC,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACjE;gBACE,OAAO,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YAC/D;gBACE,OAAO,IAAI,CAAC,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YAC9D;gBACE,OAAO,IAAI,CAAC,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACjE;gBACE,OAAO,IAAI,CAAC,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACjE;gBACE,OAAO,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACzD;gBACE,OAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YAChE;gBACE,OAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;YACjE;gBACE,OAAO,IAAI,CAAC,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YAChE;gBACE,OAAO,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACxD;gBACE,OAAO,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACzD;gBACE,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACnD;gBACE,gBAAM,CAAC,IAAI,CAAC,yBAAyB,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;SAC5D;IACH,CAAC;IAEM,MAAM,CAAC,QAA2B;QACvC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;IACrD,CAAC;IAEO,yBAAyB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QAC7E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACrC,OAAO,IAAI,+BAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjD,CAAC;IAEO,2BAA2B,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QAC/E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACnC,OAAO,IAAI,iCAAsB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAClD,CAAC;IAEO,aAAa,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QACjE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACzD,OAAO,IAAI,0BAAe,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAEO,kBAAkB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QACtE,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAA;IACvE,CAAC;IAEO,mBAAmB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QACvE,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAA;IACxE,CAAC;IAEO,gBAAgB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa,EAAE,WAAmB;QACzF,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACvC,MAAM,OAAO,GAAG,IAAI,uBAAY,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;QAC7E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE;YACpC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;SAC9C;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,wBAAwB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QAC5E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACtC,OAAO,IAAI,sCAA2B,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC9E,CAAC;IAEO,0BAA0B,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QAC9E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACtC,MAAM,OAAO,GAAG,IAAI,gCAAqB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE;YACnC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,CAAA;SACtC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,UAAU;QAChB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACpC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACtC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACxC,MAAM,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC3D,OAAO,IAAI,gBAAK,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,IAAI,CAAC,CAAA;IAC7F,CAAC;IAEO,mBAAmB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QACvE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACvC,MAAM,MAAM,GAAU,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;QAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE;YACnC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAChC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE;gBACd,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;aACjB;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE;gBAC/B,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;aACpC;SACF;QACD,OAAO,IAAI,yBAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAEO,2BAA2B,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QAC/E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;QACnC,OAAO,IAAI,iCAAsB,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;IACxD,CAAC;IAEO,mBAAmB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QACvE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACrC,OAAO,IAAI,gCAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;IAChE,CAAC;IAGM,2BAA2B,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QAC9E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QAChC,qCAAqC;QACrC,MAAM,OAAO,GAAQ;YACnB,IAAI,EAAE,kBAAkB;YACxB,MAAM;SACP,CAAC;QAEF,QAAQ,IAAI,EAAE;YACZ,KAAK,CAAC,EAAE,mBAAmB;gBACzB,MAAM;YACR,KAAK,CAAC,EAAE,kCAAkC;gBACxC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;oBACxB,OAAO,CAAC,IAAI,GAAG,iCAAiC,CAAA;iBACjD;gBACD,MAAK;YACP,KAAK,CAAC,EAAE,4BAA4B;gBAClC,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE,EAAE;oBACzB,OAAO,CAAC,IAAI,GAAG,2BAA2B,CAAA;oBAC1C,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;iBACrC;gBACD,MAAK;YACP,KAAK,EAAE,EAAE,qBAAqB;gBAC5B,OAAO,CAAC,IAAI,GAAG,oBAAoB,CAAA;gBACnC,OAAO,CAAC,UAAU,GAAG,EAAE,CAAA;gBACvB,IAAI,SAAiB,CAAC;gBACtB,GAAG;oBACD,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;oBAEjC,IAAI,SAAS,EAAE;wBACb,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;qBACnC;iBACF,QAAQ,SAAS,EAAC;gBACnB,MAAM;YACR,KAAK,EAAE,EAAE,6BAA6B;gBACpC,OAAO,CAAC,IAAI,GAAG,4BAA4B,CAAA;gBAC3C,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;gBAC7C,MAAM;YACR,KAAK,EAAE,EAAE,0BAA0B;gBACjC,OAAO,CAAC,IAAI,GAAG,yBAAyB,CAAA;gBACxC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;gBAC7C,MAAM;YACR;gBACE,MAAM,IAAI,KAAK,CAAC,wCAAwC,GAAG,IAAI,CAAC,CAAA;SACnE;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,iBAAiB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa,EAAE,IAAY;QACnF,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,IAAI,MAAM,GAA2B,EAAE,CAAA;QACvC,IAAI,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACrC,OAAO,SAAS,KAAK,IAAI,EAAE;YACzB,MAAM,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;YACzC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;SAClC;QAED,+BAA+B;QAC/B,IAAI,OAAO,GAAG,IAAI,wBAAa,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;QAEvD,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAA;QAC3B,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAA;QACvB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAA;QACzB,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAA;QACvB,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAA;QAC3B,OAAO,CAAC,gBAAgB,GAAG,MAAM,CAAC,CAAC,CAAA;QACnC,OAAO,CAAC,aAAa,GAAG,MAAM,CAAC,CAAC,CAAA;QAChC,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAA;QACxB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAA;QACzB,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAA;QACxB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAA;QACzB,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAA;QAC3B,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC,CAAA;QAC7B,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAA;QACvB,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAA;QACvB,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC,CAAA;QAC1B,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAjRD,wCAiRC"} \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/index.test.js b/packages/pg-packet-stream/dist/index.test.js new file mode 100644 index 000000000..1e4c8f357 --- /dev/null +++ b/packages/pg-packet-stream/dist/index.test.js @@ -0,0 +1,109 @@ +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +require("mocha"); +const _1 = require("./"); +const chai_1 = require("chai"); +const chunky_1 = __importDefault(require("chunky")); +const consume = (stream, count) => __awaiter(void 0, void 0, void 0, function* () { + const result = []; + return new Promise((resolve) => { + const read = () => { + stream.once('readable', () => { + let packet; + while (packet = stream.read()) { + result.push(packet); + } + if (result.length === count) { + resolve(result); + } + else { + read(); + } + }); + }; + read(); + }); +}); +const emptyMessage = Buffer.from([0x0a, 0x00, 0x00, 0x00, 0x04]); +const oneByteMessage = Buffer.from([0x0b, 0x00, 0x00, 0x00, 0x05, 0x0a]); +const bigMessage = Buffer.from([0x0f, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e0, 0x0f]); +describe.skip('PgPacketStream', () => { + it('should chunk a perfect input packet', () => __awaiter(void 0, void 0, void 0, function* () { + const stream = new _1.PgPacketStream(); + stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x04])); + stream.end(); + const buffers = yield consume(stream, 1); + chai_1.expect(buffers).to.have.length(1); + chai_1.expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x04])); + })); + it('should read 2 chunks into perfect input packet', () => __awaiter(void 0, void 0, void 0, function* () { + const stream = new _1.PgPacketStream(); + stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x08])); + stream.write(Buffer.from([0x1, 0x2, 0x3, 0x4])); + stream.end(); + const buffers = yield consume(stream, 1); + chai_1.expect(buffers).to.have.length(1); + chai_1.expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x08, 0x1, 0x2, 0x3, 0x4])); + })); + it('should read a bunch of big messages', () => __awaiter(void 0, void 0, void 0, function* () { + const stream = new _1.PgPacketStream(); + let totalBuffer = Buffer.allocUnsafe(0); + const num = 2; + for (let i = 0; i < 2; i++) { + totalBuffer = Buffer.concat([totalBuffer, bigMessage, bigMessage]); + } + const chunks = chunky_1.default(totalBuffer); + for (const chunk of chunks) { + stream.write(chunk); + } + stream.end(); + const messages = yield consume(stream, num * 2); + chai_1.expect(messages.map(x => x.code)).to.eql(new Array(num * 2).fill(0x0f)); + })); + it('should read multiple messages in a single chunk', () => __awaiter(void 0, void 0, void 0, function* () { + const stream = new _1.PgPacketStream(); + stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x04])); + stream.end(); + const buffers = yield consume(stream, 2); + chai_1.expect(buffers).to.have.length(2); + chai_1.expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x04])); + chai_1.expect(buffers[1].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x04])); + })); + it('should read multiple chunks into multiple packets', () => __awaiter(void 0, void 0, void 0, function* () { + const stream = new _1.PgPacketStream(); + stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x05, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x05, 0x0b])); + stream.write(Buffer.from([0x01, 0x00, 0x00])); + stream.write(Buffer.from([0x00, 0x06, 0x0c, 0x0d, 0x03, 0x00, 0x00, 0x00, 0x04])); + stream.end(); + const buffers = yield consume(stream, 4); + chai_1.expect(buffers).to.have.length(4); + chai_1.expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x05, 0x0a])); + chai_1.expect(buffers[1].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x05, 0x0b])); + chai_1.expect(buffers[2].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x0d])); + chai_1.expect(buffers[3].packet).to.deep.equal(Buffer.from([0x3, 0x00, 0x00, 0x00, 0x04])); + })); + it('reads packet that spans multiple chunks', () => __awaiter(void 0, void 0, void 0, function* () { + const stream = new _1.PgPacketStream(); + stream.write(Buffer.from([0x0d, 0x00, 0x00, 0x00])); + stream.write(Buffer.from([0x09])); // length + stream.write(Buffer.from([0x0a, 0x0b, 0x0c, 0x0d])); + stream.write(Buffer.from([0x0a, 0x0b, 0x0c, 0x0d])); + stream.write(Buffer.from([0x0a, 0x0b, 0x0c, 0x0d])); + stream.end(); + const buffers = yield consume(stream, 1); + chai_1.expect(buffers).to.have.length(1); + })); +}); +//# sourceMappingURL=index.test.js.map \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/index.test.js.map b/packages/pg-packet-stream/dist/index.test.js.map new file mode 100644 index 000000000..6697efee1 --- /dev/null +++ b/packages/pg-packet-stream/dist/index.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,iBAAe;AACf,yBAA2C;AAC3C,+BAA6B;AAC7B,oDAA2B;AAE3B,MAAM,OAAO,GAAG,CAAO,MAAsB,EAAE,KAAa,EAAqB,EAAE;IACjF,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE;gBAC3B,IAAI,MAAM,CAAC;gBACX,OAAO,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE;oBAC7B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;iBACpB;gBACD,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK,EAAE;oBAC3B,OAAO,CAAC,MAAM,CAAC,CAAC;iBACjB;qBAAM;oBACL,IAAI,EAAE,CAAA;iBACP;YAEH,CAAC,CAAC,CAAA;QACJ,CAAC,CAAA;QACD,IAAI,EAAE,CAAA;IACR,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA,CAAA;AAED,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;AAChE,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;AACxE,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;AAE/J,QAAQ,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,qCAAqC,EAAE,GAAS,EAAE;QACnD,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACzD,MAAM,CAAC,GAAG,EAAE,CAAA;QACZ,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACxC,aAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACjC,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;IACrF,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAS,EAAE;QAC9D,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACzD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;QAC/C,MAAM,CAAC,GAAG,EAAE,CAAA;QACZ,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACxC,aAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACjC,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;IACzG,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAS,EAAE;QACnD,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAC;QACpC,IAAI,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,CAAC,CAAC;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1B,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAA;SACnE;QACD,MAAM,MAAM,GAAG,gBAAM,CAAC,WAAW,CAAC,CAAA;QAClC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;YAC1B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;SACpB;QACD,MAAM,CAAC,GAAG,EAAE,CAAA;QACZ,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAA;QAC/C,aAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACzE,CAAC,CAAA,CAAC,CAAA;IAEF,EAAE,CAAC,iDAAiD,EAAE,GAAS,EAAE;QAC/D,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACvF,MAAM,CAAC,GAAG,EAAE,CAAA;QACZ,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACxC,aAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACjC,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACnF,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;IACrF,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAS,EAAE;QACjE,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACnG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACjF,MAAM,CAAC,GAAG,EAAE,CAAA;QACZ,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACxC,aAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACjC,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACzF,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACzF,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QAC/F,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;IACrF,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAS,EAAE;QACvD,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACnD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA,CAAC,SAAS;QAC3C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACnD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACnD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACnD,MAAM,CAAC,GAAG,EAAE,CAAA;QACZ,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACxC,aAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IACnC,CAAC,CAAA,CAAC,CAAA;AACJ,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/messages.js b/packages/pg-packet-stream/dist/messages.js new file mode 100644 index 000000000..9515af05d --- /dev/null +++ b/packages/pg-packet-stream/dist/messages.js @@ -0,0 +1,134 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.parseComplete = { + name: 'parseComplete', + length: 5, +}; +exports.bindComplete = { + name: 'bindComplete', + length: 5, +}; +exports.closeComplete = { + name: 'closeComplete', + length: 5, +}; +exports.noData = { + name: 'noData', + length: 5 +}; +exports.portalSuspended = { + name: 'portalSuspended', + length: 5, +}; +exports.replicationStart = { + name: 'replicationStart', + length: 4, +}; +exports.emptyQuery = { + name: 'emptyQuery', + length: 4, +}; +exports.copyDone = { + name: 'copyDone', + length: 4, +}; +class DatabaseError extends Error { + constructor(message, length, name) { + super(message); + this.length = length; + this.name = name; + } +} +exports.DatabaseError = DatabaseError; +class CopyDataMessage { + constructor(length, chunk) { + this.length = length; + this.chunk = chunk; + this.name = 'copyData'; + } +} +exports.CopyDataMessage = CopyDataMessage; +class CopyResponse { + constructor(length, name, binary, columnCount) { + this.length = length; + this.name = name; + this.binary = binary; + this.columnTypes = new Array(columnCount); + } +} +exports.CopyResponse = CopyResponse; +class Field { + constructor(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, format) { + this.name = name; + this.tableID = tableID; + this.columnID = columnID; + this.dataTypeID = dataTypeID; + this.dataTypeSize = dataTypeSize; + this.dataTypeModifier = dataTypeModifier; + this.format = format; + } +} +exports.Field = Field; +class RowDescriptionMessage { + constructor(length, fieldCount) { + this.length = length; + this.fieldCount = fieldCount; + this.name = 'rowDescription'; + this.fields = new Array(this.fieldCount); + } +} +exports.RowDescriptionMessage = RowDescriptionMessage; +class ParameterStatusMessage { + constructor(length, parameterName, parameterValue) { + this.length = length; + this.parameterName = parameterName; + this.parameterValue = parameterValue; + this.name = 'parameterStatus'; + } +} +exports.ParameterStatusMessage = ParameterStatusMessage; +class BackendKeyDataMessage { + constructor(length, processID, secretKey) { + this.length = length; + this.processID = processID; + this.secretKey = secretKey; + this.name = 'backendKeyData'; + } +} +exports.BackendKeyDataMessage = BackendKeyDataMessage; +class NotificationResponseMessage { + constructor(length, processId, channel, payload) { + this.length = length; + this.processId = processId; + this.channel = channel; + this.payload = payload; + this.name = 'notification'; + } +} +exports.NotificationResponseMessage = NotificationResponseMessage; +class ReadyForQueryMessage { + constructor(length, status) { + this.length = length; + this.status = status; + this.name = 'readyForQuery'; + } +} +exports.ReadyForQueryMessage = ReadyForQueryMessage; +class CommandCompleteMessage { + constructor(length, text) { + this.length = length; + this.text = text; + this.name = 'commandComplete'; + } +} +exports.CommandCompleteMessage = CommandCompleteMessage; +class DataRowMessage { + constructor(length, fields) { + this.length = length; + this.fields = fields; + this.name = 'dataRow'; + this.fieldCount = fields.length; + } +} +exports.DataRowMessage = DataRowMessage; +//# sourceMappingURL=messages.js.map \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/messages.js.map b/packages/pg-packet-stream/dist/messages.js.map new file mode 100644 index 000000000..1fe1ba7aa --- /dev/null +++ b/packages/pg-packet-stream/dist/messages.js.map @@ -0,0 +1 @@ +{"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":";;AAOa,QAAA,aAAa,GAAmB;IAC3C,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,CAAC;CACV,CAAC;AAEW,QAAA,YAAY,GAAmB;IAC1C,IAAI,EAAE,cAAc;IACpB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,aAAa,GAAmB;IAC3C,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,MAAM,GAAmB;IACpC,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,eAAe,GAAmB;IAC7C,IAAI,EAAE,iBAAiB;IACvB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,gBAAgB,GAAmB;IAC9C,IAAI,EAAE,kBAAkB;IACxB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,UAAU,GAAmB;IACxC,IAAI,EAAE,YAAY;IAClB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,QAAQ,GAAmB;IACtC,IAAI,EAAE,UAAU;IAChB,MAAM,EAAE,CAAC;CACV,CAAA;AAED,MAAa,aAAc,SAAQ,KAAK;IAiBtC,YAAY,OAAe,EAAkB,MAAc,EAAkB,IAAY;QACvF,KAAK,CAAC,OAAO,CAAC,CAAA;QAD6B,WAAM,GAAN,MAAM,CAAQ;QAAkB,SAAI,GAAJ,IAAI,CAAQ;IAEzF,CAAC;CACF;AApBD,sCAoBC;AAED,MAAa,eAAe;IAE1B,YAA4B,MAAc,EAAkB,KAAa;QAA7C,WAAM,GAAN,MAAM,CAAQ;QAAkB,UAAK,GAAL,KAAK,CAAQ;QADzD,SAAI,GAAG,UAAU,CAAC;IAGlC,CAAC;CACF;AALD,0CAKC;AAED,MAAa,YAAY;IAEvB,YAA4B,MAAc,EAAkB,IAAY,EAAkB,MAAe,EAAE,WAAmB;QAAlG,WAAM,GAAN,MAAM,CAAQ;QAAkB,SAAI,GAAJ,IAAI,CAAQ;QAAkB,WAAM,GAAN,MAAM,CAAS;QACvG,IAAI,CAAC,WAAW,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;IAC5C,CAAC;CACF;AALD,oCAKC;AAED,MAAa,KAAK;IAChB,YAA4B,IAAY,EAAkB,OAAe,EAAkB,QAAgB,EAAkB,UAAkB,EAAkB,YAAoB,EAAkB,gBAAwB,EAAkB,MAAY;QAAjO,SAAI,GAAJ,IAAI,CAAQ;QAAkB,YAAO,GAAP,OAAO,CAAQ;QAAkB,aAAQ,GAAR,QAAQ,CAAQ;QAAkB,eAAU,GAAV,UAAU,CAAQ;QAAkB,iBAAY,GAAZ,YAAY,CAAQ;QAAkB,qBAAgB,GAAhB,gBAAgB,CAAQ;QAAkB,WAAM,GAAN,MAAM,CAAM;IAC7P,CAAC;CACF;AAHD,sBAGC;AAED,MAAa,qBAAqB;IAGhC,YAA4B,MAAc,EAAkB,UAAkB;QAAlD,WAAM,GAAN,MAAM,CAAQ;QAAkB,eAAU,GAAV,UAAU,CAAQ;QAF9D,SAAI,GAAW,gBAAgB,CAAC;QAG9C,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAC1C,CAAC;CACF;AAND,sDAMC;AAED,MAAa,sBAAsB;IAEjC,YAA4B,MAAc,EAAkB,aAAqB,EAAkB,cAAsB;QAA7F,WAAM,GAAN,MAAM,CAAQ;QAAkB,kBAAa,GAAb,aAAa,CAAQ;QAAkB,mBAAc,GAAd,cAAc,CAAQ;QADzG,SAAI,GAAW,iBAAiB,CAAC;IAGjD,CAAC;CACF;AALD,wDAKC;AAED,MAAa,qBAAqB;IAEhC,YAA4B,MAAc,EAAkB,SAAiB,EAAkB,SAAiB;QAApF,WAAM,GAAN,MAAM,CAAQ;QAAkB,cAAS,GAAT,SAAS,CAAQ;QAAkB,cAAS,GAAT,SAAS,CAAQ;QADhG,SAAI,GAAW,gBAAgB,CAAC;IAEhD,CAAC;CACF;AAJD,sDAIC;AAED,MAAa,2BAA2B;IAEtC,YAA4B,MAAc,EAAkB,SAAiB,EAAkB,OAAe,EAAkB,OAAe;QAAnH,WAAM,GAAN,MAAM,CAAQ;QAAkB,cAAS,GAAT,SAAS,CAAQ;QAAkB,YAAO,GAAP,OAAO,CAAQ;QAAkB,YAAO,GAAP,OAAO,CAAQ;QAD/H,SAAI,GAAW,cAAc,CAAC;IAE9C,CAAC;CACF;AAJD,kEAIC;AAED,MAAa,oBAAoB;IAE/B,YAA4B,MAAc,EAAkB,MAAc;QAA9C,WAAM,GAAN,MAAM,CAAQ;QAAkB,WAAM,GAAN,MAAM,CAAQ;QAD1D,SAAI,GAAW,eAAe,CAAC;IAE/C,CAAC;CACF;AAJD,oDAIC;AAED,MAAa,sBAAsB;IAEjC,YAA4B,MAAc,EAAkB,IAAY;QAA5C,WAAM,GAAN,MAAM,CAAQ;QAAkB,SAAI,GAAJ,IAAI,CAAQ;QADxD,SAAI,GAAW,iBAAiB,CAAA;IAEhD,CAAC;CACF;AAJD,wDAIC;AAED,MAAa,cAAc;IAGzB,YAAmB,MAAc,EAAS,MAAa;QAApC,WAAM,GAAN,MAAM,CAAQ;QAAS,WAAM,GAAN,MAAM,CAAO;QADvC,SAAI,GAAW,SAAS,CAAA;QAEtC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;IAClC,CAAC;CACF;AAND,wCAMC"} \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/testing/buffer-list.js b/packages/pg-packet-stream/dist/testing/buffer-list.js new file mode 100644 index 000000000..9a7494f6c --- /dev/null +++ b/packages/pg-packet-stream/dist/testing/buffer-list.js @@ -0,0 +1,73 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +class BufferList { + constructor(buffers = []) { + this.buffers = buffers; + } + add(buffer, front) { + this.buffers[front ? 'unshift' : 'push'](buffer); + return this; + } + addInt16(val, front) { + return this.add(Buffer.from([(val >>> 8), (val >>> 0)]), front); + } + getByteLength(initial) { + return this.buffers.reduce(function (previous, current) { + return previous + current.length; + }, initial || 0); + } + addInt32(val, first) { + return this.add(Buffer.from([ + (val >>> 24 & 0xFF), + (val >>> 16 & 0xFF), + (val >>> 8 & 0xFF), + (val >>> 0 & 0xFF) + ]), first); + } + addCString(val, front) { + var len = Buffer.byteLength(val); + var buffer = Buffer.alloc(len + 1); + buffer.write(val); + buffer[len] = 0; + return this.add(buffer, front); + } + addString(val, front) { + var len = Buffer.byteLength(val); + var buffer = Buffer.alloc(len); + buffer.write(val); + return this.add(buffer, front); + } + addChar(char, first) { + return this.add(Buffer.from(char, 'utf8'), first); + } + addByte(byte) { + return this.add(Buffer.from([byte])); + } + join(appendLength, char) { + var length = this.getByteLength(); + if (appendLength) { + this.addInt32(length + 4, true); + return this.join(false, char); + } + if (char) { + this.addChar(char, true); + length++; + } + var result = Buffer.alloc(length); + var index = 0; + this.buffers.forEach(function (buffer) { + buffer.copy(result, index, 0); + index += buffer.length; + }); + return result; + } + static concat() { + var total = new BufferList(); + for (var i = 0; i < arguments.length; i++) { + total.add(arguments[i]); + } + return total.join(); + } +} +exports.default = BufferList; +//# sourceMappingURL=buffer-list.js.map \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/testing/buffer-list.js.map b/packages/pg-packet-stream/dist/testing/buffer-list.js.map new file mode 100644 index 000000000..c10853902 --- /dev/null +++ b/packages/pg-packet-stream/dist/testing/buffer-list.js.map @@ -0,0 +1 @@ +{"version":3,"file":"buffer-list.js","sourceRoot":"","sources":["../../src/testing/buffer-list.ts"],"names":[],"mappings":";;AAAA,MAAqB,UAAU;IAC7B,YAAmB,UAAoB,EAAE;QAAtB,YAAO,GAAP,OAAO,CAAe;IAEzC,CAAC;IAEM,GAAG,CAAC,MAAc,EAAE,KAAe;QACxC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;QAChD,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,QAAQ,CAAC,GAAW,EAAE,KAAe;QAC1C,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IACjE,CAAC;IAEM,aAAa,CAAC,OAAgB;QACnC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,QAAQ,EAAE,OAAO;YACpD,OAAO,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAA;QAClC,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC,CAAA;IAClB,CAAC;IAEM,QAAQ,CAAC,GAAW,EAAE,KAAe;QAC1C,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;YAC1B,CAAC,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;YACnB,CAAC,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;YACnB,CAAC,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC;YAClB,CAAC,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC;SACnB,CAAC,EAAE,KAAK,CAAC,CAAA;IACZ,CAAC;IAEM,UAAU,CAAC,GAAW,EAAE,KAAe;QAC5C,IAAI,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;QAChC,IAAI,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;QAClC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACjB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACf,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IAChC,CAAC;IAEM,SAAS,CAAC,GAAW,EAAE,KAAe;QAC3C,IAAI,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;QAChC,IAAI,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC9B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACjB,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IAChC,CAAC;IAEM,OAAO,CAAC,IAAY,EAAE,KAAe;QAC1C,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,CAAA;IACnD,CAAC;IAEM,OAAO,CAAC,IAAY;QACzB,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACtC,CAAC;IAEM,IAAI,CAAC,YAAsB,EAAE,IAAa;QAC/C,IAAI,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAA;QACjC,IAAI,YAAY,EAAE;YAChB,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,CAAA;YAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;SAC9B;QACD,IAAI,IAAI,EAAE;YACR,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;YACxB,MAAM,EAAE,CAAA;SACT;QACD,IAAI,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QACjC,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,MAAM;YACnC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;YAC7B,KAAK,IAAI,MAAM,CAAC,MAAM,CAAA;QACxB,CAAC,CAAC,CAAA;QACF,OAAO,MAAM,CAAA;IACf,CAAC;IAEM,MAAM,CAAC,MAAM;QAClB,IAAI,KAAK,GAAG,IAAI,UAAU,EAAE,CAAA;QAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACzC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;SACxB;QACD,OAAO,KAAK,CAAC,IAAI,EAAE,CAAA;IACrB,CAAC;CACF;AA9ED,6BA8EC"} \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/testing/test-buffers.js b/packages/pg-packet-stream/dist/testing/test-buffers.js new file mode 100644 index 000000000..4f174075d --- /dev/null +++ b/packages/pg-packet-stream/dist/testing/test-buffers.js @@ -0,0 +1,164 @@ +"use strict"; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +// http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html +const buffer_list_1 = __importDefault(require("./buffer-list")); +const buffers = { + readyForQuery: function () { + return new buffer_list_1.default() + .add(Buffer.from('I')) + .join(true, 'Z'); + }, + authenticationOk: function () { + return new buffer_list_1.default() + .addInt32(0) + .join(true, 'R'); + }, + authenticationCleartextPassword: function () { + return new buffer_list_1.default() + .addInt32(3) + .join(true, 'R'); + }, + authenticationMD5Password: function () { + return new buffer_list_1.default() + .addInt32(5) + .add(Buffer.from([1, 2, 3, 4])) + .join(true, 'R'); + }, + authenticationSASL: function () { + return new buffer_list_1.default() + .addInt32(10) + .addCString('SCRAM-SHA-256') + .addCString('') + .join(true, 'R'); + }, + authenticationSASLContinue: function () { + return new buffer_list_1.default() + .addInt32(11) + .addString('data') + .join(true, 'R'); + }, + authenticationSASLFinal: function () { + return new buffer_list_1.default() + .addInt32(12) + .addString('data') + .join(true, 'R'); + }, + parameterStatus: function (name, value) { + return new buffer_list_1.default() + .addCString(name) + .addCString(value) + .join(true, 'S'); + }, + backendKeyData: function (processID, secretKey) { + return new buffer_list_1.default() + .addInt32(processID) + .addInt32(secretKey) + .join(true, 'K'); + }, + commandComplete: function (string) { + return new buffer_list_1.default() + .addCString(string) + .join(true, 'C'); + }, + rowDescription: function (fields) { + fields = fields || []; + var buf = new buffer_list_1.default(); + buf.addInt16(fields.length); + fields.forEach(function (field) { + buf.addCString(field.name) + .addInt32(field.tableID || 0) + .addInt16(field.attributeNumber || 0) + .addInt32(field.dataTypeID || 0) + .addInt16(field.dataTypeSize || 0) + .addInt32(field.typeModifier || 0) + .addInt16(field.formatCode || 0); + }); + return buf.join(true, 'T'); + }, + dataRow: function (columns) { + columns = columns || []; + var buf = new buffer_list_1.default(); + buf.addInt16(columns.length); + columns.forEach(function (col) { + if (col == null) { + buf.addInt32(-1); + } + else { + var strBuf = Buffer.from(col, 'utf8'); + buf.addInt32(strBuf.length); + buf.add(strBuf); + } + }); + return buf.join(true, 'D'); + }, + error: function (fields) { + return buffers.errorOrNotice(fields).join(true, 'E'); + }, + notice: function (fields) { + return buffers.errorOrNotice(fields).join(true, 'N'); + }, + errorOrNotice: function (fields) { + fields = fields || []; + var buf = new buffer_list_1.default(); + fields.forEach(function (field) { + buf.addChar(field.type); + buf.addCString(field.value); + }); + return buf.add(Buffer.from([0])); // terminator + }, + parseComplete: function () { + return new buffer_list_1.default().join(true, '1'); + }, + bindComplete: function () { + return new buffer_list_1.default().join(true, '2'); + }, + notification: function (id, channel, payload) { + return new buffer_list_1.default() + .addInt32(id) + .addCString(channel) + .addCString(payload) + .join(true, 'A'); + }, + emptyQuery: function () { + return new buffer_list_1.default().join(true, 'I'); + }, + portalSuspended: function () { + return new buffer_list_1.default().join(true, 's'); + }, + closeComplete: function () { + return new buffer_list_1.default().join(true, '3'); + }, + copyIn: function (cols) { + const list = new buffer_list_1.default() + // text mode + .addByte(0) + // column count + .addInt16(cols); + for (let i = 0; i < cols; i++) { + list.addInt16(i); + } + return list.join(true, 'G'); + }, + copyOut: function (cols) { + const list = new buffer_list_1.default() + // text mode + .addByte(0) + // column count + .addInt16(cols); + for (let i = 0; i < cols; i++) { + list.addInt16(i); + } + return list.join(true, 'H'); + }, + copyData: function (bytes) { + return new buffer_list_1.default().add(bytes).join(true, 'd'); + }, + copyDone: function () { + return new buffer_list_1.default().join(true, 'c'); + } +}; +exports.default = buffers; +//# sourceMappingURL=test-buffers.js.map \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/testing/test-buffers.js.map b/packages/pg-packet-stream/dist/testing/test-buffers.js.map new file mode 100644 index 000000000..e0aa10721 --- /dev/null +++ b/packages/pg-packet-stream/dist/testing/test-buffers.js.map @@ -0,0 +1 @@ +{"version":3,"file":"test-buffers.js","sourceRoot":"","sources":["../../src/testing/test-buffers.ts"],"names":[],"mappings":";;;;;AAAA,gFAAgF;AAChF,gEAAsC;AAEtC,MAAM,OAAO,GAAG;IACd,aAAa,EAAE;QACb,OAAO,IAAI,qBAAU,EAAE;aACpB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;aACrB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,gBAAgB,EAAE;QAChB,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,CAAC,CAAC;aACX,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,+BAA+B,EAAE;QAC/B,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,CAAC,CAAC;aACX,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,yBAAyB,EAAE;QACzB,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,CAAC,CAAC;aACX,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;aAC9B,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,kBAAkB,EAAE;QAClB,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,EAAE,CAAC;aACZ,UAAU,CAAC,eAAe,CAAC;aAC3B,UAAU,CAAC,EAAE,CAAC;aACd,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,0BAA0B,EAAE;QAC1B,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,EAAE,CAAC;aACZ,SAAS,CAAC,MAAM,CAAC;aACjB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,uBAAuB,EAAE;QACvB,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,EAAE,CAAC;aACZ,SAAS,CAAC,MAAM,CAAC;aACjB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,eAAe,EAAE,UAAU,IAAY,EAAE,KAAa;QACpD,OAAO,IAAI,qBAAU,EAAE;aACpB,UAAU,CAAC,IAAI,CAAC;aAChB,UAAU,CAAC,KAAK,CAAC;aACjB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,cAAc,EAAE,UAAU,SAAiB,EAAE,SAAiB;QAC5D,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,SAAS,CAAC;aACnB,QAAQ,CAAC,SAAS,CAAC;aACnB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,eAAe,EAAE,UAAU,MAAc;QACvC,OAAO,IAAI,qBAAU,EAAE;aACpB,UAAU,CAAC,MAAM,CAAC;aAClB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,cAAc,EAAE,UAAU,MAAa;QACrC,MAAM,GAAG,MAAM,IAAI,EAAE,CAAA;QACrB,IAAI,GAAG,GAAG,IAAI,qBAAU,EAAE,CAAA;QAC1B,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QAC3B,MAAM,CAAC,OAAO,CAAC,UAAU,KAAK;YAC5B,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;iBACvB,QAAQ,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;iBAC5B,QAAQ,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,CAAC;iBACpC,QAAQ,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC;iBAC/B,QAAQ,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC;iBACjC,QAAQ,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC;iBACjC,QAAQ,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC,CAAA;QACpC,CAAC,CAAC,CAAA;QACF,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC5B,CAAC;IAED,OAAO,EAAE,UAAU,OAAc;QAC/B,OAAO,GAAG,OAAO,IAAI,EAAE,CAAA;QACvB,IAAI,GAAG,GAAG,IAAI,qBAAU,EAAE,CAAA;QAC1B,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAC5B,OAAO,CAAC,OAAO,CAAC,UAAU,GAAG;YAC3B,IAAI,GAAG,IAAI,IAAI,EAAE;gBACf,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;aACjB;iBAAM;gBACL,IAAI,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;gBACrC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;gBAC3B,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;aAChB;QACH,CAAC,CAAC,CAAA;QACF,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC5B,CAAC;IAED,KAAK,EAAE,UAAU,MAAW;QAC1B,OAAO,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACtD,CAAC;IAED,MAAM,EAAE,UAAU,MAAW;QAC3B,OAAO,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACtD,CAAC;IAED,aAAa,EAAE,UAAU,MAAW;QAClC,MAAM,GAAG,MAAM,IAAI,EAAE,CAAA;QACrB,IAAI,GAAG,GAAG,IAAI,qBAAU,EAAE,CAAA;QAC1B,MAAM,CAAC,OAAO,CAAC,UAAU,KAAU;YACjC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YACvB,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAC7B,CAAC,CAAC,CAAA;QACF,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA,CAAA,aAAa;IAC/C,CAAC;IAED,aAAa,EAAE;QACb,OAAO,IAAI,qBAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACzC,CAAC;IAED,YAAY,EAAE;QACZ,OAAO,IAAI,qBAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACzC,CAAC;IAED,YAAY,EAAE,UAAU,EAAU,EAAE,OAAe,EAAE,OAAe;QAClE,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,EAAE,CAAC;aACZ,UAAU,CAAC,OAAO,CAAC;aACnB,UAAU,CAAC,OAAO,CAAC;aACnB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,UAAU,EAAE;QACV,OAAO,IAAI,qBAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACzC,CAAC;IAED,eAAe,EAAE;QACf,OAAO,IAAI,qBAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACzC,CAAC;IAED,aAAa,EAAE;QACb,OAAO,IAAI,qBAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACzC,CAAC;IAED,MAAM,EAAE,UAAU,IAAY;QAC5B,MAAM,IAAI,GAAG,IAAI,qBAAU,EAAE;YAC3B,YAAY;aACX,OAAO,CAAC,CAAC,CAAC;YACX,eAAe;aACd,QAAQ,CAAC,IAAI,CAAC,CAAC;QAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE;YAC7B,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;SAClB;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC7B,CAAC;IAED,OAAO,EAAE,UAAU,IAAY;QAC7B,MAAM,IAAI,GAAG,IAAI,qBAAU,EAAE;YAC3B,YAAY;aACX,OAAO,CAAC,CAAC,CAAC;YACX,eAAe;aACd,QAAQ,CAAC,IAAI,CAAC,CAAC;QAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE;YAC7B,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;SAClB;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC7B,CAAC;IAED,QAAQ,EAAE,UAAU,KAAa;QAC/B,OAAO,IAAI,qBAAU,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACrD,CAAC;IAED,QAAQ,EAAE;QACR,OAAO,IAAI,qBAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACzC,CAAC;CACF,CAAA;AAED,kBAAe,OAAO,CAAA"} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 110a8dc72..7fd9acf02 100644 --- a/yarn.lock +++ b/yarn.lock @@ -872,16 +872,41 @@ JSONStream@^1.0.4, JSONStream@^1.3.4: jsonparse "^1.2.0" through ">=2.2.7 <3" +JSONStream@~0.7.1: + version "0.7.4" + resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-0.7.4.tgz#734290e41511eea7c2cfe151fbf9a563a97b9786" + integrity sha1-c0KQ5BUR7qfCz+FR+/mlY6l7l4Y= + dependencies: + jsonparse "0.0.5" + through ">=2.2.7 <3" + abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +acorn-jsx@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" + integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= + dependencies: + acorn "^3.0.4" + acorn-jsx@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== +acorn@^3.0.4: + version "3.3.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" + integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= + +acorn@^5.5.0: + version "5.7.3" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" + integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== + acorn@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" @@ -908,6 +933,21 @@ agentkeepalive@^3.4.1: dependencies: humanize-ms "^1.2.1" +ajv-keywords@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" + integrity sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I= + +ajv@^5.2.3, ajv@^5.3.0: + version "5.5.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" + integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= + dependencies: + co "^4.6.0" + fast-deep-equal "^1.0.0" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.3.0" + ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: version "6.10.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" @@ -923,7 +963,7 @@ ansi-colors@3.2.3: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== -ansi-escapes@^3.2.0: +ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== @@ -955,6 +995,11 @@ ansi-regex@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -1077,6 +1122,15 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= +assertions@~2.3.0: + version "2.3.4" + resolved "https://registry.yarnpkg.com/assertions/-/assertions-2.3.4.tgz#a9433ced1fce57cc999af0965d1008e96c2796e6" + integrity sha1-qUM87R/OV8yZmvCWXRAI6WwnluY= + dependencies: + fomatto "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6" + render "0.1" + traverser "1" + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -1117,11 +1171,25 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c" integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A== +babel-code-frame@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= +base64-js@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.2.tgz#024f0f72afa25b75f9c0ee73cd4f55ec1bed9784" + integrity sha1-Ak8Pcq+iW3X5wO5zzU9V7Bvtl4Q= + base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" @@ -1157,6 +1225,14 @@ bluebird@^3.5.1, bluebird@^3.5.3, bluebird@^3.5.5: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== +bops@0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/bops/-/bops-0.0.6.tgz#082d1d55fa01e60dbdc2ebc2dba37f659554cf3a" + integrity sha1-CC0dVfoB5g29wuvC26N/ZZVUzzo= + dependencies: + base64-js "0.0.2" + to-utf8 "0.0.1" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1264,6 +1340,13 @@ caller-callsite@^2.0.0: dependencies: callsites "^2.0.0" +caller-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" + integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= + dependencies: + callsites "^0.2.0" + caller-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" @@ -1271,6 +1354,11 @@ caller-path@^2.0.0: dependencies: caller-callsite "^2.0.0" +callsites@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" + integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= + callsites@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" @@ -1318,6 +1406,17 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1327,6 +1426,11 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chardet@^0.4.0: + version "0.4.2" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" + integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -1342,6 +1446,11 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== +circular-json@^0.3.1: + version "0.3.3" + resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" + integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== + class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -1394,7 +1503,7 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= -co@4.6.0: +co@4.6.0, co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= @@ -1462,7 +1571,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.5.0: +concat-stream@^1.5.0, concat-stream@^1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -1482,6 +1591,13 @@ concat-stream@^2.0.0: readable-stream "^3.0.2" typedarray "^0.0.6" +concat-stream@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.0.1.tgz#018b18bc1c7d073a2dc82aa48442341a2c4dd79f" + integrity sha1-AYsYvBx9BzotyCqkhEI0GixN158= + dependencies: + bops "0.0.6" + config-chain@^1.1.11: version "1.1.12" resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" @@ -1615,6 +1731,15 @@ cosmiconfig@^5.1.0: js-yaml "^3.13.1" parse-json "^4.0.0" +cross-spawn@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -1633,6 +1758,11 @@ currently-unhandled@^0.4.1: dependencies: array-find-index "^1.0.1" +curry@0.0.x: + version "0.0.4" + resolved "https://registry.yarnpkg.com/curry/-/curry-0.0.4.tgz#1750d518d919c44f3d37ff44edc693de1f0d5fcb" + integrity sha1-F1DVGNkZxE89N/9E7caT3h8NX8s= + cyclist@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" @@ -1802,6 +1932,13 @@ doctrine@1.5.0: esutils "^2.0.2" isarray "^1.0.0" +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -1925,7 +2062,7 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -1937,6 +2074,11 @@ eslint-config-prettier@^6.4.0: dependencies: get-stdin "^6.0.0" +eslint-config-standard@^10.2.1: + version "10.2.1" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591" + integrity sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE= + eslint-config-standard@^13.0.1: version "13.0.1" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-13.0.1.tgz#c9c6ffe0cfb8a51535bc5c7ec9f70eafb8c6b2c0" @@ -1966,7 +2108,7 @@ eslint-plugin-es@^1.4.1: eslint-utils "^1.4.2" regexpp "^2.0.1" -eslint-plugin-import@^2.18.1: +eslint-plugin-import@^2.18.1, eslint-plugin-import@^2.7.0: version "2.19.1" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.19.1.tgz#5654e10b7839d064dd0d46cd1b88ec2133a11448" integrity sha512-x68131aKoCZlCae7rDXKSAQmbT5DQuManyXo2sK6fJJ0aK5CWAkv6A6HJZGgqC8IhjQxYPgo6/IY4Oz8AFsbBw== @@ -1984,6 +2126,16 @@ eslint-plugin-import@^2.18.1: read-pkg-up "^2.0.0" resolve "^1.12.0" +eslint-plugin-node@^5.1.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz#80df3253c4d7901045ec87fa660a284e32bdca29" + integrity sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g== + dependencies: + ignore "^3.3.6" + minimatch "^3.0.4" + resolve "^1.3.3" + semver "5.3.0" + eslint-plugin-node@^9.1.0: version "9.2.0" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-9.2.0.tgz#b1911f111002d366c5954a6d96d3cd5bf2a3036a" @@ -2003,16 +2155,34 @@ eslint-plugin-prettier@^3.1.1: dependencies: prettier-linter-helpers "^1.0.0" +eslint-plugin-promise@^3.5.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621" + integrity sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ== + eslint-plugin-promise@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw== +eslint-plugin-standard@^3.0.1: + version "3.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz#2a9e21259ba4c47c02d53b2d0c9135d4b1022d47" + integrity sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w== + eslint-plugin-standard@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz#ff0519f7ffaff114f76d1bd7c3996eef0f6e20b4" integrity sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ== +eslint-scope@^3.7.1: + version "3.7.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" + integrity sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + eslint-scope@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" @@ -2028,11 +2198,55 @@ eslint-utils@^1.4.2, eslint-utils@^1.4.3: dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.1.0: +eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== +eslint@^4.4.0: + version "4.19.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" + integrity sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ== + dependencies: + ajv "^5.3.0" + babel-code-frame "^6.22.0" + chalk "^2.1.0" + concat-stream "^1.6.0" + cross-spawn "^5.1.0" + debug "^3.1.0" + doctrine "^2.1.0" + eslint-scope "^3.7.1" + eslint-visitor-keys "^1.0.0" + espree "^3.5.4" + esquery "^1.0.0" + esutils "^2.0.2" + file-entry-cache "^2.0.0" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.0.1" + ignore "^3.3.3" + imurmurhash "^0.1.4" + inquirer "^3.0.6" + is-resolvable "^1.0.0" + js-yaml "^3.9.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.4" + minimatch "^3.0.2" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + pluralize "^7.0.0" + progress "^2.0.0" + regexpp "^1.0.1" + require-uncached "^1.0.3" + semver "^5.3.0" + strip-ansi "^4.0.0" + strip-json-comments "~2.0.1" + table "4.0.2" + text-table "~0.2.0" + eslint@^6.0.1, eslint@^6.5.1: version "6.7.2" resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.2.tgz#c17707ca4ad7b2d8af986a33feba71e18a9fecd1" @@ -2076,6 +2290,14 @@ eslint@^6.0.1, eslint@^6.5.1: text-table "^0.2.0" v8-compile-cache "^2.0.3" +espree@^3.5.4: + version "3.5.4" + resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" + integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== + dependencies: + acorn "^5.5.0" + acorn-jsx "^3.0.0" + espree@^6.1.2: version "6.1.2" resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" @@ -2090,7 +2312,7 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1: +esquery@^1.0.0, esquery@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== @@ -2165,6 +2387,15 @@ extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== +external-editor@^2.0.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" + integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== + dependencies: + chardet "^0.4.0" + iconv-lite "^0.4.17" + tmp "^0.0.33" + external-editor@^3.0.3: version "3.1.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" @@ -2198,6 +2429,11 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= +fast-deep-equal@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" + integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= + fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" @@ -2249,6 +2485,14 @@ figures@^3.0.0: dependencies: escape-string-regexp "^1.0.5" +file-entry-cache@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" + integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= + dependencies: + flat-cache "^1.2.1" + object-assign "^4.0.1" + file-entry-cache@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" @@ -2288,6 +2532,16 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" +flat-cache@^1.2.1: + version "1.3.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" + integrity sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg== + dependencies: + circular-json "^0.3.1" + graceful-fs "^4.1.2" + rimraf "~2.6.2" + write "^0.2.1" + flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -2317,6 +2571,10 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" +"fomatto@git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6": + version "0.6.0" + resolved "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6" + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -2351,6 +2609,11 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" +from@~0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/from/-/from-0.0.2.tgz#7fffac647a2f99b20d57b8e28379455cbb4189d0" + integrity sha1-f/+sZHovmbINV7jig3lFXLtBidA= + fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -2542,7 +2805,7 @@ glob@7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -2554,6 +2817,11 @@ glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" +globals@^11.0.1: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + globals@^12.1.0: version "12.3.0" resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13" @@ -2609,6 +2877,13 @@ har-validator@~5.1.0: ajv "^6.5.5" har-schema "^2.0.0" +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -2709,7 +2984,7 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-lite@^0.4.24, iconv-lite@~0.4.13: +iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -2728,6 +3003,11 @@ ignore-walk@^3.0.1: dependencies: minimatch "^3.0.4" +ignore@^3.3.3, ignore@^3.3.6: + version "3.3.10" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== + ignore@^4.0.3, ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -2816,6 +3096,26 @@ init-package-json@^1.10.3: validate-npm-package-license "^3.0.1" validate-npm-package-name "^3.0.0" +inquirer@^3.0.6: + version "3.3.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" + integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ== + dependencies: + ansi-escapes "^3.0.0" + chalk "^2.0.0" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^2.0.4" + figures "^2.0.0" + lodash "^4.3.0" + mute-stream "0.0.7" + run-async "^2.2.0" + rx-lite "^4.0.8" + rx-lite-aggregates "^4.0.8" + string-width "^2.1.0" + strip-ansi "^4.0.0" + through "^2.3.6" + inquirer@^6.2.0: version "6.5.2" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" @@ -3040,6 +3340,11 @@ is-regex@^1.0.4: dependencies: has "^1.0.3" +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== + is-ssh@^1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.1.tgz#f349a8cadd24e65298037a522cf7520f2e81a0f3" @@ -3113,12 +3418,17 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.13.1, js-yaml@^3.13.1: +js-yaml@3.13.1, js-yaml@^3.13.1, js-yaml@^3.9.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -3136,6 +3446,11 @@ json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1: resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== +json-schema-traverse@^0.3.0: + version "0.3.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" + integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -3163,6 +3478,11 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" +jsonparse@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-0.0.5.tgz#330542ad3f0a654665b778f3eb2d9a9fa507ac64" + integrity sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ= + jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" @@ -3341,7 +3661,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: +lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.2.1, lodash@^4.3.0: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -3361,6 +3681,14 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -3368,6 +3696,11 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +macgyver@~1.10: + version "1.10.1" + resolved "https://registry.yarnpkg.com/macgyver/-/macgyver-1.10.1.tgz#b09d1599d8b36ed5b16f59589515d9d14bc2fd88" + integrity sha1-sJ0VmdizbtWxb1lYlRXZ0UvC/Yg= + macos-release@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" @@ -3519,7 +3852,7 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@3.0.4, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -3966,7 +4299,7 @@ optimist@^0.6.1: minimist "~0.0.1" wordwrap "~0.0.2" -optionator@^0.8.3: +optionator@^0.8.2, optionator@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -4169,6 +4502,11 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -4286,6 +4624,11 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" +pluralize@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" + integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -4377,6 +4720,11 @@ protoduck@^5.0.1: dependencies: genfun "^5.0.0" +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= + psl@^1.1.24: version "1.6.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.6.0.tgz#60557582ee23b6c43719d9890fb4170ecd91e110" @@ -4574,11 +4922,23 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexpp@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" + integrity sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw== + regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== +render@0.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/render/-/render-0.1.4.tgz#cfb33a34e26068591d418469e23d8cc5ce1ceff5" + integrity sha1-z7M6NOJgaFkdQYRp4j2Mxc4c7/U= + dependencies: + traverser "0.0.x" + repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" @@ -4632,6 +4992,14 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== +require-uncached@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" + integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= + dependencies: + caller-path "^0.1.0" + resolve-from "^1.0.0" + resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" @@ -4639,6 +5007,11 @@ resolve-cwd@^2.0.0: dependencies: resolve-from "^3.0.0" +resolve-from@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" + integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= + resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" @@ -4661,6 +5034,13 @@ resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.5.0: dependencies: path-parse "^1.0.6" +resolve@^1.3.3: + version "1.14.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.1.tgz#9e018c540fcf0c427d678b9931cbf45e984bcaff" + integrity sha512-fn5Wobh4cxbLzuHaE+nphztHy43/b++4M6SsGFC2gB8uYwf0C8LcarfCz1un7UTW8OFQg9iNjZ4xpcFVGebDPg== + dependencies: + path-parse "^1.0.6" + restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -4687,7 +5067,7 @@ retry@^0.10.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q= -rimraf@2.6.3: +rimraf@2.6.3, rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== @@ -4715,6 +5095,18 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" +rx-lite-aggregates@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" + integrity sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74= + dependencies: + rx-lite "*" + +rx-lite@*, rx-lite@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" + integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ= + rxjs@^6.4.0, rxjs@^6.5.3: version "6.5.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" @@ -4744,7 +5136,7 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -4754,6 +5146,11 @@ semver@4.3.2: resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= +semver@5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" + integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= + semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.2.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" @@ -4803,6 +5200,13 @@ slash@^2.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== +slice-ansi@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" + integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== + dependencies: + is-fullwidth-code-point "^2.0.0" + slice-ansi@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" @@ -4996,6 +5400,22 @@ stream-shift@^1.0.0: resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== +stream-spec@~0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/stream-spec/-/stream-spec-0.3.6.tgz#2fddac4a07bf3e9f8963c677a6b5a6cc2115255e" + integrity sha1-L92sSge/Pp+JY8Z3prWmzCEVJV4= + dependencies: + macgyver "~1.10" + +stream-tester@0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/stream-tester/-/stream-tester-0.0.5.tgz#4f86f2531149adaf6dd4b3ff262edf64ae9a171a" + integrity sha1-T4byUxFJra9t1LP/Ji7fZK6aFxo= + dependencies: + assertions "~2.3.0" + from "~0.0.2" + through "~0.0.3" + string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -5005,7 +5425,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.1.0: +"string-width@^1.0.2 || 2", string-width@^2.1.0, string-width@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -5118,7 +5538,7 @@ strip-indent@^2.0.0: resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= -strip-json-comments@2.0.1: +strip-json-comments@2.0.1, strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= @@ -5144,6 +5564,11 @@ supports-color@6.0.0: dependencies: has-flag "^3.0.0" +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -5151,6 +5576,18 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +table@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" + integrity sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA== + dependencies: + ajv "^5.2.3" + ajv-keywords "^2.1.0" + chalk "^2.1.0" + lodash "^4.17.4" + slice-ansi "1.0.0" + string-width "^2.1.1" + table@^5.2.3: version "5.4.6" resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" @@ -5196,7 +5633,7 @@ text-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== -text-table@^0.2.0: +text-table@^0.2.0, text-table@~0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= @@ -5230,11 +5667,16 @@ through2@^3.0.0: dependencies: readable-stream "2 || 3" -through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6: +through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@~2.3.4: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= +through@~0.0.3: + version "0.0.4" + resolved "https://registry.yarnpkg.com/through/-/through-0.0.4.tgz#0bf2f0fffafaac4bacbc533667e98aad00b588c8" + integrity sha1-C/Lw//r6rEusvFM2Z+mKrQC1iMg= + tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -5267,6 +5709,11 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" +to-utf8@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/to-utf8/-/to-utf8-0.0.1.tgz#d17aea72ff2fba39b9e43601be7b3ff72e089852" + integrity sha1-0Xrqcv8vujm55DYBvns/9y4ImFI= + tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" @@ -5282,6 +5729,20 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" +traverser@0.0.x: + version "0.0.5" + resolved "https://registry.yarnpkg.com/traverser/-/traverser-0.0.5.tgz#c66f38c456a0c21a88014b1223580c7ebe0631eb" + integrity sha1-xm84xFagwhqIAUsSI1gMfr4GMes= + dependencies: + curry "0.0.x" + +traverser@1: + version "1.0.0" + resolved "https://registry.yarnpkg.com/traverser/-/traverser-1.0.0.tgz#6f59e5813759aeeab3646b8f4513fd4a62e4fe20" + integrity sha1-b1nlgTdZruqzZGuPRRP9SmLk/iA= + dependencies: + curry "0.0.x" + trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" @@ -5580,6 +6041,13 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" +write@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" + integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= + dependencies: + mkdirp "^0.5.1" + xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" @@ -5590,6 +6058,11 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= + yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" From ef2f2d264d71d3eb80b62e3e008924bdaf2c2db2 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 20 Dec 2019 12:17:53 -0600 Subject: [PATCH 0549/1037] Unify lint Delete accidental addition --- .../pg-packet-stream/dist/BufferReader.js | 48 -- .../pg-packet-stream/dist/BufferReader.js.map | 1 - .../dist/inbound-parser.test.js | 469 ------------------ .../dist/inbound-parser.test.js.map | 1 - packages/pg-packet-stream/dist/index.js | 264 ---------- packages/pg-packet-stream/dist/index.js.map | 1 - packages/pg-packet-stream/dist/index.test.js | 109 ---- .../pg-packet-stream/dist/index.test.js.map | 1 - packages/pg-packet-stream/dist/messages.js | 134 ----- .../pg-packet-stream/dist/messages.js.map | 1 - .../dist/testing/buffer-list.js | 73 --- .../dist/testing/buffer-list.js.map | 1 - .../dist/testing/test-buffers.js | 164 ------ .../dist/testing/test-buffers.js.map | 1 - packages/pg-query-stream/.eslintrc | 9 - packages/pg-query-stream/package.json | 15 +- yarn.lock | 396 +-------------- 17 files changed, 20 insertions(+), 1668 deletions(-) delete mode 100644 packages/pg-packet-stream/dist/BufferReader.js delete mode 100644 packages/pg-packet-stream/dist/BufferReader.js.map delete mode 100644 packages/pg-packet-stream/dist/inbound-parser.test.js delete mode 100644 packages/pg-packet-stream/dist/inbound-parser.test.js.map delete mode 100644 packages/pg-packet-stream/dist/index.js delete mode 100644 packages/pg-packet-stream/dist/index.js.map delete mode 100644 packages/pg-packet-stream/dist/index.test.js delete mode 100644 packages/pg-packet-stream/dist/index.test.js.map delete mode 100644 packages/pg-packet-stream/dist/messages.js delete mode 100644 packages/pg-packet-stream/dist/messages.js.map delete mode 100644 packages/pg-packet-stream/dist/testing/buffer-list.js delete mode 100644 packages/pg-packet-stream/dist/testing/buffer-list.js.map delete mode 100644 packages/pg-packet-stream/dist/testing/test-buffers.js delete mode 100644 packages/pg-packet-stream/dist/testing/test-buffers.js.map delete mode 100644 packages/pg-query-stream/.eslintrc diff --git a/packages/pg-packet-stream/dist/BufferReader.js b/packages/pg-packet-stream/dist/BufferReader.js deleted file mode 100644 index 60186a51c..000000000 --- a/packages/pg-packet-stream/dist/BufferReader.js +++ /dev/null @@ -1,48 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -const emptyBuffer = Buffer.allocUnsafe(0); -class BufferReader { - constructor(offset = 0) { - this.offset = offset; - this.buffer = emptyBuffer; - // TODO(bmc): support non-utf8 encoding - this.encoding = 'utf-8'; - } - setBuffer(offset, buffer) { - this.offset = offset; - this.buffer = buffer; - } - int16() { - const result = this.buffer.readInt16BE(this.offset); - this.offset += 2; - return result; - } - byte() { - const result = this.buffer[this.offset]; - this.offset++; - return result; - } - int32() { - const result = this.buffer.readInt32BE(this.offset); - this.offset += 4; - return result; - } - string(length) { - const result = this.buffer.toString(this.encoding, this.offset, this.offset + length); - this.offset += length; - return result; - } - cstring() { - var start = this.offset; - var end = this.buffer.indexOf(0, start); - this.offset = end + 1; - return this.buffer.toString(this.encoding, start, end); - } - bytes(length) { - const result = this.buffer.slice(this.offset, this.offset + length); - this.offset += length; - return result; - } -} -exports.BufferReader = BufferReader; -//# sourceMappingURL=BufferReader.js.map \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/BufferReader.js.map b/packages/pg-packet-stream/dist/BufferReader.js.map deleted file mode 100644 index a4c367c7d..000000000 --- a/packages/pg-packet-stream/dist/BufferReader.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"BufferReader.js","sourceRoot":"","sources":["../src/BufferReader.ts"],"names":[],"mappings":";;AAAA,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAE1C,MAAa,YAAY;IAIvB,YAAoB,SAAiB,CAAC;QAAlB,WAAM,GAAN,MAAM,CAAY;QAH9B,WAAM,GAAW,WAAW,CAAC;QACrC,uCAAuC;QAC/B,aAAQ,GAAW,OAAO,CAAC;IAEnC,CAAC;IACM,SAAS,CAAC,MAAc,EAAE,MAAc;QAC7C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IACM,KAAK;QACV,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;QACjB,OAAO,MAAM,CAAC;IAChB,CAAC;IACM,IAAI;QACT,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,EAAE,CAAC;QACd,OAAO,MAAM,CAAC;IAChB,CAAC;IACM,KAAK;QACV,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;QACjB,OAAO,MAAM,CAAC;IAChB,CAAC;IACM,MAAM,CAAC,MAAc;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QACtF,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC;QACtB,OAAO,MAAM,CAAC;IAChB,CAAC;IACM,OAAO;QACZ,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;QACxB,IAAI,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC;QACtB,OAAO,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;IACzD,CAAC;IACM,KAAK,CAAC,MAAc;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QACpE,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC;QACtB,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAzCD,oCAyCC"} \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/inbound-parser.test.js b/packages/pg-packet-stream/dist/inbound-parser.test.js deleted file mode 100644 index 288ea9656..000000000 --- a/packages/pg-packet-stream/dist/inbound-parser.test.js +++ /dev/null @@ -1,469 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const test_buffers_1 = __importDefault(require("./testing/test-buffers")); -const buffer_list_1 = __importDefault(require("./testing/buffer-list")); -const _1 = require("./"); -const assert_1 = __importDefault(require("assert")); -var authOkBuffer = test_buffers_1.default.authenticationOk(); -var paramStatusBuffer = test_buffers_1.default.parameterStatus('client_encoding', 'UTF8'); -var readyForQueryBuffer = test_buffers_1.default.readyForQuery(); -var backendKeyDataBuffer = test_buffers_1.default.backendKeyData(1, 2); -var commandCompleteBuffer = test_buffers_1.default.commandComplete('SELECT 3'); -var parseCompleteBuffer = test_buffers_1.default.parseComplete(); -var bindCompleteBuffer = test_buffers_1.default.bindComplete(); -var portalSuspendedBuffer = test_buffers_1.default.portalSuspended(); -var addRow = function (bufferList, name, offset) { - return bufferList.addCString(name) // field name - .addInt32(offset++) // table id - .addInt16(offset++) // attribute of column number - .addInt32(offset++) // objectId of field's data type - .addInt16(offset++) // datatype size - .addInt32(offset++) // type modifier - .addInt16(0); // format code, 0 => text -}; -var row1 = { - name: 'id', - tableID: 1, - attributeNumber: 2, - dataTypeID: 3, - dataTypeSize: 4, - typeModifier: 5, - formatCode: 0 -}; -var oneRowDescBuff = test_buffers_1.default.rowDescription([row1]); -row1.name = 'bang'; -var twoRowBuf = test_buffers_1.default.rowDescription([row1, { - name: 'whoah', - tableID: 10, - attributeNumber: 11, - dataTypeID: 12, - dataTypeSize: 13, - typeModifier: 14, - formatCode: 0 - }]); -var emptyRowFieldBuf = new buffer_list_1.default() - .addInt16(0) - .join(true, 'D'); -var emptyRowFieldBuf = test_buffers_1.default.dataRow([]); -var oneFieldBuf = new buffer_list_1.default() - .addInt16(1) // number of fields - .addInt32(5) // length of bytes of fields - .addCString('test') - .join(true, 'D'); -var oneFieldBuf = test_buffers_1.default.dataRow(['test']); -var expectedAuthenticationOkayMessage = { - name: 'authenticationOk', - length: 8 -}; -var expectedParameterStatusMessage = { - name: 'parameterStatus', - parameterName: 'client_encoding', - parameterValue: 'UTF8', - length: 25 -}; -var expectedBackendKeyDataMessage = { - name: 'backendKeyData', - processID: 1, - secretKey: 2 -}; -var expectedReadyForQueryMessage = { - name: 'readyForQuery', - length: 5, - status: 'I' -}; -var expectedCommandCompleteMessage = { - name: 'commandComplete', - length: 13, - text: 'SELECT 3' -}; -var emptyRowDescriptionBuffer = new buffer_list_1.default() - .addInt16(0) // number of fields - .join(true, 'T'); -var expectedEmptyRowDescriptionMessage = { - name: 'rowDescription', - length: 6, - fieldCount: 0, - fields: [], -}; -var expectedOneRowMessage = { - name: 'rowDescription', - length: 27, - fieldCount: 1, - fields: [{ - name: 'id', - tableID: 1, - columnID: 2, - dataTypeID: 3, - dataTypeSize: 4, - dataTypeModifier: 5, - format: 'text' - }] -}; -var expectedTwoRowMessage = { - name: 'rowDescription', - length: 53, - fieldCount: 2, - fields: [{ - name: 'bang', - tableID: 1, - columnID: 2, - dataTypeID: 3, - dataTypeSize: 4, - dataTypeModifier: 5, - format: 'text' - }, - { - name: 'whoah', - tableID: 10, - columnID: 11, - dataTypeID: 12, - dataTypeSize: 13, - dataTypeModifier: 14, - format: 'text' - }] -}; -const concat = (stream) => { - return new Promise((resolve) => { - const results = []; - stream.on('data', item => results.push(item)); - stream.on('end', () => resolve(results)); - }); -}; -var testForMessage = function (buffer, expectedMessage) { - it('recieves and parses ' + expectedMessage.name, () => __awaiter(this, void 0, void 0, function* () { - const parser = new _1.PgPacketStream(); - parser.write(buffer); - parser.end(); - const [lastMessage] = yield concat(parser); - for (const key in expectedMessage) { - assert_1.default.deepEqual(lastMessage[key], expectedMessage[key]); - } - })); -}; -var plainPasswordBuffer = test_buffers_1.default.authenticationCleartextPassword(); -var md5PasswordBuffer = test_buffers_1.default.authenticationMD5Password(); -var SASLBuffer = test_buffers_1.default.authenticationSASL(); -var SASLContinueBuffer = test_buffers_1.default.authenticationSASLContinue(); -var SASLFinalBuffer = test_buffers_1.default.authenticationSASLFinal(); -var expectedPlainPasswordMessage = { - name: 'authenticationCleartextPassword' -}; -var expectedMD5PasswordMessage = { - name: 'authenticationMD5Password', - salt: Buffer.from([1, 2, 3, 4]) -}; -var expectedSASLMessage = { - name: 'authenticationSASL', - mechanisms: ['SCRAM-SHA-256'] -}; -var expectedSASLContinueMessage = { - name: 'authenticationSASLContinue', - data: 'data', -}; -var expectedSASLFinalMessage = { - name: 'authenticationSASLFinal', - data: 'data', -}; -var notificationResponseBuffer = test_buffers_1.default.notification(4, 'hi', 'boom'); -var expectedNotificationResponseMessage = { - name: 'notification', - processId: 4, - channel: 'hi', - payload: 'boom' -}; -describe('PgPacketStream', function () { - testForMessage(authOkBuffer, expectedAuthenticationOkayMessage); - testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage); - testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage); - testForMessage(SASLBuffer, expectedSASLMessage); - testForMessage(SASLContinueBuffer, expectedSASLContinueMessage); - testForMessage(SASLFinalBuffer, expectedSASLFinalMessage); - testForMessage(paramStatusBuffer, expectedParameterStatusMessage); - testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage); - testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage); - testForMessage(commandCompleteBuffer, expectedCommandCompleteMessage); - testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage); - testForMessage(test_buffers_1.default.emptyQuery(), { - name: 'emptyQuery', - length: 4, - }); - testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), { - name: 'noData' - }); - describe('rowDescription messages', function () { - testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage); - testForMessage(oneRowDescBuff, expectedOneRowMessage); - testForMessage(twoRowBuf, expectedTwoRowMessage); - }); - describe('parsing rows', function () { - describe('parsing empty row', function () { - testForMessage(emptyRowFieldBuf, { - name: 'dataRow', - fieldCount: 0 - }); - }); - describe('parsing data row with fields', function () { - testForMessage(oneFieldBuf, { - name: 'dataRow', - fieldCount: 1, - fields: ['test'] - }); - }); - }); - describe('notice message', function () { - // this uses the same logic as error message - var buff = test_buffers_1.default.notice([{ type: 'C', value: 'code' }]); - testForMessage(buff, { - name: 'notice', - code: 'code' - }); - }); - testForMessage(test_buffers_1.default.error([]), { - name: 'error' - }); - describe('with all the fields', function () { - var buffer = test_buffers_1.default.error([{ - type: 'S', - value: 'ERROR' - }, { - type: 'C', - value: 'code' - }, { - type: 'M', - value: 'message' - }, { - type: 'D', - value: 'details' - }, { - type: 'H', - value: 'hint' - }, { - type: 'P', - value: '100' - }, { - type: 'p', - value: '101' - }, { - type: 'q', - value: 'query' - }, { - type: 'W', - value: 'where' - }, { - type: 'F', - value: 'file' - }, { - type: 'L', - value: 'line' - }, { - type: 'R', - value: 'routine' - }, { - type: 'Z', - value: 'alsdkf' - }]); - testForMessage(buffer, { - name: 'error', - severity: 'ERROR', - code: 'code', - message: 'message', - detail: 'details', - hint: 'hint', - position: '100', - internalPosition: '101', - internalQuery: 'query', - where: 'where', - file: 'file', - line: 'line', - routine: 'routine' - }); - }); - testForMessage(parseCompleteBuffer, { - name: 'parseComplete' - }); - testForMessage(bindCompleteBuffer, { - name: 'bindComplete' - }); - testForMessage(bindCompleteBuffer, { - name: 'bindComplete' - }); - testForMessage(test_buffers_1.default.closeComplete(), { - name: 'closeComplete' - }); - describe('parses portal suspended message', function () { - testForMessage(portalSuspendedBuffer, { - name: 'portalSuspended' - }); - }); - describe('parses replication start message', function () { - testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { - name: 'replicationStart', - length: 4 - }); - }); - describe('copy', () => { - testForMessage(test_buffers_1.default.copyIn(0), { - name: 'copyInResponse', - length: 7, - binary: false, - columnTypes: [] - }); - testForMessage(test_buffers_1.default.copyIn(2), { - name: 'copyInResponse', - length: 11, - binary: false, - columnTypes: [0, 1] - }); - testForMessage(test_buffers_1.default.copyOut(0), { - name: 'copyOutResponse', - length: 7, - binary: false, - columnTypes: [] - }); - testForMessage(test_buffers_1.default.copyOut(3), { - name: 'copyOutResponse', - length: 13, - binary: false, - columnTypes: [0, 1, 2] - }); - testForMessage(test_buffers_1.default.copyDone(), { - name: 'copyDone', - length: 4, - }); - testForMessage(test_buffers_1.default.copyData(Buffer.from([5, 6, 7])), { - name: 'copyData', - length: 7, - chunk: Buffer.from([5, 6, 7]) - }); - }); - // since the data message on a stream can randomly divide the incomming - // tcp packets anywhere, we need to make sure we can parse every single - // split on a tcp message - describe('split buffer, single message parsing', function () { - var fullBuffer = test_buffers_1.default.dataRow([null, 'bang', 'zug zug', null, '!']); - const parse = (buffers) => __awaiter(this, void 0, void 0, function* () { - const parser = new _1.PgPacketStream(); - for (const buffer of buffers) { - parser.write(buffer); - } - parser.end(); - const [msg] = yield concat(parser); - return msg; - }); - it('parses when full buffer comes in', function () { - return __awaiter(this, void 0, void 0, function* () { - const message = yield parse([fullBuffer]); - assert_1.default.equal(message.fields.length, 5); - assert_1.default.equal(message.fields[0], null); - assert_1.default.equal(message.fields[1], 'bang'); - assert_1.default.equal(message.fields[2], 'zug zug'); - assert_1.default.equal(message.fields[3], null); - assert_1.default.equal(message.fields[4], '!'); - }); - }); - var testMessageRecievedAfterSpiltAt = function (split) { - return __awaiter(this, void 0, void 0, function* () { - var firstBuffer = Buffer.alloc(fullBuffer.length - split); - var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length); - fullBuffer.copy(firstBuffer, 0, 0); - fullBuffer.copy(secondBuffer, 0, firstBuffer.length); - const message = yield parse([firstBuffer, secondBuffer]); - assert_1.default.equal(message.fields.length, 5); - assert_1.default.equal(message.fields[0], null); - assert_1.default.equal(message.fields[1], 'bang'); - assert_1.default.equal(message.fields[2], 'zug zug'); - assert_1.default.equal(message.fields[3], null); - assert_1.default.equal(message.fields[4], '!'); - }); - }; - it('parses when split in the middle', function () { - testMessageRecievedAfterSpiltAt(6); - }); - it('parses when split at end', function () { - testMessageRecievedAfterSpiltAt(2); - }); - it('parses when split at beginning', function () { - testMessageRecievedAfterSpiltAt(fullBuffer.length - 2); - testMessageRecievedAfterSpiltAt(fullBuffer.length - 1); - testMessageRecievedAfterSpiltAt(fullBuffer.length - 5); - }); - }); - describe('split buffer, multiple message parsing', function () { - var dataRowBuffer = test_buffers_1.default.dataRow(['!']); - var readyForQueryBuffer = test_buffers_1.default.readyForQuery(); - var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length); - dataRowBuffer.copy(fullBuffer, 0, 0); - readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0); - const parse = (buffers) => { - const parser = new _1.PgPacketStream(); - for (const buffer of buffers) { - parser.write(buffer); - } - parser.end(); - return concat(parser); - }; - var verifyMessages = function (messages) { - assert_1.default.strictEqual(messages.length, 2); - assert_1.default.deepEqual(messages[0], { - name: 'dataRow', - fieldCount: 1, - length: 11, - fields: ['!'] - }); - assert_1.default.equal(messages[0].fields[0], '!'); - assert_1.default.deepEqual(messages[1], { - name: 'readyForQuery', - length: 5, - status: 'I' - }); - }; - // sanity check - it('recieves both messages when packet is not split', function () { - return __awaiter(this, void 0, void 0, function* () { - const messages = yield parse([fullBuffer]); - verifyMessages(messages); - }); - }); - var splitAndVerifyTwoMessages = function (split) { - return __awaiter(this, void 0, void 0, function* () { - var firstBuffer = Buffer.alloc(fullBuffer.length - split); - var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length); - fullBuffer.copy(firstBuffer, 0, 0); - fullBuffer.copy(secondBuffer, 0, firstBuffer.length); - const messages = yield parse([firstBuffer, secondBuffer]); - verifyMessages(messages); - }); - }; - describe('recieves both messages when packet is split', function () { - it('in the middle', function () { - return splitAndVerifyTwoMessages(11); - }); - it('at the front', function () { - return Promise.all([ - splitAndVerifyTwoMessages(fullBuffer.length - 1), - splitAndVerifyTwoMessages(fullBuffer.length - 4), - splitAndVerifyTwoMessages(fullBuffer.length - 6) - ]); - }); - it('at the end', function () { - return Promise.all([ - splitAndVerifyTwoMessages(8), - splitAndVerifyTwoMessages(1) - ]); - }); - }); - }); -}); -//# sourceMappingURL=inbound-parser.test.js.map \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/inbound-parser.test.js.map b/packages/pg-packet-stream/dist/inbound-parser.test.js.map deleted file mode 100644 index 8689edf67..000000000 --- a/packages/pg-packet-stream/dist/inbound-parser.test.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"inbound-parser.test.js","sourceRoot":"","sources":["../src/inbound-parser.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,0EAA4C;AAC5C,wEAA8C;AAC9C,yBAAmC;AACnC,oDAA2B;AAG3B,IAAI,YAAY,GAAG,sBAAO,CAAC,gBAAgB,EAAE,CAAA;AAC7C,IAAI,iBAAiB,GAAG,sBAAO,CAAC,eAAe,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAA;AAC1E,IAAI,mBAAmB,GAAG,sBAAO,CAAC,aAAa,EAAE,CAAA;AACjD,IAAI,oBAAoB,GAAG,sBAAO,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;AACvD,IAAI,qBAAqB,GAAG,sBAAO,CAAC,eAAe,CAAC,UAAU,CAAC,CAAA;AAC/D,IAAI,mBAAmB,GAAG,sBAAO,CAAC,aAAa,EAAE,CAAA;AACjD,IAAI,kBAAkB,GAAG,sBAAO,CAAC,YAAY,EAAE,CAAA;AAC/C,IAAI,qBAAqB,GAAG,sBAAO,CAAC,eAAe,EAAE,CAAA;AAErD,IAAI,MAAM,GAAG,UAAU,UAAsB,EAAE,IAAY,EAAE,MAAc;IACzE,OAAO,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,aAAa;SAC7C,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,WAAW;SAC9B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,6BAA6B;SAChD,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,gCAAgC;SACnD,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,gBAAgB;SACnC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,gBAAgB;SACnC,QAAQ,CAAC,CAAC,CAAC,CAAA,CAAC,yBAAyB;AAC1C,CAAC,CAAA;AAED,IAAI,IAAI,GAAG;IACT,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,CAAC;IACV,eAAe,EAAE,CAAC;IAClB,UAAU,EAAE,CAAC;IACb,YAAY,EAAE,CAAC;IACf,YAAY,EAAE,CAAC;IACf,UAAU,EAAE,CAAC;CACd,CAAA;AACD,IAAI,cAAc,GAAG,sBAAO,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,CAAA;AACnD,IAAI,CAAC,IAAI,GAAG,MAAM,CAAA;AAElB,IAAI,SAAS,GAAG,sBAAO,CAAC,cAAc,CAAC,CAAC,IAAI,EAAE;QAC5C,IAAI,EAAE,OAAO;QACb,OAAO,EAAE,EAAE;QACX,eAAe,EAAE,EAAE;QACnB,UAAU,EAAE,EAAE;QACd,YAAY,EAAE,EAAE;QAChB,YAAY,EAAE,EAAE;QAChB,UAAU,EAAE,CAAC;KACd,CAAC,CAAC,CAAA;AAEH,IAAI,gBAAgB,GAAG,IAAI,qBAAU,EAAE;KACpC,QAAQ,CAAC,CAAC,CAAC;KACX,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAElB,IAAI,gBAAgB,GAAG,sBAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;AAE1C,IAAI,WAAW,GAAG,IAAI,qBAAU,EAAE;KAC/B,QAAQ,CAAC,CAAC,CAAC,CAAC,mBAAmB;KAC/B,QAAQ,CAAC,CAAC,CAAC,CAAC,4BAA4B;KACxC,UAAU,CAAC,MAAM,CAAC;KAClB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAElB,IAAI,WAAW,GAAG,sBAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;AAE3C,IAAI,iCAAiC,GAAG;IACtC,IAAI,EAAE,kBAAkB;IACxB,MAAM,EAAE,CAAC;CACV,CAAA;AAED,IAAI,8BAA8B,GAAG;IACnC,IAAI,EAAE,iBAAiB;IACvB,aAAa,EAAE,iBAAiB;IAChC,cAAc,EAAE,MAAM;IACtB,MAAM,EAAE,EAAE;CACX,CAAA;AAED,IAAI,6BAA6B,GAAG;IAClC,IAAI,EAAE,gBAAgB;IACtB,SAAS,EAAE,CAAC;IACZ,SAAS,EAAE,CAAC;CACb,CAAA;AAED,IAAI,4BAA4B,GAAG;IACjC,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,GAAG;CACZ,CAAA;AAED,IAAI,8BAA8B,GAAG;IACnC,IAAI,EAAE,iBAAiB;IACvB,MAAM,EAAE,EAAE;IACV,IAAI,EAAE,UAAU;CACjB,CAAA;AACD,IAAI,yBAAyB,GAAG,IAAI,qBAAU,EAAE;KAC7C,QAAQ,CAAC,CAAC,CAAC,CAAC,mBAAmB;KAC/B,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;AAElB,IAAI,kCAAkC,GAAG;IACvC,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,CAAC;IACT,UAAU,EAAE,CAAC;IACb,MAAM,EAAE,EAAE;CACX,CAAA;AACD,IAAI,qBAAqB,GAAG;IAC1B,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,EAAE;IACV,UAAU,EAAE,CAAC;IACb,MAAM,EAAE,CAAC;YACP,IAAI,EAAE,IAAI;YACV,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,CAAC;YACX,UAAU,EAAE,CAAC;YACb,YAAY,EAAE,CAAC;YACf,gBAAgB,EAAE,CAAC;YACnB,MAAM,EAAE,MAAM;SACf,CAAC;CACH,CAAA;AAED,IAAI,qBAAqB,GAAG;IAC1B,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,EAAE;IACV,UAAU,EAAE,CAAC;IACb,MAAM,EAAE,CAAC;YACP,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,CAAC;YACV,QAAQ,EAAE,CAAC;YACX,UAAU,EAAE,CAAC;YACb,YAAY,EAAE,CAAC;YACf,gBAAgB,EAAE,CAAC;YACnB,MAAM,EAAE,MAAM;SACf;QACD;YACE,IAAI,EAAE,OAAO;YACb,OAAO,EAAE,EAAE;YACX,QAAQ,EAAE,EAAE;YACZ,UAAU,EAAE,EAAE;YACd,YAAY,EAAE,EAAE;YAChB,gBAAgB,EAAE,EAAE;YACpB,MAAM,EAAE,MAAM;SACf,CAAC;CACH,CAAA;AAED,MAAM,MAAM,GAAG,CAAC,MAAgB,EAAkB,EAAE;IAClD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,OAAO,GAAU,EAAE,CAAA;QACzB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;QAC7C,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;IAC1C,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AAED,IAAI,cAAc,GAAG,UAAU,MAAc,EAAE,eAAoB;IACjE,EAAE,CAAC,sBAAsB,GAAG,eAAe,CAAC,IAAI,EAAE,GAAS,EAAE;QAC3D,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAC;QACpC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACrB,MAAM,CAAC,GAAG,EAAE,CAAC;QACb,MAAM,CAAC,WAAW,CAAC,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QAE3C,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE;YACjC,gBAAM,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,eAAe,CAAC,GAAG,CAAC,CAAC,CAAA;SACzD;IAEH,CAAC,CAAA,CAAC,CAAA;AACJ,CAAC,CAAA;AAED,IAAI,mBAAmB,GAAG,sBAAO,CAAC,+BAA+B,EAAE,CAAA;AACnE,IAAI,iBAAiB,GAAG,sBAAO,CAAC,yBAAyB,EAAE,CAAA;AAC3D,IAAI,UAAU,GAAG,sBAAO,CAAC,kBAAkB,EAAE,CAAA;AAC7C,IAAI,kBAAkB,GAAG,sBAAO,CAAC,0BAA0B,EAAE,CAAA;AAC7D,IAAI,eAAe,GAAG,sBAAO,CAAC,uBAAuB,EAAE,CAAA;AAEvD,IAAI,4BAA4B,GAAG;IACjC,IAAI,EAAE,iCAAiC;CACxC,CAAA;AAED,IAAI,0BAA0B,GAAG;IAC/B,IAAI,EAAE,2BAA2B;IACjC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;CAChC,CAAA;AAED,IAAI,mBAAmB,GAAG;IACxB,IAAI,EAAE,oBAAoB;IAC1B,UAAU,EAAE,CAAC,eAAe,CAAC;CAC9B,CAAA;AAED,IAAI,2BAA2B,GAAG;IAChC,IAAI,EAAE,4BAA4B;IAClC,IAAI,EAAE,MAAM;CACb,CAAA;AAED,IAAI,wBAAwB,GAAG;IAC7B,IAAI,EAAE,yBAAyB;IAC/B,IAAI,EAAE,MAAM;CACb,CAAA;AAED,IAAI,0BAA0B,GAAG,sBAAO,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,CAAA;AACtE,IAAI,mCAAmC,GAAG;IACxC,IAAI,EAAE,cAAc;IACpB,SAAS,EAAE,CAAC;IACZ,OAAO,EAAE,IAAI;IACb,OAAO,EAAE,MAAM;CAChB,CAAA;AAED,QAAQ,CAAC,gBAAgB,EAAE;IACzB,cAAc,CAAC,YAAY,EAAE,iCAAiC,CAAC,CAAA;IAC/D,cAAc,CAAC,mBAAmB,EAAE,4BAA4B,CAAC,CAAA;IACjE,cAAc,CAAC,iBAAiB,EAAE,0BAA0B,CAAC,CAAA;IAC7D,cAAc,CAAC,UAAU,EAAE,mBAAmB,CAAC,CAAA;IAC/C,cAAc,CAAC,kBAAkB,EAAE,2BAA2B,CAAC,CAAA;IAC/D,cAAc,CAAC,eAAe,EAAE,wBAAwB,CAAC,CAAA;IAEzD,cAAc,CAAC,iBAAiB,EAAE,8BAA8B,CAAC,CAAA;IACjE,cAAc,CAAC,oBAAoB,EAAE,6BAA6B,CAAC,CAAA;IACnE,cAAc,CAAC,mBAAmB,EAAE,4BAA4B,CAAC,CAAA;IACjE,cAAc,CAAC,qBAAqB,EAAE,8BAA8B,CAAC,CAAA;IACrE,cAAc,CAAC,0BAA0B,EAAE,mCAAmC,CAAC,CAAA;IAC/E,cAAc,CAAC,sBAAO,CAAC,UAAU,EAAE,EAAE;QACnC,IAAI,EAAE,YAAY;QAClB,MAAM,EAAE,CAAC;KACV,CAAC,CAAA;IAEF,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;QAC9C,IAAI,EAAE,QAAQ;KACf,CAAC,CAAA;IAEF,QAAQ,CAAC,yBAAyB,EAAE;QAClC,cAAc,CAAC,yBAAyB,EAAE,kCAAkC,CAAC,CAAA;QAC7E,cAAc,CAAC,cAAc,EAAE,qBAAqB,CAAC,CAAA;QACrD,cAAc,CAAC,SAAS,EAAE,qBAAqB,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,cAAc,EAAE;QACvB,QAAQ,CAAC,mBAAmB,EAAE;YAC5B,cAAc,CAAC,gBAAgB,EAAE;gBAC/B,IAAI,EAAE,SAAS;gBACf,UAAU,EAAE,CAAC;aACd,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;QAEF,QAAQ,CAAC,8BAA8B,EAAE;YACvC,cAAc,CAAC,WAAW,EAAE;gBAC1B,IAAI,EAAE,SAAS;gBACf,UAAU,EAAE,CAAC;gBACb,MAAM,EAAE,CAAC,MAAM,CAAC;aACjB,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,gBAAgB,EAAE;QACzB,4CAA4C;QAC5C,IAAI,IAAI,GAAG,sBAAO,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;QACzD,cAAc,CAAC,IAAI,EAAE;YACnB,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,MAAM;SACb,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,cAAc,CAAC,sBAAO,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE;QAChC,IAAI,EAAE,OAAO;KACd,CAAC,CAAA;IAEF,QAAQ,CAAC,qBAAqB,EAAE;QAC9B,IAAI,MAAM,GAAG,sBAAO,CAAC,KAAK,CAAC,CAAC;gBAC1B,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,OAAO;aACf,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,MAAM;aACd,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,SAAS;aACjB,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,SAAS;aACjB,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,MAAM;aACd,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,KAAK;aACb,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,KAAK;aACb,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,OAAO;aACf,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,OAAO;aACf,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,MAAM;aACd,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,MAAM;aACd,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,SAAS;aACjB,EAAE;gBACD,IAAI,EAAE,GAAG;gBACT,KAAK,EAAE,QAAQ;aAChB,CAAC,CAAC,CAAA;QAEH,cAAc,CAAC,MAAM,EAAE;YACrB,IAAI,EAAE,OAAO;YACb,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,SAAS;YAClB,MAAM,EAAE,SAAS;YACjB,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,KAAK;YACf,gBAAgB,EAAE,KAAK;YACvB,aAAa,EAAE,OAAO;YACtB,KAAK,EAAE,OAAO;YACd,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,SAAS;SACnB,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,cAAc,CAAC,mBAAmB,EAAE;QAClC,IAAI,EAAE,eAAe;KACtB,CAAC,CAAA;IAEF,cAAc,CAAC,kBAAkB,EAAE;QACjC,IAAI,EAAE,cAAc;KACrB,CAAC,CAAA;IAEF,cAAc,CAAC,kBAAkB,EAAE;QACjC,IAAI,EAAE,cAAc;KACrB,CAAC,CAAA;IAEF,cAAc,CAAC,sBAAO,CAAC,aAAa,EAAE,EAAE;QACtC,IAAI,EAAE,eAAe;KACtB,CAAC,CAAA;IAEF,QAAQ,CAAC,iCAAiC,EAAE;QAC1C,cAAc,CAAC,qBAAqB,EAAE;YACpC,IAAI,EAAE,iBAAiB;SACxB,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,kCAAkC,EAAE;QAC3C,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE;YAC1D,IAAI,EAAE,kBAAkB;YACxB,MAAM,EAAE,CAAC;SACV,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE;QACpB,cAAc,CAAC,sBAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;YAChC,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,KAAK;YACb,WAAW,EAAE,EAAE;SAChB,CAAC,CAAA;QAEF,cAAc,CAAC,sBAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;YAChC,IAAI,EAAE,gBAAgB;YACtB,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,KAAK;YACb,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;SACpB,CAAC,CAAA;QAEF,cAAc,CAAC,sBAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YACjC,IAAI,EAAE,iBAAiB;YACvB,MAAM,EAAE,CAAC;YACT,MAAM,EAAE,KAAK;YACb,WAAW,EAAE,EAAE;SAChB,CAAC,CAAA;QAEF,cAAc,CAAC,sBAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YACjC,IAAI,EAAE,iBAAiB;YACvB,MAAM,EAAE,EAAE;YACV,MAAM,EAAE,KAAK;YACb,WAAW,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;SACvB,CAAC,CAAA;QAEF,cAAc,CAAC,sBAAO,CAAC,QAAQ,EAAE,EAAE;YACjC,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,CAAC;SACV,CAAC,CAAA;QAEF,cAAc,CAAC,sBAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE;YACvD,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,CAAC;YACT,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;SAC9B,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAGF,uEAAuE;IACvE,uEAAuE;IACvE,yBAAyB;IACzB,QAAQ,CAAC,sCAAsC,EAAE;QAC/C,IAAI,UAAU,GAAG,sBAAO,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,CAAC,CAAC,CAAA;QAEtE,MAAM,KAAK,GAAG,CAAO,OAAiB,EAAgB,EAAE;YACtD,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAC;YACpC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;gBAC5B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;aACtB;YACD,MAAM,CAAC,GAAG,EAAE,CAAA;YACZ,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAA;YAClC,OAAO,GAAG,CAAC;QACb,CAAC,CAAA,CAAA;QAED,EAAE,CAAC,kCAAkC,EAAE;;gBACrC,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;gBAC1C,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;gBACtC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;gBACrC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;gBACvC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;gBAC1C,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;gBACrC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;YACtC,CAAC;SAAA,CAAC,CAAA;QAEF,IAAI,+BAA+B,GAAG,UAAgB,KAAa;;gBACjE,IAAI,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,KAAK,CAAC,CAAA;gBACzD,IAAI,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;gBACvE,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;gBAClC,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;gBACpD,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAC;gBACzD,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;gBACtC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;gBACrC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAA;gBACvC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;gBAC1C,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAA;gBACrC,gBAAM,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;YACtC,CAAC;SAAA,CAAA;QAED,EAAE,CAAC,iCAAiC,EAAE;YACpC,+BAA+B,CAAC,CAAC,CAAC,CAAA;QACpC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,0BAA0B,EAAE;YAC7B,+BAA+B,CAAC,CAAC,CAAC,CAAA;QACpC,CAAC,CAAC,CAAA;QAEF,EAAE,CAAC,gCAAgC,EAAE;YACnC,+BAA+B,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;YACtD,+BAA+B,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;YACtD,+BAA+B,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;QACxD,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,QAAQ,CAAC,wCAAwC,EAAE;QACjD,IAAI,aAAa,GAAG,sBAAO,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QAC1C,IAAI,mBAAmB,GAAG,sBAAO,CAAC,aAAa,EAAE,CAAA;QACjD,IAAI,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAA;QAChF,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;QACpC,mBAAmB,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QAE7D,MAAM,KAAK,GAAG,CAAC,OAAiB,EAAkB,EAAE;YAClD,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAC;YACpC,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE;gBAC5B,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;aACtB;YACD,MAAM,CAAC,GAAG,EAAE,CAAA;YACZ,OAAO,MAAM,CAAC,MAAM,CAAC,CAAA;QACvB,CAAC,CAAA;QAED,IAAI,cAAc,GAAG,UAAU,QAAe;YAC5C,gBAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;YACtC,gBAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;gBAC5B,IAAI,EAAE,SAAS;gBACf,UAAU,EAAE,CAAC;gBACb,MAAM,EAAE,EAAE;gBACV,MAAM,EAAE,CAAC,GAAG,CAAC;aACd,CAAC,CAAA;YACF,gBAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;YACxC,gBAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;gBAC5B,IAAI,EAAE,eAAe;gBACrB,MAAM,EAAE,CAAC;gBACT,MAAM,EAAE,GAAG;aACZ,CAAC,CAAA;QACJ,CAAC,CAAA;QACD,eAAe;QACf,EAAE,CAAC,iDAAiD,EAAE;;gBACpD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;gBAC1C,cAAc,CAAC,QAAQ,CAAC,CAAA;YAC1B,CAAC;SAAA,CAAC,CAAA;QAEF,IAAI,yBAAyB,GAAG,UAAgB,KAAa;;gBAC3D,IAAI,WAAW,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,KAAK,CAAC,CAAA;gBACzD,IAAI,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC,CAAA;gBACvE,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAA;gBAClC,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAA;gBACpD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC,CAAA;gBACzD,cAAc,CAAC,QAAQ,CAAC,CAAA;YAC1B,CAAC;SAAA,CAAA;QAED,QAAQ,CAAC,6CAA6C,EAAE;YACtD,EAAE,CAAC,eAAe,EAAE;gBAClB,OAAO,yBAAyB,CAAC,EAAE,CAAC,CAAA;YACtC,CAAC,CAAC,CAAA;YACF,EAAE,CAAC,cAAc,EAAE;gBACjB,OAAO,OAAO,CAAC,GAAG,CAAC;oBACjB,yBAAyB,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;oBAChD,yBAAyB,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;oBAChD,yBAAyB,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;iBACjD,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;YAEF,EAAE,CAAC,YAAY,EAAE;gBACf,OAAO,OAAO,CAAC,GAAG,CAAC;oBACjB,yBAAyB,CAAC,CAAC,CAAC;oBAC5B,yBAAyB,CAAC,CAAC,CAAC;iBAC7B,CAAC,CAAA;YACJ,CAAC,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AAEJ,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/index.js b/packages/pg-packet-stream/dist/index.js deleted file mode 100644 index 48527f2ed..000000000 --- a/packages/pg-packet-stream/dist/index.js +++ /dev/null @@ -1,264 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -const stream_1 = require("stream"); -const messages_1 = require("./messages"); -const BufferReader_1 = require("./BufferReader"); -const assert_1 = __importDefault(require("assert")); -// every message is prefixed with a single bye -const CODE_LENGTH = 1; -// every message has an int32 length which includes itself but does -// NOT include the code in the length -const LEN_LENGTH = 4; -const HEADER_LENGTH = CODE_LENGTH + LEN_LENGTH; -const emptyBuffer = Buffer.allocUnsafe(0); -class PgPacketStream extends stream_1.Transform { - constructor(opts) { - var _a, _b; - super(Object.assign(Object.assign({}, opts), { readableObjectMode: true })); - this.remainingBuffer = emptyBuffer; - this.reader = new BufferReader_1.BufferReader(); - if (((_a = opts) === null || _a === void 0 ? void 0 : _a.mode) === 'binary') { - throw new Error('Binary mode not supported yet'); - } - this.mode = ((_b = opts) === null || _b === void 0 ? void 0 : _b.mode) || 'text'; - } - _transform(buffer, encoding, callback) { - const combinedBuffer = this.remainingBuffer.byteLength ? Buffer.concat([this.remainingBuffer, buffer], this.remainingBuffer.length + buffer.length) : buffer; - let offset = 0; - while ((offset + HEADER_LENGTH) <= combinedBuffer.byteLength) { - // code is 1 byte long - it identifies the message type - const code = combinedBuffer[offset]; - // length is 1 Uint32BE - it is the length of the message EXCLUDING the code - const length = combinedBuffer.readUInt32BE(offset + CODE_LENGTH); - const fullMessageLength = CODE_LENGTH + length; - if (fullMessageLength + offset <= combinedBuffer.byteLength) { - const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer); - this.push(message); - offset += fullMessageLength; - } - else { - break; - } - } - if (offset === combinedBuffer.byteLength) { - this.remainingBuffer = emptyBuffer; - } - else { - this.remainingBuffer = combinedBuffer.slice(offset); - } - callback(null); - } - handlePacket(offset, code, length, bytes) { - switch (code) { - case 50 /* BindComplete */: - return messages_1.bindComplete; - case 49 /* ParseComplete */: - return messages_1.parseComplete; - case 51 /* CloseComplete */: - return messages_1.closeComplete; - case 110 /* NoData */: - return messages_1.noData; - case 115 /* PortalSuspended */: - return messages_1.portalSuspended; - case 99 /* CopyDone */: - return messages_1.copyDone; - case 87 /* ReplicationStart */: - return messages_1.replicationStart; - case 73 /* EmptyQuery */: - return messages_1.emptyQuery; - case 68 /* DataRow */: - return this.parseDataRowMessage(offset, length, bytes); - case 67 /* CommandComplete */: - return this.parseCommandCompleteMessage(offset, length, bytes); - case 90 /* ReadyForQuery */: - return this.parseReadyForQueryMessage(offset, length, bytes); - case 65 /* NotificationResponse */: - return this.parseNotificationMessage(offset, length, bytes); - case 82 /* AuthenticationResponse */: - return this.parseAuthenticationResponse(offset, length, bytes); - case 83 /* ParameterStatus */: - return this.parseParameterStatusMessage(offset, length, bytes); - case 75 /* BackendKeyData */: - return this.parseBackendKeyData(offset, length, bytes); - case 69 /* ErrorMessage */: - return this.parseErrorMessage(offset, length, bytes, 'error'); - case 78 /* NoticeMessage */: - return this.parseErrorMessage(offset, length, bytes, 'notice'); - case 84 /* RowDescriptionMessage */: - return this.parseRowDescriptionMessage(offset, length, bytes); - case 71 /* CopyIn */: - return this.parseCopyInMessage(offset, length, bytes); - case 72 /* CopyOut */: - return this.parseCopyOutMessage(offset, length, bytes); - case 100 /* CopyData */: - return this.parseCopyData(offset, length, bytes); - default: - assert_1.default.fail(`unknown message code: ${code.toString(16)}`); - } - } - _flush(callback) { - this._transform(Buffer.alloc(0), 'utf-i', callback); - } - parseReadyForQueryMessage(offset, length, bytes) { - this.reader.setBuffer(offset, bytes); - const status = this.reader.string(1); - return new messages_1.ReadyForQueryMessage(length, status); - } - parseCommandCompleteMessage(offset, length, bytes) { - this.reader.setBuffer(offset, bytes); - const text = this.reader.cstring(); - return new messages_1.CommandCompleteMessage(length, text); - } - parseCopyData(offset, length, bytes) { - const chunk = bytes.slice(offset, offset + (length - 4)); - return new messages_1.CopyDataMessage(length, chunk); - } - parseCopyInMessage(offset, length, bytes) { - return this.parseCopyMessage(offset, length, bytes, 'copyInResponse'); - } - parseCopyOutMessage(offset, length, bytes) { - return this.parseCopyMessage(offset, length, bytes, 'copyOutResponse'); - } - parseCopyMessage(offset, length, bytes, messageName) { - this.reader.setBuffer(offset, bytes); - const isBinary = this.reader.byte() !== 0; - const columnCount = this.reader.int16(); - const message = new messages_1.CopyResponse(length, messageName, isBinary, columnCount); - for (let i = 0; i < columnCount; i++) { - message.columnTypes[i] = this.reader.int16(); - } - return message; - } - parseNotificationMessage(offset, length, bytes) { - this.reader.setBuffer(offset, bytes); - const processId = this.reader.int32(); - const channel = this.reader.cstring(); - const payload = this.reader.cstring(); - return new messages_1.NotificationResponseMessage(length, processId, channel, payload); - } - parseRowDescriptionMessage(offset, length, bytes) { - this.reader.setBuffer(offset, bytes); - const fieldCount = this.reader.int16(); - const message = new messages_1.RowDescriptionMessage(length, fieldCount); - for (let i = 0; i < fieldCount; i++) { - message.fields[i] = this.parseField(); - } - return message; - } - parseField() { - const name = this.reader.cstring(); - const tableID = this.reader.int32(); - const columnID = this.reader.int16(); - const dataTypeID = this.reader.int32(); - const dataTypeSize = this.reader.int16(); - const dataTypeModifier = this.reader.int32(); - const mode = this.reader.int16() === 0 ? 'text' : 'binary'; - return new messages_1.Field(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, mode); - } - parseDataRowMessage(offset, length, bytes) { - this.reader.setBuffer(offset, bytes); - const fieldCount = this.reader.int16(); - const fields = new Array(fieldCount); - for (let i = 0; i < fieldCount; i++) { - const len = this.reader.int32(); - if (len === -1) { - fields[i] = null; - } - else if (this.mode === 'text') { - fields[i] = this.reader.string(len); - } - } - return new messages_1.DataRowMessage(length, fields); - } - parseParameterStatusMessage(offset, length, bytes) { - this.reader.setBuffer(offset, bytes); - const name = this.reader.cstring(); - const value = this.reader.cstring(); - return new messages_1.ParameterStatusMessage(length, name, value); - } - parseBackendKeyData(offset, length, bytes) { - this.reader.setBuffer(offset, bytes); - const processID = this.reader.int32(); - const secretKey = this.reader.int32(); - return new messages_1.BackendKeyDataMessage(length, processID, secretKey); - } - parseAuthenticationResponse(offset, length, bytes) { - this.reader.setBuffer(offset, bytes); - const code = this.reader.int32(); - // TODO(bmc): maybe better types here - const message = { - name: 'authenticationOk', - length, - }; - switch (code) { - case 0: // AuthenticationOk - break; - case 3: // AuthenticationCleartextPassword - if (message.length === 8) { - message.name = 'authenticationCleartextPassword'; - } - break; - case 5: // AuthenticationMD5Password - if (message.length === 12) { - message.name = 'authenticationMD5Password'; - message.salt = this.reader.bytes(4); - } - break; - case 10: // AuthenticationSASL - message.name = 'authenticationSASL'; - message.mechanisms = []; - let mechanism; - do { - mechanism = this.reader.cstring(); - if (mechanism) { - message.mechanisms.push(mechanism); - } - } while (mechanism); - break; - case 11: // AuthenticationSASLContinue - message.name = 'authenticationSASLContinue'; - message.data = this.reader.string(length - 4); - break; - case 12: // AuthenticationSASLFinal - message.name = 'authenticationSASLFinal'; - message.data = this.reader.string(length - 4); - break; - default: - throw new Error('Unknown authenticationOk message type ' + code); - } - return message; - } - parseErrorMessage(offset, length, bytes, name) { - this.reader.setBuffer(offset, bytes); - var fields = {}; - var fieldType = this.reader.string(1); - while (fieldType !== '\0') { - fields[fieldType] = this.reader.cstring(); - fieldType = this.reader.string(1); - } - // the msg is an Error instance - var message = new messages_1.DatabaseError(fields.M, length, name); - message.severity = fields.S; - message.code = fields.C; - message.detail = fields.D; - message.hint = fields.H; - message.position = fields.P; - message.internalPosition = fields.p; - message.internalQuery = fields.q; - message.where = fields.W; - message.schema = fields.s; - message.table = fields.t; - message.column = fields.c; - message.dataType = fields.d; - message.constraint = fields.n; - message.file = fields.F; - message.line = fields.L; - message.routine = fields.R; - return message; - } -} -exports.PgPacketStream = PgPacketStream; -//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/index.js.map b/packages/pg-packet-stream/dist/index.js.map deleted file mode 100644 index 878db40a3..000000000 --- a/packages/pg-packet-stream/dist/index.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;AAAA,mCAAwE;AACxE,yCAAqX;AACrX,iDAA8C;AAC9C,oDAA2B;AAE3B,8CAA8C;AAC9C,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,mEAAmE;AACnE,qCAAqC;AACrC,MAAM,UAAU,GAAG,CAAC,CAAC;AAErB,MAAM,aAAa,GAAG,WAAW,GAAG,UAAU,CAAC;AAO/C,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AA8B1C,MAAa,cAAe,SAAQ,kBAAS;IAK3C,YAAY,IAAoB;;QAC9B,KAAK,iCACA,IAAI,KACP,kBAAkB,EAAE,IAAI,IACxB,CAAA;QARI,oBAAe,GAAW,WAAW,CAAC;QACtC,WAAM,GAAG,IAAI,2BAAY,EAAE,CAAC;QAQlC,IAAI,OAAA,IAAI,0CAAE,IAAI,MAAK,QAAQ,EAAE;YAC3B,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAA;SACjD;QACD,IAAI,CAAC,IAAI,GAAG,OAAA,IAAI,0CAAE,IAAI,KAAI,MAAM,CAAC;IACnC,CAAC;IAEM,UAAU,CAAC,MAAc,EAAE,QAAgB,EAAE,QAA2B;QAC7E,MAAM,cAAc,GAAW,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QACrK,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,OAAO,CAAC,MAAM,GAAG,aAAa,CAAC,IAAI,cAAc,CAAC,UAAU,EAAE;YAC5D,uDAAuD;YACvD,MAAM,IAAI,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YAEpC,4EAA4E;YAC5E,MAAM,MAAM,GAAG,cAAc,CAAC,YAAY,CAAC,MAAM,GAAG,WAAW,CAAC,CAAC;YAEjE,MAAM,iBAAiB,GAAG,WAAW,GAAG,MAAM,CAAC;YAE/C,IAAI,iBAAiB,GAAG,MAAM,IAAI,cAAc,CAAC,UAAU,EAAE;gBAC3D,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;gBACxF,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBAClB,MAAM,IAAI,iBAAiB,CAAC;aAC7B;iBAAM;gBACL,MAAM;aACP;SACF;QAED,IAAI,MAAM,KAAK,cAAc,CAAC,UAAU,EAAE;YACxC,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC;SACpC;aAAM;YACL,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;SACpD;QAED,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC;IAEO,YAAY,CAAC,MAAc,EAAE,IAAY,EAAE,MAAc,EAAE,KAAa;QAC9E,QAAQ,IAAI,EAAE;YACZ;gBACE,OAAO,uBAAY,CAAC;YACtB;gBACE,OAAO,wBAAa,CAAC;YACvB;gBACE,OAAO,wBAAa,CAAC;YACvB;gBACE,OAAO,iBAAM,CAAC;YAChB;gBACE,OAAO,0BAAe,CAAC;YACzB;gBACE,OAAO,mBAAQ,CAAC;YAClB;gBACE,OAAO,2BAAgB,CAAC;YAC1B;gBACE,OAAO,qBAAU,CAAC;YACpB;gBACE,OAAO,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACzD;gBACE,OAAO,IAAI,CAAC,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACjE;gBACE,OAAO,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YAC/D;gBACE,OAAO,IAAI,CAAC,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YAC9D;gBACE,OAAO,IAAI,CAAC,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACjE;gBACE,OAAO,IAAI,CAAC,2BAA2B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACjE;gBACE,OAAO,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACzD;gBACE,OAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;YAChE;gBACE,OAAO,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;YACjE;gBACE,OAAO,IAAI,CAAC,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YAChE;gBACE,OAAO,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACxD;gBACE,OAAO,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACzD;gBACE,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACnD;gBACE,gBAAM,CAAC,IAAI,CAAC,yBAAyB,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;SAC5D;IACH,CAAC;IAEM,MAAM,CAAC,QAA2B;QACvC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;IACrD,CAAC;IAEO,yBAAyB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QAC7E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACrC,OAAO,IAAI,+BAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjD,CAAC;IAEO,2BAA2B,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QAC/E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACnC,OAAO,IAAI,iCAAsB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAClD,CAAC;IAEO,aAAa,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QACjE,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACzD,OAAO,IAAI,0BAAe,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAEO,kBAAkB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QACtE,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,CAAC,CAAA;IACvE,CAAC;IAEO,mBAAmB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QACvE,OAAO,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,CAAC,CAAA;IACxE,CAAC;IAEO,gBAAgB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa,EAAE,WAAmB;QACzF,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACvC,MAAM,OAAO,GAAG,IAAI,uBAAY,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;QAC7E,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,EAAE,EAAE;YACpC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;SAC9C;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,wBAAwB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QAC5E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACtC,OAAO,IAAI,sCAA2B,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC9E,CAAC;IAEO,0BAA0B,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QAC9E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACtC,MAAM,OAAO,GAAG,IAAI,gCAAqB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC9D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE;YACnC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,CAAA;SACtC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,UAAU;QAChB,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACnC,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACpC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACtC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACxC,MAAM,gBAAgB,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC3D,OAAO,IAAI,gBAAK,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,IAAI,CAAC,CAAA;IAC7F,CAAC;IAEO,mBAAmB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QACvE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACvC,MAAM,MAAM,GAAU,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;QAC5C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,EAAE,EAAE;YACnC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAChC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE;gBACd,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAA;aACjB;iBAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE;gBAC/B,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;aACpC;SACF;QACD,OAAO,IAAI,yBAAc,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC;IAEO,2BAA2B,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QAC/E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;QACnC,OAAO,IAAI,iCAAsB,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,CAAA;IACxD,CAAC;IAEO,mBAAmB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QACvE,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACrC,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QACrC,OAAO,IAAI,gCAAqB,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,CAAA;IAChE,CAAC;IAGM,2BAA2B,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa;QAC9E,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QAChC,qCAAqC;QACrC,MAAM,OAAO,GAAQ;YACnB,IAAI,EAAE,kBAAkB;YACxB,MAAM;SACP,CAAC;QAEF,QAAQ,IAAI,EAAE;YACZ,KAAK,CAAC,EAAE,mBAAmB;gBACzB,MAAM;YACR,KAAK,CAAC,EAAE,kCAAkC;gBACxC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;oBACxB,OAAO,CAAC,IAAI,GAAG,iCAAiC,CAAA;iBACjD;gBACD,MAAK;YACP,KAAK,CAAC,EAAE,4BAA4B;gBAClC,IAAI,OAAO,CAAC,MAAM,KAAK,EAAE,EAAE;oBACzB,OAAO,CAAC,IAAI,GAAG,2BAA2B,CAAA;oBAC1C,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;iBACrC;gBACD,MAAK;YACP,KAAK,EAAE,EAAE,qBAAqB;gBAC5B,OAAO,CAAC,IAAI,GAAG,oBAAoB,CAAA;gBACnC,OAAO,CAAC,UAAU,GAAG,EAAE,CAAA;gBACvB,IAAI,SAAiB,CAAC;gBACtB,GAAG;oBACD,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;oBAEjC,IAAI,SAAS,EAAE;wBACb,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;qBACnC;iBACF,QAAQ,SAAS,EAAC;gBACnB,MAAM;YACR,KAAK,EAAE,EAAE,6BAA6B;gBACpC,OAAO,CAAC,IAAI,GAAG,4BAA4B,CAAA;gBAC3C,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;gBAC7C,MAAM;YACR,KAAK,EAAE,EAAE,0BAA0B;gBACjC,OAAO,CAAC,IAAI,GAAG,yBAAyB,CAAA;gBACxC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;gBAC7C,MAAM;YACR;gBACE,MAAM,IAAI,KAAK,CAAC,wCAAwC,GAAG,IAAI,CAAC,CAAA;SACnE;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAEO,iBAAiB,CAAC,MAAc,EAAE,MAAc,EAAE,KAAa,EAAE,IAAY;QACnF,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACrC,IAAI,MAAM,GAA2B,EAAE,CAAA;QACvC,IAAI,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACrC,OAAO,SAAS,KAAK,IAAI,EAAE;YACzB,MAAM,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAA;YACzC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;SAClC;QAED,+BAA+B;QAC/B,IAAI,OAAO,GAAG,IAAI,wBAAa,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,CAAA;QAEvD,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAA;QAC3B,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAA;QACvB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAA;QACzB,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAA;QACvB,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAA;QAC3B,OAAO,CAAC,gBAAgB,GAAG,MAAM,CAAC,CAAC,CAAA;QACnC,OAAO,CAAC,aAAa,GAAG,MAAM,CAAC,CAAC,CAAA;QAChC,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAA;QACxB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAA;QACzB,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,CAAC,CAAA;QACxB,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAA;QACzB,OAAO,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAA;QAC3B,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC,CAAA;QAC7B,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAA;QACvB,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC,CAAA;QACvB,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC,CAAA;QAC1B,OAAO,OAAO,CAAC;IACjB,CAAC;CACF;AAjRD,wCAiRC"} \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/index.test.js b/packages/pg-packet-stream/dist/index.test.js deleted file mode 100644 index 1e4c8f357..000000000 --- a/packages/pg-packet-stream/dist/index.test.js +++ /dev/null @@ -1,109 +0,0 @@ -"use strict"; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -require("mocha"); -const _1 = require("./"); -const chai_1 = require("chai"); -const chunky_1 = __importDefault(require("chunky")); -const consume = (stream, count) => __awaiter(void 0, void 0, void 0, function* () { - const result = []; - return new Promise((resolve) => { - const read = () => { - stream.once('readable', () => { - let packet; - while (packet = stream.read()) { - result.push(packet); - } - if (result.length === count) { - resolve(result); - } - else { - read(); - } - }); - }; - read(); - }); -}); -const emptyMessage = Buffer.from([0x0a, 0x00, 0x00, 0x00, 0x04]); -const oneByteMessage = Buffer.from([0x0b, 0x00, 0x00, 0x00, 0x05, 0x0a]); -const bigMessage = Buffer.from([0x0f, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e0, 0x0f]); -describe.skip('PgPacketStream', () => { - it('should chunk a perfect input packet', () => __awaiter(void 0, void 0, void 0, function* () { - const stream = new _1.PgPacketStream(); - stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x04])); - stream.end(); - const buffers = yield consume(stream, 1); - chai_1.expect(buffers).to.have.length(1); - chai_1.expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x04])); - })); - it('should read 2 chunks into perfect input packet', () => __awaiter(void 0, void 0, void 0, function* () { - const stream = new _1.PgPacketStream(); - stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x08])); - stream.write(Buffer.from([0x1, 0x2, 0x3, 0x4])); - stream.end(); - const buffers = yield consume(stream, 1); - chai_1.expect(buffers).to.have.length(1); - chai_1.expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x08, 0x1, 0x2, 0x3, 0x4])); - })); - it('should read a bunch of big messages', () => __awaiter(void 0, void 0, void 0, function* () { - const stream = new _1.PgPacketStream(); - let totalBuffer = Buffer.allocUnsafe(0); - const num = 2; - for (let i = 0; i < 2; i++) { - totalBuffer = Buffer.concat([totalBuffer, bigMessage, bigMessage]); - } - const chunks = chunky_1.default(totalBuffer); - for (const chunk of chunks) { - stream.write(chunk); - } - stream.end(); - const messages = yield consume(stream, num * 2); - chai_1.expect(messages.map(x => x.code)).to.eql(new Array(num * 2).fill(0x0f)); - })); - it('should read multiple messages in a single chunk', () => __awaiter(void 0, void 0, void 0, function* () { - const stream = new _1.PgPacketStream(); - stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x04])); - stream.end(); - const buffers = yield consume(stream, 2); - chai_1.expect(buffers).to.have.length(2); - chai_1.expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x04])); - chai_1.expect(buffers[1].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x04])); - })); - it('should read multiple chunks into multiple packets', () => __awaiter(void 0, void 0, void 0, function* () { - const stream = new _1.PgPacketStream(); - stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x05, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x05, 0x0b])); - stream.write(Buffer.from([0x01, 0x00, 0x00])); - stream.write(Buffer.from([0x00, 0x06, 0x0c, 0x0d, 0x03, 0x00, 0x00, 0x00, 0x04])); - stream.end(); - const buffers = yield consume(stream, 4); - chai_1.expect(buffers).to.have.length(4); - chai_1.expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x05, 0x0a])); - chai_1.expect(buffers[1].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x05, 0x0b])); - chai_1.expect(buffers[2].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x0d])); - chai_1.expect(buffers[3].packet).to.deep.equal(Buffer.from([0x3, 0x00, 0x00, 0x00, 0x04])); - })); - it('reads packet that spans multiple chunks', () => __awaiter(void 0, void 0, void 0, function* () { - const stream = new _1.PgPacketStream(); - stream.write(Buffer.from([0x0d, 0x00, 0x00, 0x00])); - stream.write(Buffer.from([0x09])); // length - stream.write(Buffer.from([0x0a, 0x0b, 0x0c, 0x0d])); - stream.write(Buffer.from([0x0a, 0x0b, 0x0c, 0x0d])); - stream.write(Buffer.from([0x0a, 0x0b, 0x0c, 0x0d])); - stream.end(); - const buffers = yield consume(stream, 1); - chai_1.expect(buffers).to.have.length(1); - })); -}); -//# sourceMappingURL=index.test.js.map \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/index.test.js.map b/packages/pg-packet-stream/dist/index.test.js.map deleted file mode 100644 index 6697efee1..000000000 --- a/packages/pg-packet-stream/dist/index.test.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":";;;;;;;;;;;;;;AAAA,iBAAe;AACf,yBAA2C;AAC3C,+BAA6B;AAC7B,oDAA2B;AAE3B,MAAM,OAAO,GAAG,CAAO,MAAsB,EAAE,KAAa,EAAqB,EAAE;IACjF,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,IAAI,GAAG,GAAG,EAAE;YAChB,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE;gBAC3B,IAAI,MAAM,CAAC;gBACX,OAAO,MAAM,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE;oBAC7B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;iBACpB;gBACD,IAAI,MAAM,CAAC,MAAM,KAAK,KAAK,EAAE;oBAC3B,OAAO,CAAC,MAAM,CAAC,CAAC;iBACjB;qBAAM;oBACL,IAAI,EAAE,CAAA;iBACP;YAEH,CAAC,CAAC,CAAA;QACJ,CAAC,CAAA;QACD,IAAI,EAAE,CAAA;IACR,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA,CAAA;AAED,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;AAChE,MAAM,cAAc,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;AACxE,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAA;AAE/J,QAAQ,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE;IACnC,EAAE,CAAC,qCAAqC,EAAE,GAAS,EAAE;QACnD,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACzD,MAAM,CAAC,GAAG,EAAE,CAAA;QACZ,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACxC,aAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACjC,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;IACrF,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAS,EAAE;QAC9D,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACzD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;QAC/C,MAAM,CAAC,GAAG,EAAE,CAAA;QACZ,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACxC,aAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACjC,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAA;IACzG,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAS,EAAE;QACnD,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAC;QACpC,IAAI,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,CAAC,CAAC;QACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE;YAC1B,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC,CAAA;SACnE;QACD,MAAM,MAAM,GAAG,gBAAM,CAAC,WAAW,CAAC,CAAA;QAClC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE;YAC1B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;SACpB;QACD,MAAM,CAAC,GAAG,EAAE,CAAA;QACZ,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC,CAAA;QAC/C,aAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;IACzE,CAAC,CAAA,CAAC,CAAA;IAEF,EAAE,CAAC,iDAAiD,EAAE,GAAS,EAAE;QAC/D,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACvF,MAAM,CAAC,GAAG,EAAE,CAAA;QACZ,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACxC,aAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACjC,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACnF,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;IACrF,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,GAAS,EAAE;QACjE,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACnG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACjF,MAAM,CAAC,GAAG,EAAE,CAAA;QACZ,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACxC,aAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;QACjC,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACzF,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACzF,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QAC/F,aAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;IACrF,CAAC,CAAA,CAAC,CAAC;IAEH,EAAE,CAAC,yCAAyC,EAAE,GAAS,EAAE;QACvD,MAAM,MAAM,GAAG,IAAI,iBAAc,EAAE,CAAA;QACnC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACnD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA,CAAC,SAAS;QAC3C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACnD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACnD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QACnD,MAAM,CAAC,GAAG,EAAE,CAAA;QACZ,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;QACxC,aAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;IACnC,CAAC,CAAA,CAAC,CAAA;AACJ,CAAC,CAAC,CAAC"} \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/messages.js b/packages/pg-packet-stream/dist/messages.js deleted file mode 100644 index 9515af05d..000000000 --- a/packages/pg-packet-stream/dist/messages.js +++ /dev/null @@ -1,134 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -exports.parseComplete = { - name: 'parseComplete', - length: 5, -}; -exports.bindComplete = { - name: 'bindComplete', - length: 5, -}; -exports.closeComplete = { - name: 'closeComplete', - length: 5, -}; -exports.noData = { - name: 'noData', - length: 5 -}; -exports.portalSuspended = { - name: 'portalSuspended', - length: 5, -}; -exports.replicationStart = { - name: 'replicationStart', - length: 4, -}; -exports.emptyQuery = { - name: 'emptyQuery', - length: 4, -}; -exports.copyDone = { - name: 'copyDone', - length: 4, -}; -class DatabaseError extends Error { - constructor(message, length, name) { - super(message); - this.length = length; - this.name = name; - } -} -exports.DatabaseError = DatabaseError; -class CopyDataMessage { - constructor(length, chunk) { - this.length = length; - this.chunk = chunk; - this.name = 'copyData'; - } -} -exports.CopyDataMessage = CopyDataMessage; -class CopyResponse { - constructor(length, name, binary, columnCount) { - this.length = length; - this.name = name; - this.binary = binary; - this.columnTypes = new Array(columnCount); - } -} -exports.CopyResponse = CopyResponse; -class Field { - constructor(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, format) { - this.name = name; - this.tableID = tableID; - this.columnID = columnID; - this.dataTypeID = dataTypeID; - this.dataTypeSize = dataTypeSize; - this.dataTypeModifier = dataTypeModifier; - this.format = format; - } -} -exports.Field = Field; -class RowDescriptionMessage { - constructor(length, fieldCount) { - this.length = length; - this.fieldCount = fieldCount; - this.name = 'rowDescription'; - this.fields = new Array(this.fieldCount); - } -} -exports.RowDescriptionMessage = RowDescriptionMessage; -class ParameterStatusMessage { - constructor(length, parameterName, parameterValue) { - this.length = length; - this.parameterName = parameterName; - this.parameterValue = parameterValue; - this.name = 'parameterStatus'; - } -} -exports.ParameterStatusMessage = ParameterStatusMessage; -class BackendKeyDataMessage { - constructor(length, processID, secretKey) { - this.length = length; - this.processID = processID; - this.secretKey = secretKey; - this.name = 'backendKeyData'; - } -} -exports.BackendKeyDataMessage = BackendKeyDataMessage; -class NotificationResponseMessage { - constructor(length, processId, channel, payload) { - this.length = length; - this.processId = processId; - this.channel = channel; - this.payload = payload; - this.name = 'notification'; - } -} -exports.NotificationResponseMessage = NotificationResponseMessage; -class ReadyForQueryMessage { - constructor(length, status) { - this.length = length; - this.status = status; - this.name = 'readyForQuery'; - } -} -exports.ReadyForQueryMessage = ReadyForQueryMessage; -class CommandCompleteMessage { - constructor(length, text) { - this.length = length; - this.text = text; - this.name = 'commandComplete'; - } -} -exports.CommandCompleteMessage = CommandCompleteMessage; -class DataRowMessage { - constructor(length, fields) { - this.length = length; - this.fields = fields; - this.name = 'dataRow'; - this.fieldCount = fields.length; - } -} -exports.DataRowMessage = DataRowMessage; -//# sourceMappingURL=messages.js.map \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/messages.js.map b/packages/pg-packet-stream/dist/messages.js.map deleted file mode 100644 index 1fe1ba7aa..000000000 --- a/packages/pg-packet-stream/dist/messages.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":";;AAOa,QAAA,aAAa,GAAmB;IAC3C,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,CAAC;CACV,CAAC;AAEW,QAAA,YAAY,GAAmB;IAC1C,IAAI,EAAE,cAAc;IACpB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,aAAa,GAAmB;IAC3C,IAAI,EAAE,eAAe;IACrB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,MAAM,GAAmB;IACpC,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,eAAe,GAAmB;IAC7C,IAAI,EAAE,iBAAiB;IACvB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,gBAAgB,GAAmB;IAC9C,IAAI,EAAE,kBAAkB;IACxB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,UAAU,GAAmB;IACxC,IAAI,EAAE,YAAY;IAClB,MAAM,EAAE,CAAC;CACV,CAAA;AAEY,QAAA,QAAQ,GAAmB;IACtC,IAAI,EAAE,UAAU;IAChB,MAAM,EAAE,CAAC;CACV,CAAA;AAED,MAAa,aAAc,SAAQ,KAAK;IAiBtC,YAAY,OAAe,EAAkB,MAAc,EAAkB,IAAY;QACvF,KAAK,CAAC,OAAO,CAAC,CAAA;QAD6B,WAAM,GAAN,MAAM,CAAQ;QAAkB,SAAI,GAAJ,IAAI,CAAQ;IAEzF,CAAC;CACF;AApBD,sCAoBC;AAED,MAAa,eAAe;IAE1B,YAA4B,MAAc,EAAkB,KAAa;QAA7C,WAAM,GAAN,MAAM,CAAQ;QAAkB,UAAK,GAAL,KAAK,CAAQ;QADzD,SAAI,GAAG,UAAU,CAAC;IAGlC,CAAC;CACF;AALD,0CAKC;AAED,MAAa,YAAY;IAEvB,YAA4B,MAAc,EAAkB,IAAY,EAAkB,MAAe,EAAE,WAAmB;QAAlG,WAAM,GAAN,MAAM,CAAQ;QAAkB,SAAI,GAAJ,IAAI,CAAQ;QAAkB,WAAM,GAAN,MAAM,CAAS;QACvG,IAAI,CAAC,WAAW,GAAG,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;IAC5C,CAAC;CACF;AALD,oCAKC;AAED,MAAa,KAAK;IAChB,YAA4B,IAAY,EAAkB,OAAe,EAAkB,QAAgB,EAAkB,UAAkB,EAAkB,YAAoB,EAAkB,gBAAwB,EAAkB,MAAY;QAAjO,SAAI,GAAJ,IAAI,CAAQ;QAAkB,YAAO,GAAP,OAAO,CAAQ;QAAkB,aAAQ,GAAR,QAAQ,CAAQ;QAAkB,eAAU,GAAV,UAAU,CAAQ;QAAkB,iBAAY,GAAZ,YAAY,CAAQ;QAAkB,qBAAgB,GAAhB,gBAAgB,CAAQ;QAAkB,WAAM,GAAN,MAAM,CAAM;IAC7P,CAAC;CACF;AAHD,sBAGC;AAED,MAAa,qBAAqB;IAGhC,YAA4B,MAAc,EAAkB,UAAkB;QAAlD,WAAM,GAAN,MAAM,CAAQ;QAAkB,eAAU,GAAV,UAAU,CAAQ;QAF9D,SAAI,GAAW,gBAAgB,CAAC;QAG9C,IAAI,CAAC,MAAM,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAC1C,CAAC;CACF;AAND,sDAMC;AAED,MAAa,sBAAsB;IAEjC,YAA4B,MAAc,EAAkB,aAAqB,EAAkB,cAAsB;QAA7F,WAAM,GAAN,MAAM,CAAQ;QAAkB,kBAAa,GAAb,aAAa,CAAQ;QAAkB,mBAAc,GAAd,cAAc,CAAQ;QADzG,SAAI,GAAW,iBAAiB,CAAC;IAGjD,CAAC;CACF;AALD,wDAKC;AAED,MAAa,qBAAqB;IAEhC,YAA4B,MAAc,EAAkB,SAAiB,EAAkB,SAAiB;QAApF,WAAM,GAAN,MAAM,CAAQ;QAAkB,cAAS,GAAT,SAAS,CAAQ;QAAkB,cAAS,GAAT,SAAS,CAAQ;QADhG,SAAI,GAAW,gBAAgB,CAAC;IAEhD,CAAC;CACF;AAJD,sDAIC;AAED,MAAa,2BAA2B;IAEtC,YAA4B,MAAc,EAAkB,SAAiB,EAAkB,OAAe,EAAkB,OAAe;QAAnH,WAAM,GAAN,MAAM,CAAQ;QAAkB,cAAS,GAAT,SAAS,CAAQ;QAAkB,YAAO,GAAP,OAAO,CAAQ;QAAkB,YAAO,GAAP,OAAO,CAAQ;QAD/H,SAAI,GAAW,cAAc,CAAC;IAE9C,CAAC;CACF;AAJD,kEAIC;AAED,MAAa,oBAAoB;IAE/B,YAA4B,MAAc,EAAkB,MAAc;QAA9C,WAAM,GAAN,MAAM,CAAQ;QAAkB,WAAM,GAAN,MAAM,CAAQ;QAD1D,SAAI,GAAW,eAAe,CAAC;IAE/C,CAAC;CACF;AAJD,oDAIC;AAED,MAAa,sBAAsB;IAEjC,YAA4B,MAAc,EAAkB,IAAY;QAA5C,WAAM,GAAN,MAAM,CAAQ;QAAkB,SAAI,GAAJ,IAAI,CAAQ;QADxD,SAAI,GAAW,iBAAiB,CAAA;IAEhD,CAAC;CACF;AAJD,wDAIC;AAED,MAAa,cAAc;IAGzB,YAAmB,MAAc,EAAS,MAAa;QAApC,WAAM,GAAN,MAAM,CAAQ;QAAS,WAAM,GAAN,MAAM,CAAO;QADvC,SAAI,GAAW,SAAS,CAAA;QAEtC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;IAClC,CAAC;CACF;AAND,wCAMC"} \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/testing/buffer-list.js b/packages/pg-packet-stream/dist/testing/buffer-list.js deleted file mode 100644 index 9a7494f6c..000000000 --- a/packages/pg-packet-stream/dist/testing/buffer-list.js +++ /dev/null @@ -1,73 +0,0 @@ -"use strict"; -Object.defineProperty(exports, "__esModule", { value: true }); -class BufferList { - constructor(buffers = []) { - this.buffers = buffers; - } - add(buffer, front) { - this.buffers[front ? 'unshift' : 'push'](buffer); - return this; - } - addInt16(val, front) { - return this.add(Buffer.from([(val >>> 8), (val >>> 0)]), front); - } - getByteLength(initial) { - return this.buffers.reduce(function (previous, current) { - return previous + current.length; - }, initial || 0); - } - addInt32(val, first) { - return this.add(Buffer.from([ - (val >>> 24 & 0xFF), - (val >>> 16 & 0xFF), - (val >>> 8 & 0xFF), - (val >>> 0 & 0xFF) - ]), first); - } - addCString(val, front) { - var len = Buffer.byteLength(val); - var buffer = Buffer.alloc(len + 1); - buffer.write(val); - buffer[len] = 0; - return this.add(buffer, front); - } - addString(val, front) { - var len = Buffer.byteLength(val); - var buffer = Buffer.alloc(len); - buffer.write(val); - return this.add(buffer, front); - } - addChar(char, first) { - return this.add(Buffer.from(char, 'utf8'), first); - } - addByte(byte) { - return this.add(Buffer.from([byte])); - } - join(appendLength, char) { - var length = this.getByteLength(); - if (appendLength) { - this.addInt32(length + 4, true); - return this.join(false, char); - } - if (char) { - this.addChar(char, true); - length++; - } - var result = Buffer.alloc(length); - var index = 0; - this.buffers.forEach(function (buffer) { - buffer.copy(result, index, 0); - index += buffer.length; - }); - return result; - } - static concat() { - var total = new BufferList(); - for (var i = 0; i < arguments.length; i++) { - total.add(arguments[i]); - } - return total.join(); - } -} -exports.default = BufferList; -//# sourceMappingURL=buffer-list.js.map \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/testing/buffer-list.js.map b/packages/pg-packet-stream/dist/testing/buffer-list.js.map deleted file mode 100644 index c10853902..000000000 --- a/packages/pg-packet-stream/dist/testing/buffer-list.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"buffer-list.js","sourceRoot":"","sources":["../../src/testing/buffer-list.ts"],"names":[],"mappings":";;AAAA,MAAqB,UAAU;IAC7B,YAAmB,UAAoB,EAAE;QAAtB,YAAO,GAAP,OAAO,CAAe;IAEzC,CAAC;IAEM,GAAG,CAAC,MAAc,EAAE,KAAe;QACxC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAA;QAChD,OAAO,IAAI,CAAA;IACb,CAAC;IAEM,QAAQ,CAAC,GAAW,EAAE,KAAe;QAC1C,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAA;IACjE,CAAC;IAEM,aAAa,CAAC,OAAgB;QACnC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,QAAQ,EAAE,OAAO;YACpD,OAAO,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAA;QAClC,CAAC,EAAE,OAAO,IAAI,CAAC,CAAC,CAAA;IAClB,CAAC;IAEM,QAAQ,CAAC,GAAW,EAAE,KAAe;QAC1C,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;YAC1B,CAAC,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;YACnB,CAAC,GAAG,KAAK,EAAE,GAAG,IAAI,CAAC;YACnB,CAAC,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC;YAClB,CAAC,GAAG,KAAK,CAAC,GAAG,IAAI,CAAC;SACnB,CAAC,EAAE,KAAK,CAAC,CAAA;IACZ,CAAC;IAEM,UAAU,CAAC,GAAW,EAAE,KAAe;QAC5C,IAAI,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;QAChC,IAAI,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;QAClC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACjB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QACf,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IAChC,CAAC;IAEM,SAAS,CAAC,GAAW,EAAE,KAAe;QAC3C,IAAI,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;QAChC,IAAI,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QAC9B,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;QACjB,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;IAChC,CAAC;IAEM,OAAO,CAAC,IAAY,EAAE,KAAe;QAC1C,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,CAAA;IACnD,CAAC;IAEM,OAAO,CAAC,IAAY;QACzB,OAAO,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACtC,CAAC;IAEM,IAAI,CAAC,YAAsB,EAAE,IAAa;QAC/C,IAAI,MAAM,GAAG,IAAI,CAAC,aAAa,EAAE,CAAA;QACjC,IAAI,YAAY,EAAE;YAChB,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,CAAA;YAC/B,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAA;SAC9B;QACD,IAAI,IAAI,EAAE;YACR,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;YACxB,MAAM,EAAE,CAAA;SACT;QACD,IAAI,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QACjC,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,MAAM;YACnC,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;YAC7B,KAAK,IAAI,MAAM,CAAC,MAAM,CAAA;QACxB,CAAC,CAAC,CAAA;QACF,OAAO,MAAM,CAAA;IACf,CAAC;IAEM,MAAM,CAAC,MAAM;QAClB,IAAI,KAAK,GAAG,IAAI,UAAU,EAAE,CAAA;QAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACzC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAA;SACxB;QACD,OAAO,KAAK,CAAC,IAAI,EAAE,CAAA;IACrB,CAAC;CACF;AA9ED,6BA8EC"} \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/testing/test-buffers.js b/packages/pg-packet-stream/dist/testing/test-buffers.js deleted file mode 100644 index 4f174075d..000000000 --- a/packages/pg-packet-stream/dist/testing/test-buffers.js +++ /dev/null @@ -1,164 +0,0 @@ -"use strict"; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; -Object.defineProperty(exports, "__esModule", { value: true }); -// http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html -const buffer_list_1 = __importDefault(require("./buffer-list")); -const buffers = { - readyForQuery: function () { - return new buffer_list_1.default() - .add(Buffer.from('I')) - .join(true, 'Z'); - }, - authenticationOk: function () { - return new buffer_list_1.default() - .addInt32(0) - .join(true, 'R'); - }, - authenticationCleartextPassword: function () { - return new buffer_list_1.default() - .addInt32(3) - .join(true, 'R'); - }, - authenticationMD5Password: function () { - return new buffer_list_1.default() - .addInt32(5) - .add(Buffer.from([1, 2, 3, 4])) - .join(true, 'R'); - }, - authenticationSASL: function () { - return new buffer_list_1.default() - .addInt32(10) - .addCString('SCRAM-SHA-256') - .addCString('') - .join(true, 'R'); - }, - authenticationSASLContinue: function () { - return new buffer_list_1.default() - .addInt32(11) - .addString('data') - .join(true, 'R'); - }, - authenticationSASLFinal: function () { - return new buffer_list_1.default() - .addInt32(12) - .addString('data') - .join(true, 'R'); - }, - parameterStatus: function (name, value) { - return new buffer_list_1.default() - .addCString(name) - .addCString(value) - .join(true, 'S'); - }, - backendKeyData: function (processID, secretKey) { - return new buffer_list_1.default() - .addInt32(processID) - .addInt32(secretKey) - .join(true, 'K'); - }, - commandComplete: function (string) { - return new buffer_list_1.default() - .addCString(string) - .join(true, 'C'); - }, - rowDescription: function (fields) { - fields = fields || []; - var buf = new buffer_list_1.default(); - buf.addInt16(fields.length); - fields.forEach(function (field) { - buf.addCString(field.name) - .addInt32(field.tableID || 0) - .addInt16(field.attributeNumber || 0) - .addInt32(field.dataTypeID || 0) - .addInt16(field.dataTypeSize || 0) - .addInt32(field.typeModifier || 0) - .addInt16(field.formatCode || 0); - }); - return buf.join(true, 'T'); - }, - dataRow: function (columns) { - columns = columns || []; - var buf = new buffer_list_1.default(); - buf.addInt16(columns.length); - columns.forEach(function (col) { - if (col == null) { - buf.addInt32(-1); - } - else { - var strBuf = Buffer.from(col, 'utf8'); - buf.addInt32(strBuf.length); - buf.add(strBuf); - } - }); - return buf.join(true, 'D'); - }, - error: function (fields) { - return buffers.errorOrNotice(fields).join(true, 'E'); - }, - notice: function (fields) { - return buffers.errorOrNotice(fields).join(true, 'N'); - }, - errorOrNotice: function (fields) { - fields = fields || []; - var buf = new buffer_list_1.default(); - fields.forEach(function (field) { - buf.addChar(field.type); - buf.addCString(field.value); - }); - return buf.add(Buffer.from([0])); // terminator - }, - parseComplete: function () { - return new buffer_list_1.default().join(true, '1'); - }, - bindComplete: function () { - return new buffer_list_1.default().join(true, '2'); - }, - notification: function (id, channel, payload) { - return new buffer_list_1.default() - .addInt32(id) - .addCString(channel) - .addCString(payload) - .join(true, 'A'); - }, - emptyQuery: function () { - return new buffer_list_1.default().join(true, 'I'); - }, - portalSuspended: function () { - return new buffer_list_1.default().join(true, 's'); - }, - closeComplete: function () { - return new buffer_list_1.default().join(true, '3'); - }, - copyIn: function (cols) { - const list = new buffer_list_1.default() - // text mode - .addByte(0) - // column count - .addInt16(cols); - for (let i = 0; i < cols; i++) { - list.addInt16(i); - } - return list.join(true, 'G'); - }, - copyOut: function (cols) { - const list = new buffer_list_1.default() - // text mode - .addByte(0) - // column count - .addInt16(cols); - for (let i = 0; i < cols; i++) { - list.addInt16(i); - } - return list.join(true, 'H'); - }, - copyData: function (bytes) { - return new buffer_list_1.default().add(bytes).join(true, 'd'); - }, - copyDone: function () { - return new buffer_list_1.default().join(true, 'c'); - } -}; -exports.default = buffers; -//# sourceMappingURL=test-buffers.js.map \ No newline at end of file diff --git a/packages/pg-packet-stream/dist/testing/test-buffers.js.map b/packages/pg-packet-stream/dist/testing/test-buffers.js.map deleted file mode 100644 index e0aa10721..000000000 --- a/packages/pg-packet-stream/dist/testing/test-buffers.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"test-buffers.js","sourceRoot":"","sources":["../../src/testing/test-buffers.ts"],"names":[],"mappings":";;;;;AAAA,gFAAgF;AAChF,gEAAsC;AAEtC,MAAM,OAAO,GAAG;IACd,aAAa,EAAE;QACb,OAAO,IAAI,qBAAU,EAAE;aACpB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;aACrB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,gBAAgB,EAAE;QAChB,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,CAAC,CAAC;aACX,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,+BAA+B,EAAE;QAC/B,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,CAAC,CAAC;aACX,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,yBAAyB,EAAE;QACzB,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,CAAC,CAAC;aACX,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;aAC9B,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,kBAAkB,EAAE;QAClB,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,EAAE,CAAC;aACZ,UAAU,CAAC,eAAe,CAAC;aAC3B,UAAU,CAAC,EAAE,CAAC;aACd,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,0BAA0B,EAAE;QAC1B,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,EAAE,CAAC;aACZ,SAAS,CAAC,MAAM,CAAC;aACjB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,uBAAuB,EAAE;QACvB,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,EAAE,CAAC;aACZ,SAAS,CAAC,MAAM,CAAC;aACjB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,eAAe,EAAE,UAAU,IAAY,EAAE,KAAa;QACpD,OAAO,IAAI,qBAAU,EAAE;aACpB,UAAU,CAAC,IAAI,CAAC;aAChB,UAAU,CAAC,KAAK,CAAC;aACjB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,cAAc,EAAE,UAAU,SAAiB,EAAE,SAAiB;QAC5D,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,SAAS,CAAC;aACnB,QAAQ,CAAC,SAAS,CAAC;aACnB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,eAAe,EAAE,UAAU,MAAc;QACvC,OAAO,IAAI,qBAAU,EAAE;aACpB,UAAU,CAAC,MAAM,CAAC;aAClB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,cAAc,EAAE,UAAU,MAAa;QACrC,MAAM,GAAG,MAAM,IAAI,EAAE,CAAA;QACrB,IAAI,GAAG,GAAG,IAAI,qBAAU,EAAE,CAAA;QAC1B,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;QAC3B,MAAM,CAAC,OAAO,CAAC,UAAU,KAAK;YAC5B,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;iBACvB,QAAQ,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;iBAC5B,QAAQ,CAAC,KAAK,CAAC,eAAe,IAAI,CAAC,CAAC;iBACpC,QAAQ,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC;iBAC/B,QAAQ,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC;iBACjC,QAAQ,CAAC,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC;iBACjC,QAAQ,CAAC,KAAK,CAAC,UAAU,IAAI,CAAC,CAAC,CAAA;QACpC,CAAC,CAAC,CAAA;QACF,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC5B,CAAC;IAED,OAAO,EAAE,UAAU,OAAc;QAC/B,OAAO,GAAG,OAAO,IAAI,EAAE,CAAA;QACvB,IAAI,GAAG,GAAG,IAAI,qBAAU,EAAE,CAAA;QAC1B,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAC5B,OAAO,CAAC,OAAO,CAAC,UAAU,GAAG;YAC3B,IAAI,GAAG,IAAI,IAAI,EAAE;gBACf,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAA;aACjB;iBAAM;gBACL,IAAI,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;gBACrC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;gBAC3B,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;aAChB;QACH,CAAC,CAAC,CAAA;QACF,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC5B,CAAC;IAED,KAAK,EAAE,UAAU,MAAW;QAC1B,OAAO,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACtD,CAAC;IAED,MAAM,EAAE,UAAU,MAAW;QAC3B,OAAO,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACtD,CAAC;IAED,aAAa,EAAE,UAAU,MAAW;QAClC,MAAM,GAAG,MAAM,IAAI,EAAE,CAAA;QACrB,IAAI,GAAG,GAAG,IAAI,qBAAU,EAAE,CAAA;QAC1B,MAAM,CAAC,OAAO,CAAC,UAAU,KAAU;YACjC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YACvB,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QAC7B,CAAC,CAAC,CAAA;QACF,OAAO,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA,CAAA,aAAa;IAC/C,CAAC;IAED,aAAa,EAAE;QACb,OAAO,IAAI,qBAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACzC,CAAC;IAED,YAAY,EAAE;QACZ,OAAO,IAAI,qBAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACzC,CAAC;IAED,YAAY,EAAE,UAAU,EAAU,EAAE,OAAe,EAAE,OAAe;QAClE,OAAO,IAAI,qBAAU,EAAE;aACpB,QAAQ,CAAC,EAAE,CAAC;aACZ,UAAU,CAAC,OAAO,CAAC;aACnB,UAAU,CAAC,OAAO,CAAC;aACnB,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACpB,CAAC;IAED,UAAU,EAAE;QACV,OAAO,IAAI,qBAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACzC,CAAC;IAED,eAAe,EAAE;QACf,OAAO,IAAI,qBAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACzC,CAAC;IAED,aAAa,EAAE;QACb,OAAO,IAAI,qBAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACzC,CAAC;IAED,MAAM,EAAE,UAAU,IAAY;QAC5B,MAAM,IAAI,GAAG,IAAI,qBAAU,EAAE;YAC3B,YAAY;aACX,OAAO,CAAC,CAAC,CAAC;YACX,eAAe;aACd,QAAQ,CAAC,IAAI,CAAC,CAAC;QAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE;YAC7B,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;SAClB;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC7B,CAAC;IAED,OAAO,EAAE,UAAU,IAAY;QAC7B,MAAM,IAAI,GAAG,IAAI,qBAAU,EAAE;YAC3B,YAAY;aACX,OAAO,CAAC,CAAC,CAAC;YACX,eAAe;aACd,QAAQ,CAAC,IAAI,CAAC,CAAC;QAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE;YAC7B,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;SAClB;QACD,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IAC7B,CAAC;IAED,QAAQ,EAAE,UAAU,KAAa;QAC/B,OAAO,IAAI,qBAAU,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACrD,CAAC;IAED,QAAQ,EAAE;QACR,OAAO,IAAI,qBAAU,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;IACzC,CAAC;CACF,CAAA;AAED,kBAAe,OAAO,CAAA"} \ No newline at end of file diff --git a/packages/pg-query-stream/.eslintrc b/packages/pg-query-stream/.eslintrc deleted file mode 100644 index 95f4d0c65..000000000 --- a/packages/pg-query-stream/.eslintrc +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "standard", - "env": { - "mocha": true - }, - "rules": { - "no-new-func": "off" - } -} diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 4bc8b1b24..b8aaa4d7e 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -4,7 +4,8 @@ "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { - "test": "mocha" + "test": "mocha", + "lint": "eslint ." }, "repository": { "type": "git", @@ -24,25 +25,13 @@ "devDependencies": { "JSONStream": "~0.7.1", "concat-stream": "~1.0.1", - "eslint": "^4.4.0", - "eslint-config-standard": "^10.2.1", - "eslint-plugin-import": "^2.7.0", - "eslint-plugin-node": "^5.1.1", "eslint-plugin-promise": "^3.5.0", - "eslint-plugin-standard": "^3.0.1", "mocha": "^6.2.2", "pg": "^7.5.0", - "prettier": "^1.18.2", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, - "prettier": { - "semi": false, - "printWidth": 120, - "trailingComma": "es5", - "singleQuote": true - }, "dependencies": { "pg-cursor": "^2.0.1" } diff --git a/yarn.lock b/yarn.lock index 7fd9acf02..c24585af0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -885,28 +885,11 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== -acorn-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= - dependencies: - acorn "^3.0.4" - acorn-jsx@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== -acorn@^3.0.4: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= - -acorn@^5.5.0: - version "5.7.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== - acorn@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" @@ -933,21 +916,6 @@ agentkeepalive@^3.4.1: dependencies: humanize-ms "^1.2.1" -ajv-keywords@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" - integrity sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I= - -ajv@^5.2.3, ajv@^5.3.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: version "6.10.2" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" @@ -963,7 +931,7 @@ ansi-colors@3.2.3: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== -ansi-escapes@^3.0.0, ansi-escapes@^3.2.0: +ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== @@ -995,11 +963,6 @@ ansi-regex@^5.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -1171,15 +1134,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c" integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A== -babel-code-frame@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" @@ -1340,13 +1294,6 @@ caller-callsite@^2.0.0: dependencies: callsites "^2.0.0" -caller-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= - dependencies: - callsites "^0.2.0" - caller-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" @@ -1354,11 +1301,6 @@ caller-path@^2.0.0: dependencies: caller-callsite "^2.0.0" -callsites@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= - callsites@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" @@ -1406,17 +1348,6 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -1426,11 +1357,6 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chardet@^0.4.0: - version "0.4.2" - resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.4.2.tgz#b5473b33dc97c424e5d98dc87d55d4d8a29c8bf2" - integrity sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I= - chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -1446,11 +1372,6 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -circular-json@^0.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== - class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" @@ -1503,7 +1424,7 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= -co@4.6.0, co@^4.6.0: +co@4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= @@ -1571,7 +1492,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.5.0, concat-stream@^1.6.0: +concat-stream@^1.5.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -1731,15 +1652,6 @@ cosmiconfig@^5.1.0: js-yaml "^3.13.1" parse-json "^4.0.0" -cross-spawn@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -1932,13 +1844,6 @@ doctrine@1.5.0: esutils "^2.0.2" isarray "^1.0.0" -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -2062,7 +1967,7 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -2074,11 +1979,6 @@ eslint-config-prettier@^6.4.0: dependencies: get-stdin "^6.0.0" -eslint-config-standard@^10.2.1: - version "10.2.1" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591" - integrity sha1-wGHk0GbzedwXzVYsZOgZtN1FRZE= - eslint-config-standard@^13.0.1: version "13.0.1" resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-13.0.1.tgz#c9c6ffe0cfb8a51535bc5c7ec9f70eafb8c6b2c0" @@ -2108,7 +2008,7 @@ eslint-plugin-es@^1.4.1: eslint-utils "^1.4.2" regexpp "^2.0.1" -eslint-plugin-import@^2.18.1, eslint-plugin-import@^2.7.0: +eslint-plugin-import@^2.18.1: version "2.19.1" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.19.1.tgz#5654e10b7839d064dd0d46cd1b88ec2133a11448" integrity sha512-x68131aKoCZlCae7rDXKSAQmbT5DQuManyXo2sK6fJJ0aK5CWAkv6A6HJZGgqC8IhjQxYPgo6/IY4Oz8AFsbBw== @@ -2126,16 +2026,6 @@ eslint-plugin-import@^2.18.1, eslint-plugin-import@^2.7.0: read-pkg-up "^2.0.0" resolve "^1.12.0" -eslint-plugin-node@^5.1.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.2.1.tgz#80df3253c4d7901045ec87fa660a284e32bdca29" - integrity sha512-xhPXrh0Vl/b7870uEbaumb2Q+LxaEcOQ3kS1jtIXanBAwpMre1l5q/l2l/hESYJGEFKuI78bp6Uw50hlpr7B+g== - dependencies: - ignore "^3.3.6" - minimatch "^3.0.4" - resolve "^1.3.3" - semver "5.3.0" - eslint-plugin-node@^9.1.0: version "9.2.0" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-9.2.0.tgz#b1911f111002d366c5954a6d96d3cd5bf2a3036a" @@ -2165,24 +2055,11 @@ eslint-plugin-promise@^4.2.1: resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw== -eslint-plugin-standard@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.1.0.tgz#2a9e21259ba4c47c02d53b2d0c9135d4b1022d47" - integrity sha512-fVcdyuKRr0EZ4fjWl3c+gp1BANFJD1+RaWa2UPYfMZ6jCtp5RG00kSaXnK/dE5sYzt4kaWJ9qdxqUfc0d9kX0w== - eslint-plugin-standard@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz#ff0519f7ffaff114f76d1bd7c3996eef0f6e20b4" integrity sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ== -eslint-scope@^3.7.1: - version "3.7.3" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.3.tgz#bb507200d3d17f60247636160b4826284b108535" - integrity sha512-W+B0SvF4gamyCTmUc+uITPY0989iXVfKvhwtmJocTaYoc/3khEHmEmvfY/Gn9HA9VV75jrQECsHizkNw1b68FA== - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - eslint-scope@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" @@ -2198,55 +2075,11 @@ eslint-utils@^1.4.2, eslint-utils@^1.4.3: dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0: +eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== -eslint@^4.4.0: - version "4.19.1" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.19.1.tgz#32d1d653e1d90408854bfb296f076ec7e186a300" - integrity sha512-bT3/1x1EbZB7phzYu7vCr1v3ONuzDtX8WjuM9c0iYxe+cq+pwcKEoQjl7zd3RpC6YOLgnSy3cTN58M2jcoPDIQ== - dependencies: - ajv "^5.3.0" - babel-code-frame "^6.22.0" - chalk "^2.1.0" - concat-stream "^1.6.0" - cross-spawn "^5.1.0" - debug "^3.1.0" - doctrine "^2.1.0" - eslint-scope "^3.7.1" - eslint-visitor-keys "^1.0.0" - espree "^3.5.4" - esquery "^1.0.0" - esutils "^2.0.2" - file-entry-cache "^2.0.0" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.0.1" - ignore "^3.3.3" - imurmurhash "^0.1.4" - inquirer "^3.0.6" - is-resolvable "^1.0.0" - js-yaml "^3.9.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.4" - minimatch "^3.0.2" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" - pluralize "^7.0.0" - progress "^2.0.0" - regexpp "^1.0.1" - require-uncached "^1.0.3" - semver "^5.3.0" - strip-ansi "^4.0.0" - strip-json-comments "~2.0.1" - table "4.0.2" - text-table "~0.2.0" - eslint@^6.0.1, eslint@^6.5.1: version "6.7.2" resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.2.tgz#c17707ca4ad7b2d8af986a33feba71e18a9fecd1" @@ -2290,14 +2123,6 @@ eslint@^6.0.1, eslint@^6.5.1: text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^3.5.4: - version "3.5.4" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" - integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== - dependencies: - acorn "^5.5.0" - acorn-jsx "^3.0.0" - espree@^6.1.2: version "6.1.2" resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" @@ -2312,7 +2137,7 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.0, esquery@^1.0.1: +esquery@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== @@ -2387,15 +2212,6 @@ extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -external-editor@^2.0.4: - version "2.2.0" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.2.0.tgz#045511cfd8d133f3846673d1047c154e214ad3d5" - integrity sha512-bSn6gvGxKt+b7+6TKEv1ZycHleA7aHhRHyAqJyp5pbUFuYYNIzpZnQDk7AsYckyWdEnTeAnay0aCy2aV6iTk9A== - dependencies: - chardet "^0.4.0" - iconv-lite "^0.4.17" - tmp "^0.0.33" - external-editor@^3.0.3: version "3.1.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" @@ -2429,11 +2245,6 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - integrity sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ= - fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" @@ -2485,14 +2296,6 @@ figures@^3.0.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" - integrity sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E= - dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" - file-entry-cache@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" @@ -2532,16 +2335,6 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" -flat-cache@^1.2.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" - integrity sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg== - dependencies: - circular-json "^0.3.1" - graceful-fs "^4.1.2" - rimraf "~2.6.2" - write "^0.2.1" - flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -2805,7 +2598,7 @@ glob@7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: +glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -2817,11 +2610,6 @@ glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: once "^1.3.0" path-is-absolute "^1.0.0" -globals@^11.0.1: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - globals@^12.1.0: version "12.3.0" resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13" @@ -2877,13 +2665,6 @@ har-validator@~5.1.0: ajv "^6.5.5" har-schema "^2.0.0" -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -2984,7 +2765,7 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@~0.4.13: +iconv-lite@^0.4.24, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -3003,11 +2784,6 @@ ignore-walk@^3.0.1: dependencies: minimatch "^3.0.4" -ignore@^3.3.3, ignore@^3.3.6: - version "3.3.10" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" - integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== - ignore@^4.0.3, ignore@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" @@ -3096,26 +2872,6 @@ init-package-json@^1.10.3: validate-npm-package-license "^3.0.1" validate-npm-package-name "^3.0.0" -inquirer@^3.0.6: - version "3.3.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" - integrity sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ== - dependencies: - ansi-escapes "^3.0.0" - chalk "^2.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.4" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx-lite "^4.0.8" - rx-lite-aggregates "^4.0.8" - string-width "^2.1.0" - strip-ansi "^4.0.0" - through "^2.3.6" - inquirer@^6.2.0: version "6.5.2" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.2.tgz#ad50942375d036d327ff528c08bd5fab089928ca" @@ -3340,11 +3096,6 @@ is-regex@^1.0.4: dependencies: has "^1.0.3" -is-resolvable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== - is-ssh@^1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.1.tgz#f349a8cadd24e65298037a522cf7520f2e81a0f3" @@ -3418,17 +3169,12 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= - js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.13.1, js-yaml@^3.13.1, js-yaml@^3.9.1: +js-yaml@3.13.1, js-yaml@^3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -3446,11 +3192,6 @@ json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1: resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - integrity sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A= - json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -3661,7 +3402,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.2.1, lodash@^4.3.0: +lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -3681,14 +3422,6 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" -lru-cache@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -3852,7 +3585,7 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: +minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -4299,7 +4032,7 @@ optimist@^0.6.1: minimist "~0.0.1" wordwrap "~0.0.2" -optionator@^0.8.2, optionator@^0.8.3: +optionator@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -4502,11 +4235,6 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" @@ -4624,11 +4352,6 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" -pluralize@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== - posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -4720,11 +4443,6 @@ protoduck@^5.0.1: dependencies: genfun "^5.0.0" -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= - psl@^1.1.24: version "1.6.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.6.0.tgz#60557582ee23b6c43719d9890fb4170ecd91e110" @@ -4922,11 +4640,6 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexpp@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-1.1.0.tgz#0e3516dd0b7904f413d2d4193dce4618c3a689ab" - integrity sha512-LOPw8FpgdQF9etWMaAfG/WRthIdXJGYp4mJ2Jgn/2lpkbod9jPn0t9UqN7AxBOKNfzRbYyVfgc7Vk4t/MpnXgw== - regexpp@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" @@ -4992,14 +4705,6 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== -require-uncached@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= - dependencies: - caller-path "^0.1.0" - resolve-from "^1.0.0" - resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" @@ -5007,11 +4712,6 @@ resolve-cwd@^2.0.0: dependencies: resolve-from "^3.0.0" -resolve-from@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= - resolve-from@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" @@ -5034,13 +4734,6 @@ resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.5.0: dependencies: path-parse "^1.0.6" -resolve@^1.3.3: - version "1.14.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.1.tgz#9e018c540fcf0c427d678b9931cbf45e984bcaff" - integrity sha512-fn5Wobh4cxbLzuHaE+nphztHy43/b++4M6SsGFC2gB8uYwf0C8LcarfCz1un7UTW8OFQg9iNjZ4xpcFVGebDPg== - dependencies: - path-parse "^1.0.6" - restore-cursor@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" @@ -5067,7 +4760,7 @@ retry@^0.10.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q= -rimraf@2.6.3, rimraf@~2.6.2: +rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== @@ -5095,18 +4788,6 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rx-lite-aggregates@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" - integrity sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74= - dependencies: - rx-lite "*" - -rx-lite@*, rx-lite@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" - integrity sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ= - rxjs@^6.4.0, rxjs@^6.5.3: version "6.5.3" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" @@ -5136,7 +4817,7 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: +"semver@2 || 3 || 4 || 5", "semver@2.x || 3.x || 4 || 5", semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0, semver@^5.7.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -5146,11 +4827,6 @@ semver@4.3.2: resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= -semver@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - integrity sha1-myzl094C0XxgEq0yaqa00M9U+U8= - semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.2.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" @@ -5200,13 +4876,6 @@ slash@^2.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== -slice-ansi@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" - integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== - dependencies: - is-fullwidth-code-point "^2.0.0" - slice-ansi@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" @@ -5425,7 +5094,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^1.0.0" strip-ansi "^3.0.0" -"string-width@^1.0.2 || 2", string-width@^2.1.0, string-width@^2.1.1: +"string-width@^1.0.2 || 2", string-width@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== @@ -5538,7 +5207,7 @@ strip-indent@^2.0.0: resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= -strip-json-comments@2.0.1, strip-json-comments@~2.0.1: +strip-json-comments@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= @@ -5564,11 +5233,6 @@ supports-color@6.0.0: dependencies: has-flag "^3.0.0" -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -5576,18 +5240,6 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" -table@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" - integrity sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA== - dependencies: - ajv "^5.2.3" - ajv-keywords "^2.1.0" - chalk "^2.1.0" - lodash "^4.17.4" - slice-ansi "1.0.0" - string-width "^2.1.1" - table@^5.2.3: version "5.4.6" resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" @@ -5633,7 +5285,7 @@ text-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" integrity sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ== -text-table@^0.2.0, text-table@~0.2.0: +text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= @@ -6041,13 +5693,6 @@ write@1.0.3: dependencies: mkdirp "^0.5.1" -write@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= - dependencies: - mkdirp "^0.5.1" - xtend@^4.0.0, xtend@~4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" @@ -6058,11 +5703,6 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= - yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" From 6b7b8d19f50f207c29be254c945206dc89cd6632 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 20 Dec 2019 15:03:43 -0600 Subject: [PATCH 0550/1037] Do not run tests in parallel --- package.json | 2 +- packages/pg-query-stream/test/slow-reader.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 8386726e9..59b21be2e 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "packages/*" ], "scripts": { - "test": "yarn lerna exec --parallel yarn test", + "test": "yarn lerna exec yarn test", "lint": "yarn lerna exec --parallel yarn lint" }, "devDependencies": { diff --git a/packages/pg-query-stream/test/slow-reader.js b/packages/pg-query-stream/test/slow-reader.js index c95574a7a..4c0070a35 100644 --- a/packages/pg-query-stream/test/slow-reader.js +++ b/packages/pg-query-stream/test/slow-reader.js @@ -4,7 +4,7 @@ var concat = require('concat-stream') var Transform = require('stream').Transform -var mapper = new Transform({objectMode: true}) +var mapper = new Transform({ objectMode: true }) mapper._transform = function (obj, enc, cb) { this.push(obj) @@ -14,7 +14,7 @@ mapper._transform = function (obj, enc, cb) { helper('slow reader', function (client) { it('works', function (done) { this.timeout(50000) - var stream = new QueryStream('SELECT * FROM generate_series(0, 201) num', [], {highWaterMark: 100, batchSize: 50}) + var stream = new QueryStream('SELECT * FROM generate_series(0, 201) num', [], { highWaterMark: 100, batchSize: 50 }) stream.on('end', function () { // console.log('stream end') }) From fdae8516e666649393ba601070e730b5db4fa708 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 20 Dec 2019 15:10:26 -0600 Subject: [PATCH 0551/1037] Delete files which are no longer needed as they exist in the monorepo --- packages/pg-query-stream/.travis.yml | 14 -------------- packages/pg-query-stream/Makefile | 14 -------------- packages/pg-query-stream/package.json | 4 ++-- 3 files changed, 2 insertions(+), 30 deletions(-) delete mode 100644 packages/pg-query-stream/.travis.yml delete mode 100644 packages/pg-query-stream/Makefile diff --git a/packages/pg-query-stream/.travis.yml b/packages/pg-query-stream/.travis.yml deleted file mode 100644 index 177e9511b..000000000 --- a/packages/pg-query-stream/.travis.yml +++ /dev/null @@ -1,14 +0,0 @@ -language: node_js -dist: trusty -node_js: - - "8" - - "10" - - "12" -env: - - PGUSER=postgres -services: - - postgresql -addons: - postgresql: "9.6" -before_script: - - psql -c 'create database travis;' -U postgres | true diff --git a/packages/pg-query-stream/Makefile b/packages/pg-query-stream/Makefile deleted file mode 100644 index d7ec83d54..000000000 --- a/packages/pg-query-stream/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -.PHONY: 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 diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index b8aaa4d7e..ee03ab806 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -9,7 +9,7 @@ }, "repository": { "type": "git", - "url": "git://github.com/brianc/node-pg-query-stream.git" + "url": "git://github.com/brianc/node-postgres.git" }, "keywords": [ "postgres", @@ -20,7 +20,7 @@ "author": "Brian M. Carlson", "license": "MIT", "bugs": { - "url": "https://github.com/brianc/node-pg-query-stream/issues" + "url": "https://github.com/brianc/node-postgres/issues" }, "devDependencies": { "JSONStream": "~0.7.1", From 8b7e874a37552bdeb3ccb841634920b41e7c670e Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 20 Dec 2019 17:48:26 -0600 Subject: [PATCH 0552/1037] Update readme --- README.md | 1 + packages/pg/README.md | 95 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 packages/pg/README.md diff --git a/README.md b/README.md index f1368773d..256c300f8 100644 --- a/README.md +++ b/README.md @@ -86,3 +86,4 @@ Copyright (c) 2010-2019 Brian Carlson (brian.m.carlson@gmail.com) 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. + diff --git a/packages/pg/README.md b/packages/pg/README.md new file mode 100644 index 000000000..89815953a --- /dev/null +++ b/packages/pg/README.md @@ -0,0 +1,95 @@ +# node-postgres + +[![Build Status](https://secure.travis-ci.org/brianc/node-postgres.svg?branch=master)](http://travis-ci.org/brianc/node-postgres) +[![Dependency Status](https://david-dm.org/brianc/node-postgres.svg)](https://david-dm.org/brianc/node-postgres) +NPM version +NPM downloads + +Non-blocking PostgreSQL client for Node.js. Pure JavaScript and optional native libpq bindings. + +## Monorepo + +This repo is a monorepo which contains the core [pg](https://github.com/brianc/node-postgres) module as well as a handful of related modules. + +- [pg-cursor](https://github.com/brianc/node-postgres/tree/master/packages/pg-cursor) + + +## Documenation + +Each package in this repo should have it's own readme more focused on how to develop/contribute. For overall documentation on the project and the related modules managed by this repo please see: + +### :star: [Documentation](https://node-postgres.com) :star: + +### Features + +* Pure JavaScript client and native libpq bindings share _the same API_ +* Connection pooling +* Extensible JS ↔ PostgreSQL data-type coercion +* Supported PostgreSQL features + * Parameterized queries + * Named statements with query plan caching + * Async notifications with `LISTEN/NOTIFY` + * Bulk import & export with `COPY TO/COPY FROM` + +### Extras + +node-postgres is by design pretty light on abstractions. These are some handy modules we've been using over the years to complete the picture. +The entire list can be found on our [wiki](https://github.com/brianc/node-postgres/wiki/Extras). + +## Support + +node-postgres is free software. If you encounter a bug with the library please open an issue on the [GitHub repo](https://github.com/brianc/node-postgres). If you have questions unanswered by the documentation please open an issue pointing out how the documentation was unclear & I will do my best to make it better! + +When you open an issue please provide: +- version of Node +- version of Postgres +- smallest possible snippet of code to reproduce the problem + +You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on Twitter. + +### Professional Support + +I offer professional support for node-postgres. I provide implementation, training, and many years of expertise on how to build applications with Node, Express, PostgreSQL, and React/Redux. Please contact me at [brian.m.carlson@gmail.com](mailto:brian.m.carlson@gmail.com) to discuss how I can help your company be more successful! + +### Sponsorship :star: + +[If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable please consider supporting](https://github.com/sponsors/brianc) to its development. + +Also, you can view a historical list of all [previous and existing sponsors](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md). + +## Contributing + +__:heart: contributions!__ + +I will __happily__ accept your pull request if it: +- __has tests__ +- looks reasonable +- does not break backwards compatibility + +If your change involves breaking backwards compatibility please please point that out in the pull request & we can discuss & plan when and how to release it and what type of documentation or communicate it will require. + +## Troubleshooting and FAQ + +The causes and solutions to common errors can be found among the [Frequently Asked Questions (FAQ)](https://github.com/brianc/node-postgres/wiki/FAQ) + +## License + +Copyright (c) 2010-2019 Brian Carlson (brian.m.carlson@gmail.com) + + 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. From c090e4fdaf9c5949ec5c4472e1818002415ab3a8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 20 Dec 2019 17:53:26 -0600 Subject: [PATCH 0553/1037] Actually update the right file in the right place... --- README.md | 28 ++++++++++++++++------------ packages/pg/README.md | 24 ++++++++++-------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 256c300f8..2cda30984 100644 --- a/README.md +++ b/README.md @@ -7,15 +7,20 @@ Non-blocking PostgreSQL client for Node.js. Pure JavaScript and optional native libpq bindings. -## Install +## Monorepo -```sh -$ npm install pg -``` +This repo is a monorepo which contains the core [pg](https://github.com/brianc/node-postgres) module as well as a handful of related modules. ---- -## :star: [Documentation](https://node-postgres.com) :star: +- [pg-cursor](https://github.com/brianc/node-postgres/tree/master/packages/pg-cursor) +_(more to come, I'm in the process of migrating repos over here)_ + + +## Documenation + +Each package in this repo should have it's own readme more focused on how to develop/contribute. For overall documentation on the project and the related modules managed by this repo please see: + +### :star: [Documentation](https://node-postgres.com) :star: ### Features @@ -44,13 +49,11 @@ When you open an issue please provide: You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on Twitter. -### Professional Support - -I offer professional support for node-postgres. I provide implementation, training, and many years of expertise on how to build applications with Node, Express, PostgreSQL, and React/Redux. Please contact me at [brian.m.carlson@gmail.com](mailto:brian.m.carlson@gmail.com) to discuss how I can help your company be more successful! - ### Sponsorship :star: -If you are benefiting from node-postgres and would like to help keep the project financially sustainable please visit Brian Carlson's [Patreon page](https://www.patreon.com/node_postgres). +[If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable please consider supporting](https://github.com/sponsors/brianc) its development. + +Also, you can view a historical list of all [previous and existing sponsors](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md). ## Contributing @@ -61,6 +64,8 @@ I will __happily__ accept your pull request if it: - looks reasonable - does not break backwards compatibility +If your change involves breaking backwards compatibility please please point that out in the pull request & we can discuss & plan when and how to release it and what type of documentation or communicate it will require. + ## Troubleshooting and FAQ The causes and solutions to common errors can be found among the [Frequently Asked Questions (FAQ)](https://github.com/brianc/node-postgres/wiki/FAQ) @@ -86,4 +91,3 @@ Copyright (c) 2010-2019 Brian Carlson (brian.m.carlson@gmail.com) 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. - diff --git a/packages/pg/README.md b/packages/pg/README.md index 89815953a..adf0eba12 100644 --- a/packages/pg/README.md +++ b/packages/pg/README.md @@ -7,19 +7,16 @@ Non-blocking PostgreSQL client for Node.js. Pure JavaScript and optional native libpq bindings. -## Monorepo +## Install -This repo is a monorepo which contains the core [pg](https://github.com/brianc/node-postgres) module as well as a handful of related modules. +```sh +$ npm install pg +``` -- [pg-cursor](https://github.com/brianc/node-postgres/tree/master/packages/pg-cursor) +--- +## :star: [Documentation](https://node-postgres.com) :star: -## Documenation - -Each package in this repo should have it's own readme more focused on how to develop/contribute. For overall documentation on the project and the related modules managed by this repo please see: - -### :star: [Documentation](https://node-postgres.com) :star: - ### Features * Pure JavaScript client and native libpq bindings share _the same API_ @@ -47,16 +44,13 @@ When you open an issue please provide: You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on Twitter. -### Professional Support - -I offer professional support for node-postgres. I provide implementation, training, and many years of expertise on how to build applications with Node, Express, PostgreSQL, and React/Redux. Please contact me at [brian.m.carlson@gmail.com](mailto:brian.m.carlson@gmail.com) to discuss how I can help your company be more successful! - ### Sponsorship :star: -[If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable please consider supporting](https://github.com/sponsors/brianc) to its development. +[If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable please consider supporting](https://github.com/sponsors/brianc) its development. Also, you can view a historical list of all [previous and existing sponsors](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md). + ## Contributing __:heart: contributions!__ @@ -68,6 +62,7 @@ I will __happily__ accept your pull request if it: If your change involves breaking backwards compatibility please please point that out in the pull request & we can discuss & plan when and how to release it and what type of documentation or communicate it will require. + ## Troubleshooting and FAQ The causes and solutions to common errors can be found among the [Frequently Asked Questions (FAQ)](https://github.com/brianc/node-postgres/wiki/FAQ) @@ -93,3 +88,4 @@ Copyright (c) 2010-2019 Brian Carlson (brian.m.carlson@gmail.com) 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. + From e03401081162ce71d66346f0669670528797c22a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 26 Dec 2019 16:45:37 +0000 Subject: [PATCH 0554/1037] Add docker devcontainer stuff --- .devcontainer/Dockerfile | 68 ++++++++++++++++++++++++++++++++ .devcontainer/devcontainer.json | 31 +++++++++++++++ .devcontainer/docker-compose.yml | 44 +++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100644 .devcontainer/docker-compose.yml diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 000000000..c1c782d55 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,68 @@ +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- + +FROM node:12 + +# Avoid warnings by switching to noninteractive +ENV DEBIAN_FRONTEND=noninteractive + +# The node image includes a non-root user with sudo access. Use the +# "remoteUser" property in devcontainer.json to use it. On Linux, update +# these values to ensure the container user's UID/GID matches your local values. +# See https://aka.ms/vscode-remote/containers/non-root-user for details. +ARG USERNAME=node +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +# Configure apt and install packages +RUN apt-get update \ + && apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \ + # + # Verify git and needed tools are installed + && apt-get -y install git iproute2 procps \ + # + # Remove outdated yarn from /opt and install via package + # so it can be easily updated via apt-get upgrade yarn + && rm -rf /opt/yarn-* \ + && rm -f /usr/local/bin/yarn \ + && rm -f /usr/local/bin/yarnpkg \ + && apt-get install -y curl apt-transport-https lsb-release \ + && curl -sS https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/pubkey.gpg | apt-key add - 2>/dev/null \ + && echo "deb https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ + && apt-get update \ + && apt-get -y install --no-install-recommends yarn tmux locales \ + # + # Install eslint globally + && npm install -g eslint \ + # + # [Optional] Update a non-root user to UID/GID if needed. + && if [ "$USER_GID" != "1000" ] || [ "$USER_UID" != "1000" ]; then \ + groupmod --gid $USER_GID $USERNAME \ + && usermod --uid $USER_UID --gid $USER_GID $USERNAME \ + && chown -R $USER_UID:$USER_GID /home/$USERNAME; \ + fi \ + # [Optional] Add add sudo support for non-root user + && apt-get install -y sudo \ + && echo node ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME \ + # + # Clean up + && apt-get autoremove -y \ + && apt-get clean -y \ + && rm -rf /var/lib/apt/lists/* + +RUN curl https://raw.githubusercontent.com/brianc/dotfiles/master/.tmux.conf > ~/.tmux.conf + +# install nvm +RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.2/install.sh | bash + +# Set the locale +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + +# Switch back to dialog for any ad-hoc use of apt-get +ENV DEBIAN_FRONTEND=dialog diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..14fb67344 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,31 @@ +// If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml. +{ + "name": "Node.js 12 & Postgres", + "dockerComposeFile": "docker-compose.yml", + "service": "web", + "workspaceFolder": "/workspace", + + // Use 'settings' to set *default* container specific settings.json values on container create. + // You can edit these settings after create using File > Preferences > Settings > Remote. + "settings": { + "terminal.integrated.shell.linux": "/bin/bash" + }, + + // Uncomment the next line if you want start specific services in your Docker Compose config. + // "runServices": [], + + // Uncomment the line below if you want to keep your containers running after VS Code shuts down. + // "shutdownAction": "none", + + // Uncomment the next line to run commands after the container is created. + // "postCreateCommand": "npm install", + + // Uncomment the next line to have VS Code connect as an existing non-root user in the container. See + // https://aka.ms/vscode-remote/containers/non-root for details on adding a non-root user if none exist. + // "remoteUser": "node", + + // Add the IDs of extensions you want installed when the container is created in the array below. + "extensions": [ + "dbaeumer.vscode-eslint" + ] +} \ No newline at end of file diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 000000000..184aff0ed --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,44 @@ +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- + +version: '3' +services: + web: + # Uncomment the next line to use a non-root user for all processes. You can also + # simply use the "remoteUser" property in devcontainer.json if you just want VS Code + # and its sub-processes (terminals, tasks, debugging) to execute as the user. On Linux, + # you may need to update USER_UID and USER_GID in .devcontainer/Dockerfile to match your + # user if not 1000. See https://aka.ms/vscode-remote/containers/non-root for details. + # user: node + + build: + context: . + dockerfile: Dockerfile + + volumes: + - ..:/workspace:cached + + environment: + PGPASSWORD: pass + PGUSER: user + PGDATABASE: data + PGHOST: db + + # Overrides default command so things don't shut down after the process ends. + command: sleep infinity + + links: + - db + + db: + image: postgres + restart: unless-stopped + ports: + - 5432:5432 + environment: + POSTGRES_PASSWORD: pass + POSTGRES_USER: user + POSTGRES_DB: data + From 0167a4177cb766afee169c5aa0101fb4176eb964 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 26 Dec 2019 16:56:30 +0000 Subject: [PATCH 0555/1037] Add devcontainer for working on windows --- .devcontainer/Dockerfile | 68 ++++++++++++++++++++++++++++++++ .devcontainer/devcontainer.json | 31 +++++++++++++++ .devcontainer/docker-compose.yml | 44 +++++++++++++++++++++ 3 files changed, 143 insertions(+) create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100644 .devcontainer/docker-compose.yml diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 000000000..c1c782d55 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,68 @@ +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- + +FROM node:12 + +# Avoid warnings by switching to noninteractive +ENV DEBIAN_FRONTEND=noninteractive + +# The node image includes a non-root user with sudo access. Use the +# "remoteUser" property in devcontainer.json to use it. On Linux, update +# these values to ensure the container user's UID/GID matches your local values. +# See https://aka.ms/vscode-remote/containers/non-root-user for details. +ARG USERNAME=node +ARG USER_UID=1000 +ARG USER_GID=$USER_UID + +# Configure apt and install packages +RUN apt-get update \ + && apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \ + # + # Verify git and needed tools are installed + && apt-get -y install git iproute2 procps \ + # + # Remove outdated yarn from /opt and install via package + # so it can be easily updated via apt-get upgrade yarn + && rm -rf /opt/yarn-* \ + && rm -f /usr/local/bin/yarn \ + && rm -f /usr/local/bin/yarnpkg \ + && apt-get install -y curl apt-transport-https lsb-release \ + && curl -sS https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/pubkey.gpg | apt-key add - 2>/dev/null \ + && echo "deb https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ + && apt-get update \ + && apt-get -y install --no-install-recommends yarn tmux locales \ + # + # Install eslint globally + && npm install -g eslint \ + # + # [Optional] Update a non-root user to UID/GID if needed. + && if [ "$USER_GID" != "1000" ] || [ "$USER_UID" != "1000" ]; then \ + groupmod --gid $USER_GID $USERNAME \ + && usermod --uid $USER_UID --gid $USER_GID $USERNAME \ + && chown -R $USER_UID:$USER_GID /home/$USERNAME; \ + fi \ + # [Optional] Add add sudo support for non-root user + && apt-get install -y sudo \ + && echo node ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \ + && chmod 0440 /etc/sudoers.d/$USERNAME \ + # + # Clean up + && apt-get autoremove -y \ + && apt-get clean -y \ + && rm -rf /var/lib/apt/lists/* + +RUN curl https://raw.githubusercontent.com/brianc/dotfiles/master/.tmux.conf > ~/.tmux.conf + +# install nvm +RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.2/install.sh | bash + +# Set the locale +RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen +ENV LANG en_US.UTF-8 +ENV LANGUAGE en_US:en +ENV LC_ALL en_US.UTF-8 + +# Switch back to dialog for any ad-hoc use of apt-get +ENV DEBIAN_FRONTEND=dialog diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..14fb67344 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,31 @@ +// If you want to run as a non-root user in the container, see .devcontainer/docker-compose.yml. +{ + "name": "Node.js 12 & Postgres", + "dockerComposeFile": "docker-compose.yml", + "service": "web", + "workspaceFolder": "/workspace", + + // Use 'settings' to set *default* container specific settings.json values on container create. + // You can edit these settings after create using File > Preferences > Settings > Remote. + "settings": { + "terminal.integrated.shell.linux": "/bin/bash" + }, + + // Uncomment the next line if you want start specific services in your Docker Compose config. + // "runServices": [], + + // Uncomment the line below if you want to keep your containers running after VS Code shuts down. + // "shutdownAction": "none", + + // Uncomment the next line to run commands after the container is created. + // "postCreateCommand": "npm install", + + // Uncomment the next line to have VS Code connect as an existing non-root user in the container. See + // https://aka.ms/vscode-remote/containers/non-root for details on adding a non-root user if none exist. + // "remoteUser": "node", + + // Add the IDs of extensions you want installed when the container is created in the array below. + "extensions": [ + "dbaeumer.vscode-eslint" + ] +} \ No newline at end of file diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 000000000..184aff0ed --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,44 @@ +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- + +version: '3' +services: + web: + # Uncomment the next line to use a non-root user for all processes. You can also + # simply use the "remoteUser" property in devcontainer.json if you just want VS Code + # and its sub-processes (terminals, tasks, debugging) to execute as the user. On Linux, + # you may need to update USER_UID and USER_GID in .devcontainer/Dockerfile to match your + # user if not 1000. See https://aka.ms/vscode-remote/containers/non-root for details. + # user: node + + build: + context: . + dockerfile: Dockerfile + + volumes: + - ..:/workspace:cached + + environment: + PGPASSWORD: pass + PGUSER: user + PGDATABASE: data + PGHOST: db + + # Overrides default command so things don't shut down after the process ends. + command: sleep infinity + + links: + - db + + db: + image: postgres + restart: unless-stopped + ports: + - 5432:5432 + environment: + POSTGRES_PASSWORD: pass + POSTGRES_USER: user + POSTGRES_DB: data + From 30fb8fbec4e28aab4b4c05e0f8634d94a27f5e66 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 26 Dec 2019 17:40:03 +0000 Subject: [PATCH 0556/1037] Improve dockerfile prompt --- .devcontainer/Dockerfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index c1c782d55..36305f210 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -58,6 +58,11 @@ RUN curl https://raw.githubusercontent.com/brianc/dotfiles/master/.tmux.conf > ~ # install nvm RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.2/install.sh | bash +# set up a nicer prompt +RUN git clone https://github.com/magicmonty/bash-git-prompt.git ~/.bash-git-prompt --depth=1 + +RUN echo "source $HOME/.bash-git-prompt/gitprompt.sh" >> ~/.bashrc + # Set the locale RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen ENV LANG en_US.UTF-8 From dfae78e383ee33eac074fa93aa2fbb3d68f527b9 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 26 Dec 2019 17:42:55 +0000 Subject: [PATCH 0557/1037] Publish - pg-cursor@2.0.3 - pg-query-stream@2.0.2 - pg@7.15.2 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index c6841003d..14d6387d8 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.0.2", + "version": "2.0.3", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -21,7 +21,7 @@ "eslint-config-prettier": "^6.4.0", "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "^7.15.1", + "pg": "^7.15.2", "prettier": "^1.18.2" }, "prettier": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index ee03ab806..97d064c7a 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "2.0.1", + "version": "2.0.2", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -27,12 +27,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^6.2.2", - "pg": "^7.5.0", + "pg": "^7.15.2", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.0.1" + "pg-cursor": "^2.0.3" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 951e42df6..b8ba359e8 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.15.1", + "version": "7.15.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 75c94dc7fd58f5d470375a55478fec94023356b9 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 26 Dec 2019 17:48:15 +0000 Subject: [PATCH 0558/1037] Update readme Add links to pg module and pg-query-stream module --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2cda30984..7c5a90760 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,11 @@ Non-blocking PostgreSQL client for Node.js. Pure JavaScript and optional native ## Monorepo -This repo is a monorepo which contains the core [pg](https://github.com/brianc/node-postgres) module as well as a handful of related modules. +This repo is a monorepo which contains the core [pg](https://github.com/brianc/node-postgres/tree/master/packages/pg) module as well as a handful of related modules. +- [pg](https://github.com/brianc/node-postgres/tree/master/packages/pg) - [pg-cursor](https://github.com/brianc/node-postgres/tree/master/packages/pg-cursor) +- [pg-query-stream](https://github.com/brianc/node-postgres/tree/master/packages/pg-query-stream) _(more to come, I'm in the process of migrating repos over here)_ From 5c5dcc5b34ddae8d1eca166c1dc17705bfa99df5 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 26 Dec 2019 17:50:11 +0000 Subject: [PATCH 0559/1037] Add node_modules to dockerfile path --- .devcontainer/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 36305f210..f7106a5b7 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -62,6 +62,7 @@ RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.2/install.sh | b RUN git clone https://github.com/magicmonty/bash-git-prompt.git ~/.bash-git-prompt --depth=1 RUN echo "source $HOME/.bash-git-prompt/gitprompt.sh" >> ~/.bashrc +RUN echo "export PATH=$PATH:./node_modules/.bin" >> ~/.bashrc # Set the locale RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen From d28d8268573005fb68e7a3eef5dc41d9d47aeb10 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 26 Dec 2019 18:03:06 +0000 Subject: [PATCH 0560/1037] Ignore markdown changes in lerna updated --- lerna.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 3a60d401d..dbbf2c9c5 100644 --- a/lerna.json +++ b/lerna.json @@ -4,5 +4,8 @@ ], "npmClient": "yarn", "useWorkspaces": true, - "version": "independent" + "version": "independent", + "ignoreChanges": [ + "**/*.md" + ] } From 5a6166d0aeef5c38f9772f3105c17a7e30ad34d5 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 26 Dec 2019 18:36:29 +0000 Subject: [PATCH 0561/1037] Fire close callback when ready for next query Working on fixing some timing issues in pg-query-stream it uncovered an issue where the cursor is firing its 'close' callback before it's actually entirely ready to dispatch another query. This change makes the close callback trigger when the connection re-enters `readyForQuery` state. --- packages/pg-cursor/index.js | 4 ++-- packages/pg-cursor/test/close.js | 8 ++++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index 405a67129..624877680 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -6,7 +6,7 @@ const util = require('util') let nextUniqueID = 1 // concept borrowed from org.postgresql.core.v3.QueryExecutorImpl -function Cursor (text, values, config) { +function Cursor(text, values, config) { EventEmitter.call(this) this._conf = config || {} @@ -192,7 +192,7 @@ Cursor.prototype.close = function (cb) { this._closePortal() this.state = 'done' if (cb) { - this.connection.once('closeComplete', function () { + this.connection.once('readyForQuery', function () { cb() }) } diff --git a/packages/pg-cursor/test/close.js b/packages/pg-cursor/test/close.js index 5497c51b2..785a71098 100644 --- a/packages/pg-cursor/test/close.js +++ b/packages/pg-cursor/test/close.js @@ -7,7 +7,10 @@ describe('close', function () { beforeEach(function (done) { const client = (this.client = new pg.Client()) client.connect(done) - client.on('drain', client.end.bind(client)) + }) + + this.afterEach(function (done) { + this.client.end(done) }) it('can close a finished cursor without a callback', function (done) { @@ -34,8 +37,9 @@ describe('close', function () { const cursor = new Cursor(text) const client = this.client client.query(cursor) - cursor.read(25, function (err) { + cursor.read(25, function (err, rows) { assert.ifError(err) + assert.strictEqual(rows.length, 25) cursor.close(function (err) { assert.ifError(err) client.query('SELECT NOW()', done) From 47af4e810fba8e0ab91cc1b45f7d9a3fe8bd49f3 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 26 Dec 2019 19:20:43 +0000 Subject: [PATCH 0562/1037] Don't modify path vscode remote docker does some crazy path overriding...I think this messed it up somehow. Anyways, no need to do this. --- .devcontainer/Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index f7106a5b7..36305f210 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -62,7 +62,6 @@ RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.2/install.sh | b RUN git clone https://github.com/magicmonty/bash-git-prompt.git ~/.bash-git-prompt --depth=1 RUN echo "source $HOME/.bash-git-prompt/gitprompt.sh" >> ~/.bashrc -RUN echo "export PATH=$PATH:./node_modules/.bin" >> ~/.bashrc # Set the locale RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen From 766e48f34a5efaf52cfdc545230aaccfbb3d5107 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 27 Dec 2019 02:55:18 +0000 Subject: [PATCH 0563/1037] Update types & move some configs around --- .devcontainer/Dockerfile | 2 +- .eslintrc | 21 +++- packages/pg-packet-stream/package.json | 15 ++- packages/pg-packet-stream/src/index.test.ts | 103 -------------------- packages/pg-packet-stream/src/index.ts | 40 ++++---- packages/pg-packet-stream/src/messages.ts | 75 ++++++++++---- packages/pg-packet-stream/tsconfig.json | 1 + 7 files changed, 104 insertions(+), 153 deletions(-) delete mode 100644 packages/pg-packet-stream/src/index.test.ts diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index c1c782d55..179bc2250 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -32,7 +32,7 @@ RUN apt-get update \ && curl -sS https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/pubkey.gpg | apt-key add - 2>/dev/null \ && echo "deb https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ && apt-get update \ - && apt-get -y install --no-install-recommends yarn tmux locales \ + && apt-get -y install --no-install-recommends yarn tmux locales postgresql \ # # Install eslint globally && npm install -g eslint \ diff --git a/.eslintrc b/.eslintrc index 6242db30c..e4ff2e0f0 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,8 +1,18 @@ { - "plugins": ["node"], - "extends": ["standard", "eslint:recommended", "plugin:node/recommended"], + "plugins": [ + "node" + ], + "extends": [ + "standard", + "eslint:recommended", + "plugin:node/recommended" + ], + "ignorePatterns": [ + "**/*.ts" + ], "parserOptions": { - "ecmaVersion": 2017 + "ecmaVersion": 2017, + "sourceType": "module" }, "env": { "node": true, @@ -11,10 +21,13 @@ }, "rules": { "space-before-function-paren": "off", + "node/no-unsupported-features/es-syntax": "off", "node/no-unpublished-require": [ "error", { - "allowModules": ["pg"] + "allowModules": [ + "pg" + ] } ] } diff --git a/packages/pg-packet-stream/package.json b/packages/pg-packet-stream/package.json index 89027056b..06f218756 100644 --- a/packages/pg-packet-stream/package.json +++ b/packages/pg-packet-stream/package.json @@ -2,21 +2,20 @@ "name": "pg-packet-stream", "version": "1.0.0", "main": "dist/index.js", + "types": "dist/index.d.ts", "license": "MIT", "devDependencies": { "@types/node": "^12.12.21", "chunky": "^0.0.0", - "mocha": "^6.2.2", - "typescript": "^3.7.3" - }, - "scripts": { - "test": "mocha -r ts-node/register src/**/*.test.ts" - }, - "dependencies": { + "typescript": "^3.7.3", "@types/chai": "^4.2.7", "@types/mocha": "^5.2.7", "chai": "^4.2.0", "mocha": "^6.2.2", "ts-node": "^8.5.4" - } + }, + "scripts": { + "test": "mocha -r ts-node/register src/**/*.test.ts" + }, + "dependencies": {} } diff --git a/packages/pg-packet-stream/src/index.test.ts b/packages/pg-packet-stream/src/index.test.ts deleted file mode 100644 index 1962329c5..000000000 --- a/packages/pg-packet-stream/src/index.test.ts +++ /dev/null @@ -1,103 +0,0 @@ -import 'mocha'; -import { PgPacketStream, Packet } from './' -import { expect } from 'chai' -import chunky from 'chunky' - -const consume = async (stream: PgPacketStream, count: number): Promise => { - const result: Packet[] = []; - - return new Promise((resolve) => { - const read = () => { - stream.once('readable', () => { - let packet; - while (packet = stream.read()) { - result.push(packet) - } - if (result.length === count) { - resolve(result); - } else { - read() - } - - }) - } - read() - }) -} - -const emptyMessage = Buffer.from([0x0a, 0x00, 0x00, 0x00, 0x04]) -const oneByteMessage = Buffer.from([0x0b, 0x00, 0x00, 0x00, 0x05, 0x0a]) -const bigMessage = Buffer.from([0x0f, 0x00, 0x00, 0x00, 0x14, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e0, 0x0f]) - -describe.skip('PgPacketStream', () => { - it('should chunk a perfect input packet', async () => { - const stream = new PgPacketStream() - stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x04])) - stream.end() - const buffers = await consume(stream, 1) - expect(buffers).to.have.length(1) - expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x04])) - }); - - it('should read 2 chunks into perfect input packet', async () => { - const stream = new PgPacketStream() - stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x08])) - stream.write(Buffer.from([0x1, 0x2, 0x3, 0x4])) - stream.end() - const buffers = await consume(stream, 1) - expect(buffers).to.have.length(1) - expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x08, 0x1, 0x2, 0x3, 0x4])) - }); - - it('should read a bunch of big messages', async () => { - const stream = new PgPacketStream(); - let totalBuffer = Buffer.allocUnsafe(0); - const num = 2; - for (let i = 0; i < 2; i++) { - totalBuffer = Buffer.concat([totalBuffer, bigMessage, bigMessage]) - } - const chunks = chunky(totalBuffer) - for (const chunk of chunks) { - stream.write(chunk) - } - stream.end() - const messages = await consume(stream, num * 2) - expect(messages.map(x => x.code)).to.eql(new Array(num * 2).fill(0x0f)) - }) - - it('should read multiple messages in a single chunk', async () => { - const stream = new PgPacketStream() - stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x04])) - stream.end() - const buffers = await consume(stream, 2) - expect(buffers).to.have.length(2) - expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x04])) - expect(buffers[1].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x04])) - }); - - it('should read multiple chunks into multiple packets', async () => { - const stream = new PgPacketStream() - stream.write(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x05, 0x0a, 0x01, 0x00, 0x00, 0x00, 0x05, 0x0b])) - stream.write(Buffer.from([0x01, 0x00, 0x00])); - stream.write(Buffer.from([0x00, 0x06, 0x0c, 0x0d, 0x03, 0x00, 0x00, 0x00, 0x04])) - stream.end() - const buffers = await consume(stream, 4) - expect(buffers).to.have.length(4) - expect(buffers[0].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x05, 0x0a])) - expect(buffers[1].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x05, 0x0b])) - expect(buffers[2].packet).to.deep.equal(Buffer.from([0x1, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x0d])) - expect(buffers[3].packet).to.deep.equal(Buffer.from([0x3, 0x00, 0x00, 0x00, 0x04])) - }); - - it('reads packet that spans multiple chunks', async () => { - const stream = new PgPacketStream() - stream.write(Buffer.from([0x0d, 0x00, 0x00, 0x00])) - stream.write(Buffer.from([0x09])) // length - stream.write(Buffer.from([0x0a, 0x0b, 0x0c, 0x0d])) - stream.write(Buffer.from([0x0a, 0x0b, 0x0c, 0x0d])) - stream.write(Buffer.from([0x0a, 0x0b, 0x0c, 0x0d])) - stream.end() - const buffers = await consume(stream, 1) - expect(buffers).to.have.length(1) - }) -}); diff --git a/packages/pg-packet-stream/src/index.ts b/packages/pg-packet-stream/src/index.ts index dc2af4246..2bd2da69c 100644 --- a/packages/pg-packet-stream/src/index.ts +++ b/packages/pg-packet-stream/src/index.ts @@ -1,5 +1,5 @@ import { Transform, TransformCallback, TransformOptions } from 'stream'; -import { Mode, bindComplete, parseComplete, closeComplete, noData, portalSuspended, copyDone, replicationStart, emptyQuery, ReadyForQueryMessage, CommandCompleteMessage, CopyDataMessage, CopyResponse, NotificationResponseMessage, RowDescriptionMessage, Field, DataRowMessage, ParameterStatusMessage, BackendKeyDataMessage, DatabaseError, BackendMessage } from './messages'; +import { Mode, bindComplete, parseComplete, closeComplete, noData, portalSuspended, copyDone, replicationStart, emptyQuery, ReadyForQueryMessage, CommandCompleteMessage, CopyDataMessage, CopyResponse, NotificationResponseMessage, RowDescriptionMessage, Field, DataRowMessage, ParameterStatusMessage, BackendKeyDataMessage, DatabaseError, BackendMessage, MessageName, AuthenticationMD5Password } from './messages'; import { BufferReader } from './BufferReader'; import assert from 'assert' @@ -63,7 +63,12 @@ export class PgPacketStream extends Transform { } public _transform(buffer: Buffer, encoding: string, callback: TransformCallback) { - const combinedBuffer: Buffer = this.remainingBuffer.byteLength ? Buffer.concat([this.remainingBuffer, buffer], this.remainingBuffer.length + buffer.length) : buffer; + let combinedBuffer = buffer; + if (this.remainingBuffer.byteLength) { + combinedBuffer = Buffer.allocUnsafe(this.remainingBuffer.byteLength + buffer.byteLength); + this.remainingBuffer.copy(combinedBuffer) + buffer.copy(combinedBuffer, this.remainingBuffer.byteLength) + } let offset = 0; while ((offset + HEADER_LENGTH) <= combinedBuffer.byteLength) { // code is 1 byte long - it identifies the message type @@ -125,9 +130,9 @@ export class PgPacketStream extends Transform { case MessageCodes.BackendKeyData: return this.parseBackendKeyData(offset, length, bytes); case MessageCodes.ErrorMessage: - return this.parseErrorMessage(offset, length, bytes, 'error'); + return this.parseErrorMessage(offset, length, bytes, MessageName.error); case MessageCodes.NoticeMessage: - return this.parseErrorMessage(offset, length, bytes, 'notice'); + return this.parseErrorMessage(offset, length, bytes, MessageName.notice); case MessageCodes.RowDescriptionMessage: return this.parseRowDescriptionMessage(offset, length, bytes); case MessageCodes.CopyIn: @@ -142,7 +147,7 @@ export class PgPacketStream extends Transform { } public _flush(callback: TransformCallback) { - this._transform(Buffer.alloc(0), 'utf-i', callback) + this._transform(Buffer.alloc(0), 'utf-8', callback) } private parseReadyForQueryMessage(offset: number, length: number, bytes: Buffer) { @@ -163,14 +168,14 @@ export class PgPacketStream extends Transform { } private parseCopyInMessage(offset: number, length: number, bytes: Buffer) { - return this.parseCopyMessage(offset, length, bytes, 'copyInResponse') + return this.parseCopyMessage(offset, length, bytes, MessageName.copyInResponse) } private parseCopyOutMessage(offset: number, length: number, bytes: Buffer) { - return this.parseCopyMessage(offset, length, bytes, 'copyOutResponse') + return this.parseCopyMessage(offset, length, bytes, MessageName.copyOutResponse) } - private parseCopyMessage(offset: number, length: number, bytes: Buffer, messageName: string) { + private parseCopyMessage(offset: number, length: number, bytes: Buffer, messageName: MessageName) { this.reader.setBuffer(offset, bytes); const isBinary = this.reader.byte() !== 0; const columnCount = this.reader.int16() @@ -244,8 +249,8 @@ export class PgPacketStream extends Transform { this.reader.setBuffer(offset, bytes); const code = this.reader.int32() // TODO(bmc): maybe better types here - const message: any = { - name: 'authenticationOk', + const message: BackendMessage & any = { + name: MessageName.authenticationOk, length, }; @@ -254,17 +259,18 @@ export class PgPacketStream extends Transform { break; case 3: // AuthenticationCleartextPassword if (message.length === 8) { - message.name = 'authenticationCleartextPassword' + message.name = MessageName.authenticationCleartextPassword } break case 5: // AuthenticationMD5Password if (message.length === 12) { - message.name = 'authenticationMD5Password' - message.salt = this.reader.bytes(4); + message.name = MessageName.authenticationMD5Password + const salt = this.reader.bytes(4); + return new AuthenticationMD5Password(length, salt); } break case 10: // AuthenticationSASL - message.name = 'authenticationSASL' + message.name = MessageName.authenticationSASL message.mechanisms = [] let mechanism: string; do { @@ -276,11 +282,11 @@ export class PgPacketStream extends Transform { } while (mechanism) break; case 11: // AuthenticationSASLContinue - message.name = 'authenticationSASLContinue' + message.name = MessageName.authenticationSASLContinue message.data = this.reader.string(length - 4) break; case 12: // AuthenticationSASLFinal - message.name = 'authenticationSASLFinal' + message.name = MessageName.authenticationSASLFinal message.data = this.reader.string(length - 4) break; default: @@ -289,7 +295,7 @@ export class PgPacketStream extends Transform { return message; } - private parseErrorMessage(offset: number, length: number, bytes: Buffer, name: string) { + private parseErrorMessage(offset: number, length: number, bytes: Buffer, name: MessageName) { this.reader.setBuffer(offset, bytes); var fields: Record = {} var fieldType = this.reader.string(1) diff --git a/packages/pg-packet-stream/src/messages.ts b/packages/pg-packet-stream/src/messages.ts index 26013cf13..160eb3ffb 100644 --- a/packages/pg-packet-stream/src/messages.ts +++ b/packages/pg-packet-stream/src/messages.ts @@ -1,47 +1,76 @@ export type Mode = 'text' | 'binary'; -export type BackendMessage = { - name: string; +export const enum MessageName { + parseComplete = 'parseComplete', + bindComplete = 'bindComplete', + closeComplete = 'closeComplete', + noData = 'noData', + portalSuspended = 'portalSuspended', + replicationStart = 'replicationStart', + emptyQuery = 'emptyQuery', + copyDone = 'copyDone', + copyData = 'copyData', + rowDescription = 'rowDescription', + parameterStatus = 'parameterStatus', + backendKeyData = 'backendKeyData', + notification = 'notification', + readyForQuery = 'readyForQuery', + commandComplete = 'commandComplete', + dataRow = 'dataRow', + copyInResponse = 'copyInResponse', + copyOutResponse = 'copyOutResponse', + authenticationOk = 'authenticationOk', + authenticationMD5Password = 'authenticationMD5Password', + authenticationCleartextPassword = 'authenticationCleartextPassword', + authenticationSASL = 'authenticationSASL', + authenticationSASLContinue = 'authenticationSASLContinue', + authenticationSASLFinal = 'authenticationSASLFinal', + error = 'error', + notice = 'notice', +} + +export interface BackendMessage { + name: MessageName; length: number; } export const parseComplete: BackendMessage = { - name: 'parseComplete', + name: MessageName.parseComplete, length: 5, }; export const bindComplete: BackendMessage = { - name: 'bindComplete', + name: MessageName.bindComplete, length: 5, } export const closeComplete: BackendMessage = { - name: 'closeComplete', + name: MessageName.closeComplete, length: 5, } export const noData: BackendMessage = { - name: 'noData', + name: MessageName.noData, length: 5 } export const portalSuspended: BackendMessage = { - name: 'portalSuspended', + name: MessageName.portalSuspended, length: 5, } export const replicationStart: BackendMessage = { - name: 'replicationStart', + name: MessageName.replicationStart, length: 4, } export const emptyQuery: BackendMessage = { - name: 'emptyQuery', + name: MessageName.emptyQuery, length: 4, } export const copyDone: BackendMessage = { - name: 'copyDone', + name: MessageName.copyDone, length: 4, } @@ -62,13 +91,13 @@ export class DatabaseError extends Error { public file: string | undefined; public line: string | undefined; public routine: string | undefined; - constructor(message: string, public readonly length: number, public readonly name: string) { + constructor(message: string, public readonly length: number, public readonly name: MessageName) { super(message) } } export class CopyDataMessage { - public readonly name = 'copyData'; + public readonly name = MessageName.copyData; constructor(public readonly length: number, public readonly chunk: Buffer) { } @@ -76,7 +105,7 @@ export class CopyDataMessage { export class CopyResponse { public readonly columnTypes: number[]; - constructor(public readonly length: number, public readonly name: string, public readonly binary: boolean, columnCount: number) { + constructor(public readonly length: number, public readonly name: MessageName, public readonly binary: boolean, columnCount: number) { this.columnTypes = new Array(columnCount); } } @@ -87,7 +116,7 @@ export class Field { } export class RowDescriptionMessage { - public readonly name: string = 'rowDescription'; + public readonly name: MessageName = MessageName.rowDescription; public readonly fields: Field[]; constructor(public readonly length: number, public readonly fieldCount: number) { this.fields = new Array(this.fieldCount) @@ -95,39 +124,45 @@ export class RowDescriptionMessage { } export class ParameterStatusMessage { - public readonly name: string = 'parameterStatus'; + public readonly name: MessageName = MessageName.parameterStatus; constructor(public readonly length: number, public readonly parameterName: string, public readonly parameterValue: string) { } } +export class AuthenticationMD5Password implements BackendMessage { + public readonly name: MessageName = MessageName.authenticationMD5Password; + constructor(public readonly length: number, public readonly salt: Buffer) { + } +} + export class BackendKeyDataMessage { - public readonly name: string = 'backendKeyData'; + public readonly name: MessageName = MessageName.backendKeyData; constructor(public readonly length: number, public readonly processID: number, public readonly secretKey: number) { } } export class NotificationResponseMessage { - public readonly name: string = 'notification'; + public readonly name: MessageName = MessageName.notification; constructor(public readonly length: number, public readonly processId: number, public readonly channel: string, public readonly payload: string) { } } export class ReadyForQueryMessage { - public readonly name: string = 'readyForQuery'; + public readonly name: MessageName = MessageName.readyForQuery; constructor(public readonly length: number, public readonly status: string) { } } export class CommandCompleteMessage { - public readonly name: string = 'commandComplete' + public readonly name: MessageName = MessageName.commandComplete constructor(public readonly length: number, public readonly text: string) { } } export class DataRowMessage { public readonly fieldCount: number; - public readonly name: string = 'dataRow' + public readonly name: MessageName = MessageName.dataRow constructor(public length: number, public fields: any[]) { this.fieldCount = fields.length; } diff --git a/packages/pg-packet-stream/tsconfig.json b/packages/pg-packet-stream/tsconfig.json index f6661febd..bdbe07a39 100644 --- a/packages/pg-packet-stream/tsconfig.json +++ b/packages/pg-packet-stream/tsconfig.json @@ -10,6 +10,7 @@ "sourceMap": true, "outDir": "dist", "baseUrl": ".", + "declaration": true, "paths": { "*": [ "node_modules/*", From 89b451e934d307595c039bf08adb384a8720df7d Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 27 Dec 2019 03:15:51 +0000 Subject: [PATCH 0564/1037] Properly merge dockerfile --- .devcontainer/Dockerfile | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index ae2d0397f..d60b0cc49 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -32,11 +32,7 @@ RUN apt-get update \ && curl -sS https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/pubkey.gpg | apt-key add - 2>/dev/null \ && echo "deb https://dl.yarnpkg.com/$(lsb_release -is | tr '[:upper:]' '[:lower:]')/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ && apt-get update \ -<<<<<<< HEAD && apt-get -y install --no-install-recommends yarn tmux locales postgresql \ -======= - && apt-get -y install --no-install-recommends yarn tmux locales \ ->>>>>>> origin/master # # Install eslint globally && npm install -g eslint \ @@ -62,14 +58,11 @@ RUN curl https://raw.githubusercontent.com/brianc/dotfiles/master/.tmux.conf > ~ # install nvm RUN curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.2/install.sh | bash -<<<<<<< HEAD -======= # set up a nicer prompt RUN git clone https://github.com/magicmonty/bash-git-prompt.git ~/.bash-git-prompt --depth=1 RUN echo "source $HOME/.bash-git-prompt/gitprompt.sh" >> ~/.bashrc ->>>>>>> origin/master # Set the locale RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen ENV LANG en_US.UTF-8 From 6168f2ee0dc52f866250dca613170ce2f6747b49 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 27 Dec 2019 03:22:30 +0000 Subject: [PATCH 0565/1037] Disable lint on missing module since the file is not included --- packages/pg/lib/connection-fast.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index 29752df72..38f55bdcd 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -12,6 +12,7 @@ var EventEmitter = require('events').EventEmitter var util = require('util') var Writer = require('buffer-writer') +// eslint-disable-next-line var PacketStream = require('pg-packet-stream') var TEXT_MODE = 0 From 01e0644b9960482904cf32e99bc10dd222c47d74 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 27 Dec 2019 03:39:56 +0000 Subject: [PATCH 0566/1037] Add pretest and prepublish script --- packages/pg-packet-stream/package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/pg-packet-stream/package.json b/packages/pg-packet-stream/package.json index 06f218756..fcc42d74a 100644 --- a/packages/pg-packet-stream/package.json +++ b/packages/pg-packet-stream/package.json @@ -15,7 +15,9 @@ "ts-node": "^8.5.4" }, "scripts": { - "test": "mocha -r ts-node/register src/**/*.test.ts" + "test": "mocha dist/**/*.test.js", + "prepublish": "tsc", + "pretest": "tsc" }, "dependencies": {} } From 1cf64444ad3741a9ddc811e9860de6dcd9750e5e Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 27 Dec 2019 03:55:24 +0000 Subject: [PATCH 0567/1037] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d933854f..76a3aa492 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### 7.16.0 +- Add optional, opt-in behavior to test new, [faster query pipeline](https://github.com/brianc/node-postgres/pull/2044). This is experimental, and not documented yet. The pipeline changes will grow significantly after the 8.0 release. + ### 7.15.0 - Change repository structure to support lerna & future monorepo [development](https://github.com/brianc/node-postgres/pull/2014). From 69345eb96aa2552b288247960aa7126d41210eb6 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 27 Dec 2019 03:56:07 +0000 Subject: [PATCH 0568/1037] Publish - pg-cursor@2.1.0 - pg-packet-stream@1.1.0 - pg-query-stream@2.1.0 - pg@7.16.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-packet-stream/package.json | 13 ++++++------- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 13 insertions(+), 14 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 14d6387d8..397de6eb3 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.0.3", + "version": "2.1.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -21,7 +21,7 @@ "eslint-config-prettier": "^6.4.0", "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "^7.15.2", + "pg": "^7.16.0", "prettier": "^1.18.2" }, "prettier": { diff --git a/packages/pg-packet-stream/package.json b/packages/pg-packet-stream/package.json index fcc42d74a..9cc325274 100644 --- a/packages/pg-packet-stream/package.json +++ b/packages/pg-packet-stream/package.json @@ -1,23 +1,22 @@ { "name": "pg-packet-stream", - "version": "1.0.0", + "version": "1.1.0", "main": "dist/index.js", "types": "dist/index.d.ts", "license": "MIT", "devDependencies": { - "@types/node": "^12.12.21", - "chunky": "^0.0.0", - "typescript": "^3.7.3", "@types/chai": "^4.2.7", "@types/mocha": "^5.2.7", + "@types/node": "^12.12.21", "chai": "^4.2.0", + "chunky": "^0.0.0", "mocha": "^6.2.2", - "ts-node": "^8.5.4" + "ts-node": "^8.5.4", + "typescript": "^3.7.3" }, "scripts": { "test": "mocha dist/**/*.test.js", "prepublish": "tsc", "pretest": "tsc" - }, - "dependencies": {} + } } diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 97d064c7a..6bab12d09 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "2.0.2", + "version": "2.1.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -27,12 +27,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^6.2.2", - "pg": "^7.15.2", + "pg": "^7.16.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.0.3" + "pg-cursor": "^2.1.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index c4b549a18..147c10ccb 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.15.2", + "version": "7.16.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -22,7 +22,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "0.1.3", - "pg-packet-stream": "^1.0.0", + "pg-packet-stream": "^1.1.0", "pg-pool": "^2.0.7", "pg-types": "^2.1.0", "pgpass": "1.x", From 637bcf355cf266876f40671a094e97580796342c Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 27 Dec 2019 17:52:28 +0000 Subject: [PATCH 0569/1037] Cleanup things a bit --- README.md | 3 +- package.json | 3 +- packages/pg-cursor/.gitignore | 1 - packages/pg-cursor/Makefile | 15 - packages/pg-pool/.gitignore | 2 - packages/pg-pool/.travis.yml | 13 - packages/pg-pool/Makefile | 14 - packages/pg-pool/package-lock.json | 2106 ------------------- packages/pg-pool/package.json | 7 +- packages/pg-pool/test/connection-timeout.js | 8 +- packages/pg-pool/test/error-handling.js | 14 +- packages/pg-pool/yarn.lock | 1688 --------------- packages/pg-query-stream/.gitignore | 1 - packages/pg-query-stream/yarn.lock | 1627 -------------- yarn.lock | 68 +- 15 files changed, 78 insertions(+), 5492 deletions(-) delete mode 100644 packages/pg-cursor/.gitignore delete mode 100644 packages/pg-cursor/Makefile delete mode 100644 packages/pg-pool/.gitignore delete mode 100644 packages/pg-pool/.travis.yml delete mode 100644 packages/pg-pool/Makefile delete mode 100644 packages/pg-pool/package-lock.json delete mode 100644 packages/pg-pool/yarn.lock delete mode 100644 packages/pg-query-stream/.gitignore delete mode 100644 packages/pg-query-stream/yarn.lock diff --git a/README.md b/README.md index 7c5a90760..2207db8a1 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,10 @@ Non-blocking PostgreSQL client for Node.js. Pure JavaScript and optional native This repo is a monorepo which contains the core [pg](https://github.com/brianc/node-postgres/tree/master/packages/pg) module as well as a handful of related modules. - [pg](https://github.com/brianc/node-postgres/tree/master/packages/pg) +- [pg-pool](https://github.com/brianc/node-postgres/tree/master/packages/pg-pool) - [pg-cursor](https://github.com/brianc/node-postgres/tree/master/packages/pg-cursor) - [pg-query-stream](https://github.com/brianc/node-postgres/tree/master/packages/pg-query-stream) -_(more to come, I'm in the process of migrating repos over here)_ - ## Documenation diff --git a/package.json b/package.json index 59b21be2e..ce7f9f3b8 100644 --- a/package.json +++ b/package.json @@ -15,5 +15,6 @@ }, "devDependencies": { "lerna": "^3.19.0" - } + }, + "dependencies": {} } diff --git a/packages/pg-cursor/.gitignore b/packages/pg-cursor/.gitignore deleted file mode 100644 index 3c3629e64..000000000 --- a/packages/pg-cursor/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/packages/pg-cursor/Makefile b/packages/pg-cursor/Makefile deleted file mode 100644 index fea33ad64..000000000 --- a/packages/pg-cursor/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -.PHONY: test -test: - npm test - -.PHONY: patch -patch: test - npm version patch -m "Bump version" - git push origin master --tags - npm publish - -.PHONY: minor -minor: test - npm version minor -m "Bump version" - git push origin master --tags - npm publish diff --git a/packages/pg-pool/.gitignore b/packages/pg-pool/.gitignore deleted file mode 100644 index 93f136199..000000000 --- a/packages/pg-pool/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -node_modules -npm-debug.log diff --git a/packages/pg-pool/.travis.yml b/packages/pg-pool/.travis.yml deleted file mode 100644 index db2833db9..000000000 --- a/packages/pg-pool/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -language: node_js - -matrix: - include: - - node_js: "6" - addons: - postgresql: "9.4" - - node_js: "8" - addons: - postgresql: "9.6" - - node_js: "10" - addons: - postgresql: "9.6" diff --git a/packages/pg-pool/Makefile b/packages/pg-pool/Makefile deleted file mode 100644 index 8a7631426..000000000 --- a/packages/pg-pool/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -.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 diff --git a/packages/pg-pool/package-lock.json b/packages/pg-pool/package-lock.json deleted file mode 100644 index e1f089f91..000000000 --- a/packages/pg-pool/package-lock.json +++ /dev/null @@ -1,2106 +0,0 @@ -{ - "name": "pg-pool", - "version": "2.0.8", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "acorn": { - "version": "3.3.0", - "resolved": "http://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", - "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", - "dev": true - }, - "acorn-jsx": { - "version": "3.0.1", - "resolved": "http://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", - "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", - "dev": true, - "requires": { - "acorn": "^3.0.4" - } - }, - "acorn-to-esprima": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/acorn-to-esprima/-/acorn-to-esprima-2.0.8.tgz", - "integrity": "sha1-AD8MZC65ITL0F9NwjxStqCrfLrE=", - "dev": true - }, - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", - "dev": true, - "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" - } - }, - "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", - "dev": true - }, - "ansi-escapes": { - "version": "1.4.0", - "resolved": "http://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", - "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", - "dev": true - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "bluebird": { - "version": "3.4.1", - "resolved": "http://registry.npmjs.org/bluebird/-/bluebird-3.4.1.tgz", - "integrity": "sha1-tzHd9I4t077awudeEhWhG8uR+gc=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "dev": true - }, - "caller-path": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", - "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", - "dev": true, - "requires": { - "callsites": "^0.2.0" - } - }, - "callsites": { - "version": "0.2.0", - "resolved": "http://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", - "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - }, - "dependencies": { - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "circular-json": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", - "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", - "dev": true - }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "cli-width": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", - "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", - "dev": true - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "commander": { - "version": "2.15.1", - "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "config-chain": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", - "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", - "dev": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "core-js": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.0.tgz", - "integrity": "sha512-kLRC6ncVpuEW/1kwrOXYX6KQASCVtrh1gQr/UiaVgFlf9WE5Vp+lNe5+h3LuMr5PAucWnnEXwH0nQHRH/gpGtw==", - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "d": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, - "requires": { - "es5-ext": "^0.10.9" - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "debug-log": { - "version": "1.0.1", - "resolved": "http://registry.npmjs.org/debug-log/-/debug-log-1.0.1.tgz", - "integrity": "sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8=", - "dev": true - }, - "deep-is": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", - "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true - }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "^1.0.2" - } - }, - "deglob": { - "version": "1.1.2", - "resolved": "http://registry.npmjs.org/deglob/-/deglob-1.1.2.tgz", - "integrity": "sha1-dtV3wl/j9zKUEqK1nq3qV6xQDj8=", - "dev": true, - "requires": { - "find-root": "^1.0.0", - "glob": "^7.0.5", - "ignore": "^3.0.9", - "pkg-config": "^1.1.0", - "run-parallel": "^1.1.2", - "uniq": "^1.0.1", - "xtend": "^4.0.0" - }, - "dependencies": { - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "disparity": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/disparity/-/disparity-2.0.0.tgz", - "integrity": "sha1-V92stHMkrl9Y0swNqIbbTOnutxg=", - "dev": true, - "requires": { - "ansi-styles": "^2.0.1", - "diff": "^1.3.2" - }, - "dependencies": { - "diff": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-1.4.0.tgz", - "integrity": "sha1-fyjS657nsVqX79ic5j3P2qPMur8=", - "dev": true - } - } - }, - "doctrine": { - "version": "1.5.0", - "resolved": "http://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", - "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", - "dev": true, - "requires": { - "esutils": "^2.0.2", - "isarray": "^1.0.0" - } - }, - "editorconfig": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.13.3.tgz", - "integrity": "sha512-WkjsUNVCu+ITKDj73QDvi0trvpdDWdkDyHybDGSXPfekLCqwmpD7CP7iPbvBgosNuLcI96XTDwNa75JyFl7tEQ==", - "dev": true, - "requires": { - "bluebird": "^3.0.5", - "commander": "^2.9.0", - "lru-cache": "^3.2.0", - "semver": "^5.1.0", - "sigmund": "^1.0.1" - }, - "dependencies": { - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true - } - } - }, - "es5-ext": { - "version": "0.10.46", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", - "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "1" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-map": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", - "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-set": "~0.1.5", - "es6-symbol": "~3.1.1", - "event-emitter": "~0.3.5" - } - }, - "es6-set": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", - "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14", - "es6-iterator": "~2.0.1", - "es6-symbol": "3.1.1", - "event-emitter": "~0.3.5" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.14", - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "escape-string-regexp": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", - "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", - "dev": true - }, - "escope": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", - "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", - "dev": true, - "requires": { - "es6-map": "^0.1.3", - "es6-weak-map": "^2.0.1", - "esrecurse": "^4.1.0", - "estraverse": "^4.1.1" - } - }, - "esformatter": { - "version": "0.9.6", - "resolved": "https://registry.npmjs.org/esformatter/-/esformatter-0.9.6.tgz", - "integrity": "sha1-Ngiux4KN7uPNP0bhGSrrRyaKlX8=", - "dev": true, - "requires": { - "acorn-to-esprima": "^2.0.6", - "babel-traverse": "^6.4.5", - "debug": "^0.7.4", - "disparity": "^2.0.0", - "esformatter-parser": "^1.0.0", - "glob": "^5.0.3", - "minimist": "^1.1.1", - "mout": ">=0.9 <2.0", - "npm-run": "^2.0.0", - "resolve": "^1.1.5", - "rocambole": ">=0.7 <2.0", - "rocambole-indent": "^2.0.4", - "rocambole-linebreak": "^1.0.2", - "rocambole-node": "~1.0", - "rocambole-token": "^1.1.2", - "rocambole-whitespace": "^1.0.0", - "stdin": "*", - "strip-json-comments": "~0.1.1", - "supports-color": "^1.3.1", - "user-home": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", - "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=", - "dev": true - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "strip-json-comments": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-0.1.3.tgz", - "integrity": "sha1-Fkxk43Coo8wAyeAbU55WmCPw7lQ=", - "dev": true - }, - "supports-color": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-1.3.1.tgz", - "integrity": "sha1-FXWN8J2P87SswwdTn6vicJXhBC0=", - "dev": true - } - } - }, - "esformatter-eol-last": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esformatter-eol-last/-/esformatter-eol-last-1.0.0.tgz", - "integrity": "sha1-RaeP9GIrHUnkT1a0mQV2amMpDAc=", - "dev": true, - "requires": { - "string.prototype.endswith": "^0.2.0" - } - }, - "esformatter-ignore": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/esformatter-ignore/-/esformatter-ignore-0.1.3.tgz", - "integrity": "sha1-BNO4db+knd4ATMWN9va7w8BWfx4=", - "dev": true - }, - "esformatter-jsx": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/esformatter-jsx/-/esformatter-jsx-7.4.1.tgz", - "integrity": "sha1-siCa4JCPQTp0exIFcny/S6QklgI=", - "dev": true, - "requires": { - "babylon": "6.14.1", - "esformatter-ignore": "^0.1.3", - "extend": "3.0.0", - "js-beautify": "1.6.4" - }, - "dependencies": { - "babylon": { - "version": "6.14.1", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.14.1.tgz", - "integrity": "sha1-lWJ1+rcnU62bNDXXr+WPi/CimBU=", - "dev": true - } - } - }, - "esformatter-literal-notation": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esformatter-literal-notation/-/esformatter-literal-notation-1.0.1.tgz", - "integrity": "sha1-cQ57QgF1/j9+WvrVu60ykQOELi8=", - "dev": true, - "requires": { - "rocambole": "^0.3.6", - "rocambole-token": "^1.2.1" - }, - "dependencies": { - "esprima": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", - "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=", - "dev": true - }, - "rocambole": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/rocambole/-/rocambole-0.3.6.tgz", - "integrity": "sha1-Teu/WUMUS8e2AG2Vvo+swLdDUqc=", - "dev": true, - "requires": { - "esprima": "~1.0" - } - } - } - }, - "esformatter-parser": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/esformatter-parser/-/esformatter-parser-1.0.0.tgz", - "integrity": "sha1-CFQHLQSHU57TnK442KVDLBfsEdM=", - "dev": true, - "requires": { - "acorn-to-esprima": "^2.0.8", - "babel-traverse": "^6.9.0", - "babylon": "^6.8.0", - "rocambole": "^0.7.0" - } - }, - "esformatter-quotes": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/esformatter-quotes/-/esformatter-quotes-1.1.0.tgz", - "integrity": "sha1-4ixsRFx/MGBB2BybnlH8psv6yoI=", - "dev": true - }, - "esformatter-remove-trailing-commas": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/esformatter-remove-trailing-commas/-/esformatter-remove-trailing-commas-1.0.1.tgz", - "integrity": "sha1-k5diTB+qmA/E7Mfl6YE+tPK1gqc=", - "dev": true, - "requires": { - "rocambole-token": "^1.2.1" - } - }, - "esformatter-semicolon-first": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/esformatter-semicolon-first/-/esformatter-semicolon-first-1.2.0.tgz", - "integrity": "sha1-47US0dTgcxDqvKv1cnfqfIpW4kI=", - "dev": true, - "requires": { - "esformatter-parser": "^1.0", - "rocambole": ">=0.6.0 <2.0", - "rocambole-linebreak": "^1.0.2", - "rocambole-token": "^1.2.1" - } - }, - "esformatter-spaced-lined-comment": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esformatter-spaced-lined-comment/-/esformatter-spaced-lined-comment-2.0.1.tgz", - "integrity": "sha1-3F80B/k8KV4eVkRr00RWDaXm3Kw=", - "dev": true - }, - "eslint": { - "version": "2.10.2", - "resolved": "http://registry.npmjs.org/eslint/-/eslint-2.10.2.tgz", - "integrity": "sha1-sjCUgv7wQ9MgM2WjIShebM4Bw9c=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "concat-stream": "^1.4.6", - "debug": "^2.1.1", - "doctrine": "^1.2.1", - "es6-map": "^0.1.3", - "escope": "^3.6.0", - "espree": "3.1.4", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "file-entry-cache": "^1.1.1", - "glob": "^7.0.3", - "globals": "^9.2.0", - "ignore": "^3.1.2", - "imurmurhash": "^0.1.4", - "inquirer": "^0.12.0", - "is-my-json-valid": "^2.10.0", - "is-resolvable": "^1.0.0", - "js-yaml": "^3.5.1", - "json-stable-stringify": "^1.0.0", - "lodash": "^4.0.0", - "mkdirp": "^0.5.0", - "optionator": "^0.8.1", - "path-is-absolute": "^1.0.0", - "path-is-inside": "^1.0.1", - "pluralize": "^1.2.1", - "progress": "^1.1.8", - "require-uncached": "^1.0.2", - "shelljs": "^0.6.0", - "strip-json-comments": "~1.0.1", - "table": "^3.7.8", - "text-table": "~0.2.0", - "user-home": "^2.0.0" - }, - "dependencies": { - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "eslint-config-standard-jsx": { - "version": "1.2.1", - "resolved": "http://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-1.2.1.tgz", - "integrity": "sha1-DRmxcF8K1INj7yqLv6cd8BLZibM=", - "dev": true - }, - "eslint-plugin-promise": { - "version": "1.3.2", - "resolved": "http://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-1.3.2.tgz", - "integrity": "sha1-/OMy1vX/UjIApTdwSGPsPCQiunw=", - "dev": true - }, - "eslint-plugin-react": { - "version": "5.2.2", - "resolved": "http://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-5.2.2.tgz", - "integrity": "sha1-fbBo4fVIf2hx5N7vNqOBwwPqwWE=", - "dev": true, - "requires": { - "doctrine": "^1.2.2", - "jsx-ast-utils": "^1.2.1" - } - }, - "eslint-plugin-standard": { - "version": "1.3.3", - "resolved": "http://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-1.3.3.tgz", - "integrity": "sha1-owhUUVI0MedvQJxwy4+U4yvw7H8=", - "dev": true - }, - "espree": { - "version": "3.1.4", - "resolved": "http://registry.npmjs.org/espree/-/espree-3.1.4.tgz", - "integrity": "sha1-BybXrIOvl6fISY2ps2OjYJ0qaKE=", - "dev": true, - "requires": { - "acorn": "^3.1.0", - "acorn-jsx": "^3.0.0" - } - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "esrecurse": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", - "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", - "dev": true, - "requires": { - "estraverse": "^4.1.0" - } - }, - "estraverse": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", - "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "exit-hook": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", - "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", - "dev": true - }, - "expect.js": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/expect.js/-/expect.js-0.3.1.tgz", - "integrity": "sha1-sKWaDS7/VDdUTr8M6qYBWEHQm1s=", - "dev": true - }, - "extend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz", - "integrity": "sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ=", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "figures": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", - "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", - "dev": true, - "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" - }, - "dependencies": { - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - } - } - }, - "file-entry-cache": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-1.3.1.tgz", - "integrity": "sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g=", - "dev": true, - "requires": { - "flat-cache": "^1.2.1", - "object-assign": "^4.0.1" - } - }, - "find-root": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", - "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true - }, - "flat-cache": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", - "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", - "dev": true, - "requires": { - "circular-json": "^0.3.1", - "graceful-fs": "^4.1.2", - "rimraf": "~2.6.2", - "write": "^0.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "dev": true, - "requires": { - "is-property": "^1.0.2" - } - }, - "generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", - "dev": true, - "requires": { - "is-property": "^1.0.0" - } - }, - "get-stdin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", - "dev": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - }, - "graceful-fs": { - "version": "4.1.15", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz", - "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "he": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", - "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", - "dev": true - }, - "ignore": { - "version": "3.3.10", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", - "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", - "dev": true - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", - "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", - "dev": true - }, - "inquirer": { - "version": "0.12.0", - "resolved": "http://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", - "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", - "dev": true, - "requires": { - "ansi-escapes": "^1.1.0", - "ansi-regex": "^2.0.0", - "chalk": "^1.0.0", - "cli-cursor": "^1.0.1", - "cli-width": "^2.0.0", - "figures": "^1.3.5", - "lodash": "^4.3.0", - "readline2": "^1.0.1", - "run-async": "^0.1.0", - "rx-lite": "^3.1.2", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.0", - "through": "^2.3.6" - } - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-my-ip-valid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", - "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", - "dev": true - }, - "is-my-json-valid": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.19.0.tgz", - "integrity": "sha512-mG0f/unGX1HZ5ep4uhRaPOS8EkAY8/j6mDRMJrutq4CqhoJWYp7qAlonIPy3TV7p3ju4TK9fo/PbnoksWmsp5Q==", - "dev": true, - "requires": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "is-my-ip-valid": "^1.0.0", - "jsonpointer": "^4.0.0", - "xtend": "^4.0.0" - } - }, - "is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", - "dev": true - }, - "is-resolvable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", - "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "js-beautify": { - "version": "1.6.4", - "resolved": "http://registry.npmjs.org/js-beautify/-/js-beautify-1.6.4.tgz", - "integrity": "sha1-qa95aZdCrJobb93B/bx4vE1RX8M=", - "dev": true, - "requires": { - "config-chain": "~1.1.5", - "editorconfig": "^0.13.2", - "mkdirp": "~0.5.0", - "nopt": "~3.0.1" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "jsonpointer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", - "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", - "dev": true - }, - "jsx-ast-utils": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", - "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "lodash": { - "version": "4.17.13", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.13.tgz", - "integrity": "sha512-vm3/XWXfWtRua0FkUyEHBZy8kCPjErNBT9fJx8Zvs+U6zjqPbTUOpkaoum3O5uiA8sm+yNMHXfYkTUHFoMxFNA==", - "dev": true - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "lru-cache": { - "version": "3.2.0", - "resolved": "http://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", - "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", - "dev": true, - "requires": { - "pseudomap": "^1.0.1" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", - "dev": true, - "requires": { - "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - } - } - }, - "mout": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/mout/-/mout-1.1.0.tgz", - "integrity": "sha512-XsP0vf4As6BfqglxZqbqQ8SR6KQot2AgxvR0gG+WtUkf90vUXchMOZQtPf/Hml1rEffJupqL/tIrU6EYhsUQjw==", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "multiline": { - "version": "1.0.2", - "resolved": "http://registry.npmjs.org/multiline/-/multiline-1.0.2.tgz", - "integrity": "sha1-abHyX/B00oKJBPJE3dBrfZbvbJM=", - "dev": true, - "requires": { - "strip-indent": "^1.0.0" - } - }, - "mute-stream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", - "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", - "dev": true - }, - "next-tick": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "npm-path": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/npm-path/-/npm-path-1.1.0.tgz", - "integrity": "sha1-BHSuAEGcMn1UcBt88s0F3Ii+EUA=", - "dev": true, - "requires": { - "which": "^1.2.4" - } - }, - "npm-run": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/npm-run/-/npm-run-2.0.0.tgz", - "integrity": "sha1-KN/ArV4uRv4ISOK9WN3wAue3PBU=", - "dev": true, - "requires": { - "minimist": "^1.1.1", - "npm-path": "^1.0.1", - "npm-which": "^2.0.0", - "serializerr": "^1.0.1", - "spawn-sync": "^1.0.5", - "sync-exec": "^0.5.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "npm-which": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/npm-which/-/npm-which-2.0.0.tgz", - "integrity": "sha1-DEaYIWC3gwk2YdHQG9RJbS/qu6w=", - "dev": true, - "requires": { - "commander": "^2.2.0", - "npm-path": "^1.0.0", - "which": "^1.0.5" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "optionator": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", - "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" - } - }, - "os-homedir": { - "version": "1.0.2", - "resolved": "http://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", - "dev": true - }, - "os-shim": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/os-shim/-/os-shim-0.1.3.tgz", - "integrity": "sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc=", - "dev": true - }, - "packet-reader": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-0.3.1.tgz", - "integrity": "sha1-zWLmCvjX/qinBexP+ZCHHEaHHyc=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "http://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", - "dev": true - }, - "pg": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/pg/-/pg-7.7.1.tgz", - "integrity": "sha512-p3I0mXOmUvCoVlCMFW6iYSrnguPol6q8He15NGgSIdM3sPGjFc+8JGCeKclw8ZR4ETd+Jxy2KNiaPUcocHZeMw==", - "dev": true, - "requires": { - "buffer-writer": "2.0.0", - "packet-reader": "0.3.1", - "pg-connection-string": "0.1.3", - "pg-pool": "^2.0.4", - "pg-types": "~1.12.1", - "pgpass": "1.x", - "semver": "4.3.2" - } - }, - "pg-connection-string": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-0.1.3.tgz", - "integrity": "sha1-2hhHsglA5C7hSSvq9l1J2RskXfc=", - "dev": true - }, - "pg-cursor": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/pg-cursor/-/pg-cursor-1.3.0.tgz", - "integrity": "sha1-siDxkIl2t7QNqjc8etpfyoI6sNk=", - "dev": true - }, - "pg-pool": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-2.0.5.tgz", - "integrity": "sha512-T4W9qzP2LjItXuXbW6jgAF2AY0jHp6IoTxRhM3GB7yzfBxzDnA3GCm0sAduzmmiCybMqD0+V1HiqIG5X2YWqlQ==", - "dev": true - }, - "pg-types": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-1.12.1.tgz", - "integrity": "sha1-1kCH45A7WP+q0nnnWVxSIIoUw9I=", - "dev": true, - "requires": { - "postgres-array": "~1.0.0", - "postgres-bytea": "~1.0.0", - "postgres-date": "~1.0.0", - "postgres-interval": "^1.1.0" - } - }, - "pgpass": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", - "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", - "dev": true, - "requires": { - "split": "^1.0.0" - } - }, - "pkg-config": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pkg-config/-/pkg-config-1.1.1.tgz", - "integrity": "sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q=", - "dev": true, - "requires": { - "debug-log": "^1.0.0", - "find-root": "^1.0.0", - "xtend": "^4.0.1" - } - }, - "pluralize": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", - "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", - "dev": true - }, - "postgres-array": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-1.0.3.tgz", - "integrity": "sha512-5wClXrAP0+78mcsNX3/ithQ5exKvCyK5lr5NEEEeGwwM6NJdQgzIJBVxLvRW+huFpX92F2QnZ5CcokH0VhK2qQ==", - "dev": true - }, - "postgres-bytea": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", - "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=", - "dev": true - }, - "postgres-date": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.3.tgz", - "integrity": "sha1-4tiXAu/bJY/52c7g/pG9BpdSV6g=", - "dev": true - }, - "postgres-interval": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.1.2.tgz", - "integrity": "sha512-fC3xNHeTskCxL1dC8KOtxXt7YeFmlbTYtn7ul8MkVERuTmf7pI4DrkAxcw3kh1fQ9uz4wQmd03a1mRiXUZChfQ==", - "dev": true, - "requires": { - "xtend": "^4.0.0" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "progress": { - "version": "1.1.8", - "resolved": "http://registry.npmjs.org/progress/-/progress-1.1.8.tgz", - "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", - "dev": true - }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", - "dev": true - }, - "protochain": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/protochain/-/protochain-1.0.5.tgz", - "integrity": "sha1-mRxAfpneJkqt+PgVBLXn+ve/omA=", - "dev": true - }, - "pseudomap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", - "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readline2": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", - "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "mute-stream": "0.0.5" - } - }, - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "require-uncached": { - "version": "1.0.3", - "resolved": "http://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", - "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", - "dev": true, - "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" - } - }, - "resolve": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", - "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", - "dev": true, - "requires": { - "path-parse": "^1.0.5" - } - }, - "resolve-from": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", - "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", - "dev": true - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "^7.0.5" - }, - "dependencies": { - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "rocambole": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/rocambole/-/rocambole-0.7.0.tgz", - "integrity": "sha1-9seVBVF9xCtvuECEK4uVOw+WhYU=", - "dev": true, - "requires": { - "esprima": "^2.1" - }, - "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", - "dev": true - } - } - }, - "rocambole-indent": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/rocambole-indent/-/rocambole-indent-2.0.4.tgz", - "integrity": "sha1-oYokl3ygQAuGHapGMehh3LUtCFw=", - "dev": true, - "requires": { - "debug": "^2.1.3", - "mout": "^0.11.0", - "rocambole-token": "^1.2.1" - }, - "dependencies": { - "mout": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/mout/-/mout-0.11.1.tgz", - "integrity": "sha1-ujYR318OWx/7/QEWa48C0fX6K5k=", - "dev": true - } - } - }, - "rocambole-linebreak": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/rocambole-linebreak/-/rocambole-linebreak-1.0.2.tgz", - "integrity": "sha1-A2IVFbQ7RyHJflocG8paA2Y2jy8=", - "dev": true, - "requires": { - "debug": "^2.1.3", - "rocambole-token": "^1.2.1", - "semver": "^4.3.1" - } - }, - "rocambole-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rocambole-node/-/rocambole-node-1.0.0.tgz", - "integrity": "sha1-21tJ3nQHsAgN1RSHLyjjk9D3/z8=", - "dev": true - }, - "rocambole-token": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/rocambole-token/-/rocambole-token-1.2.1.tgz", - "integrity": "sha1-x4XfdCjcPLJ614lwR71SOMwHDTU=", - "dev": true - }, - "rocambole-whitespace": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rocambole-whitespace/-/rocambole-whitespace-1.0.0.tgz", - "integrity": "sha1-YzMJSSVrKZQfWbGQRZ+ZnGsdO/k=", - "dev": true, - "requires": { - "debug": "^2.1.3", - "repeat-string": "^1.5.0", - "rocambole-token": "^1.2.1" - } - }, - "run-async": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", - "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", - "dev": true, - "requires": { - "once": "^1.3.0" - } - }, - "run-parallel": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", - "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", - "dev": true - }, - "rx-lite": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", - "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", - "dev": true - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "semver": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", - "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=", - "dev": true - }, - "serializerr": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/serializerr/-/serializerr-1.0.3.tgz", - "integrity": "sha1-EtTFqhw/+49tHcXzlaqUVVacP5E=", - "dev": true, - "requires": { - "protochain": "^1.0.5" - } - }, - "shelljs": { - "version": "0.6.1", - "resolved": "http://registry.npmjs.org/shelljs/-/shelljs-0.6.1.tgz", - "integrity": "sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg=", - "dev": true - }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true - }, - "slice-ansi": { - "version": "0.0.4", - "resolved": "http://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true - }, - "spawn-sync": { - "version": "1.0.15", - "resolved": "https://registry.npmjs.org/spawn-sync/-/spawn-sync-1.0.15.tgz", - "integrity": "sha1-sAeZVX63+wyDdsKdROih6mfldHY=", - "dev": true, - "requires": { - "concat-stream": "^1.4.7", - "os-shim": "^0.1.2" - } - }, - "split": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", - "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", - "dev": true, - "requires": { - "through": "2" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "http://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "standard": { - "version": "7.1.2", - "resolved": "http://registry.npmjs.org/standard/-/standard-7.1.2.tgz", - "integrity": "sha1-QBZu7sJAUGXRpPDj8VurxuJ0YH4=", - "dev": true, - "requires": { - "eslint": "~2.10.2", - "eslint-config-standard": "5.3.1", - "eslint-config-standard-jsx": "1.2.1", - "eslint-plugin-promise": "^1.0.8", - "eslint-plugin-react": "^5.0.1", - "eslint-plugin-standard": "^1.3.1", - "standard-engine": "^4.0.0" - }, - "dependencies": { - "eslint-config-standard": { - "version": "5.3.1", - "resolved": "http://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-5.3.1.tgz", - "integrity": "sha1-WRyWkVF0QTL1YdO5FagS6kE/5JA=", - "dev": true - } - } - }, - "standard-engine": { - "version": "4.1.3", - "resolved": "http://registry.npmjs.org/standard-engine/-/standard-engine-4.1.3.tgz", - "integrity": "sha1-ejGq1U8D2fOTVfQzic4GlPQJQVU=", - "dev": true, - "requires": { - "defaults": "^1.0.2", - "deglob": "^1.0.0", - "find-root": "^1.0.0", - "get-stdin": "^5.0.1", - "minimist": "^1.1.0", - "multiline": "^1.0.2", - "pkg-config": "^1.0.1", - "xtend": "^4.0.0" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "standard-format": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/standard-format/-/standard-format-2.2.4.tgz", - "integrity": "sha1-uQ+zmmNfdJzU/RF/5HMNMRearu8=", - "dev": true, - "requires": { - "deglob": "^1.0.0", - "esformatter": "^0.9.0", - "esformatter-eol-last": "^1.0.0", - "esformatter-jsx": "^7.0.0", - "esformatter-literal-notation": "^1.0.0", - "esformatter-quotes": "^1.0.0", - "esformatter-remove-trailing-commas": "^1.0.1", - "esformatter-semicolon-first": "^1.1.0", - "esformatter-spaced-lined-comment": "^2.0.0", - "minimist": "^1.1.0", - "stdin": "0.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - } - } - }, - "stdin": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/stdin/-/stdin-0.0.1.tgz", - "integrity": "sha1-0wQZgarsPf28d6GzjWNy449ftx4=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string.prototype.endswith": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/string.prototype.endswith/-/string.prototype.endswith-0.2.0.tgz", - "integrity": "sha1-oZwg3uUamHd+mkfhDwm+OTubunU=", - "dev": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", - "dev": true, - "requires": { - "get-stdin": "^4.0.1" - }, - "dependencies": { - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - } - } - }, - "strip-json-comments": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-1.0.4.tgz", - "integrity": "sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E=", - "dev": true - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "sync-exec": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/sync-exec/-/sync-exec-0.5.0.tgz", - "integrity": "sha1-P3JY5KW6FyRTgZCfpqb2z1BuFmE=", - "dev": true - }, - "table": { - "version": "3.8.3", - "resolved": "http://registry.npmjs.org/table/-/table-3.8.3.tgz", - "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", - "dev": true, - "requires": { - "ajv": "^4.7.0", - "ajv-keywords": "^1.0.0", - "chalk": "^1.1.1", - "lodash": "^4.0.0", - "slice-ansi": "0.0.4", - "string-width": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - } - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "through": { - "version": "2.3.8", - "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "uniq": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", - "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", - "dev": true - }, - "user-home": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", - "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", - "dev": true, - "requires": { - "os-homedir": "^1.0.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", - "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", - "dev": true, - "requires": { - "mkdirp": "^0.5.1" - } - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - } - } -} diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 30f2bb2dc..5b8ebd038 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -7,7 +7,7 @@ "test": "test" }, "scripts": { - "test": " node_modules/.bin/mocha && node_modules/.bin/standard" + "test": " node_modules/.bin/mocha" }, "repository": { "type": "git", @@ -31,10 +31,7 @@ "expect.js": "0.3.1", "lodash": "^4.17.11", "mocha": "^5.2.0", - "pg": "*", - "pg-cursor": "^1.3.0", - "standard": "7.1.2", - "standard-format": "^2.2.4" + "pg-cursor": "^1.3.0" }, "dependencies": {}, "peerDependencies": { diff --git a/packages/pg-pool/test/connection-timeout.js b/packages/pg-pool/test/connection-timeout.js index 8151354cc..970785209 100644 --- a/packages/pg-pool/test/connection-timeout.js +++ b/packages/pg-pool/test/connection-timeout.js @@ -31,7 +31,7 @@ describe('connection timeout', () => { }) it('should callback with an error if timeout is passed', (done) => { - const pool = new Pool({ connectionTimeoutMillis: 10, port: this.port }) + const pool = new Pool({ connectionTimeoutMillis: 10, port: this.port, host: 'localhost' }) pool.connect((err, client, release) => { expect(err).to.be.an(Error) expect(err.message).to.contain('timeout') @@ -42,7 +42,7 @@ describe('connection timeout', () => { }) it('should reject promise with an error if timeout is passed', (done) => { - const pool = new Pool({ connectionTimeoutMillis: 10, port: this.port }) + const pool = new Pool({ connectionTimeoutMillis: 10, port: this.port, host: 'localhost' }) pool.connect().catch(err => { expect(err).to.be.an(Error) expect(err.message).to.contain('timeout') @@ -51,9 +51,9 @@ describe('connection timeout', () => { }) }) - it('should handle multiple timeouts', co.wrap(function * () { + it('should handle multiple timeouts', co.wrap(function* () { const errors = [] - const pool = new Pool({ connectionTimeoutMillis: 1, port: this.port }) + const pool = new Pool({ connectionTimeoutMillis: 1, port: this.port, host: 'localhost' }) for (var i = 0; i < 15; i++) { try { yield pool.connect() diff --git a/packages/pg-pool/test/error-handling.js b/packages/pg-pool/test/error-handling.js index 9ef8848ed..72d97ede0 100644 --- a/packages/pg-pool/test/error-handling.js +++ b/packages/pg-pool/test/error-handling.js @@ -13,7 +13,7 @@ describe('pool error handling', function () { const pool = new Pool() let errors = 0 let shouldGet = 0 - function runErrorQuery () { + function runErrorQuery() { shouldGet++ return new Promise(function (resolve, reject) { pool.query("SELECT 'asd'+1 ").then(function (res) { @@ -35,7 +35,7 @@ describe('pool error handling', function () { }) describe('calling release more than once', () => { - it('should throw each time', co.wrap(function * () { + it('should throw each time', co.wrap(function* () { const pool = new Pool() const client = yield pool.connect() client.release() @@ -60,7 +60,7 @@ describe('pool error handling', function () { }) describe('calling connect after end', () => { - it('should return an error', function * () { + 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') @@ -106,7 +106,7 @@ describe('pool error handling', function () { }) describe('error from idle client', () => { - it('removes client from pool', co.wrap(function * () { + it('removes client from pool', co.wrap(function* () { const pool = new Pool() const client = yield pool.connect() expect(pool.totalCount).to.equal(1) @@ -138,7 +138,7 @@ describe('pool error handling', function () { }) describe('error from in-use client', () => { - it('keeps the client in the pool', co.wrap(function * () { + it('keeps the client in the pool', co.wrap(function* () { const pool = new Pool() const client = yield pool.connect() expect(pool.totalCount).to.equal(1) @@ -182,7 +182,7 @@ describe('pool error handling', function () { }) describe('pool with lots of errors', () => { - it('continues to work and provide new clients', co.wrap(function * () { + 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++) { @@ -208,7 +208,7 @@ describe('pool error handling', function () { }).unref() closeServer.listen(() => { - const pool = new Pool({ max: 1, port: closeServer.address().port }) + const pool = new Pool({ max: 1, port: closeServer.address().port, host: 'localhost' }) pool.connect((err) => { expect(err).to.be.an(Error) if (err.errno) { diff --git a/packages/pg-pool/yarn.lock b/packages/pg-pool/yarn.lock deleted file mode 100644 index 5bdbcbacd..000000000 --- a/packages/pg-pool/yarn.lock +++ /dev/null @@ -1,1688 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -abbrev@1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" - integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== - -acorn-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - integrity sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s= - dependencies: - acorn "^3.0.4" - -acorn-to-esprima@^2.0.6, acorn-to-esprima@^2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/acorn-to-esprima/-/acorn-to-esprima-2.0.8.tgz#003f0c642eb92132f417d3708f14ada82adf2eb1" - integrity sha1-AD8MZC65ITL0F9NwjxStqCrfLrE= - -acorn@^3.0.4, acorn@^3.1.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - integrity sha1-ReN/s56No/JbruP/U2niu18iAXo= - -ajv-keywords@^1.0.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c" - integrity sha1-MU3QpLM2j609/NxU7eYXG4htrzw= - -ajv@^4.7.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" - integrity sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY= - dependencies: - co "^4.6.0" - json-stable-stringify "^1.0.1" - -ansi-escapes@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" - integrity sha1-06ioOzGapneTZisT52HHkRQiMG4= - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= - -ansi-styles@^2.0.1, ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha1-8830cDhYA1sqKVHG7F7fbGLyYw4= - dependencies: - babel-runtime "^6.22.0" - -babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha1-llxwWGaOgrVde/4E/yM3vItWR/4= - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-traverse@^6.4.5, babel-traverse@^6.9.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4= - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc= - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon@6.14.1: - version "6.14.1" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.14.1.tgz#956275fab72753ad9b3435d7afe58f8bf0a29815" - integrity sha1-lWJ1+rcnU62bNDXXr+WPi/CimBU= - -babylon@^6.18.0, babylon@^6.8.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= - -bluebird@3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.1.tgz#b731ddf48e2dd3bedac2e75e1215a11bcb91fa07" - integrity sha1-tzHd9I4t077awudeEhWhG8uR+gc= - -bluebird@^3.0.5: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== - -buffer-writer@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" - integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== - -caller-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - integrity sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8= - dependencies: - callsites "^0.2.0" - -callsites@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - integrity sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo= - -chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -circular-json@^0.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - integrity sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A== - -cli-cursor@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" - integrity sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc= - dependencies: - restore-cursor "^1.0.1" - -cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= - -clone@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" - integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= - -co@4.6.0, co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= - -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== - -commander@^2.2.0, commander@^2.9.0: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= - -concat-stream@^1.4.6, concat-stream@^1.4.7: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -config-chain@~1.1.5: - version "1.1.12" - resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa" - integrity sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA== - dependencies: - ini "^1.3.4" - proto-list "~1.2.1" - -core-js@^2.4.0: - version "2.6.11" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" - integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -d@1, d@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" - integrity sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA== - dependencies: - es5-ext "^0.10.50" - type "^1.0.1" - -debug-log@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" - integrity sha1-IwdjLUwEOCuN+KMvcLiVBG1SdF8= - -debug@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - -debug@^0.7.4: - version "0.7.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-0.7.4.tgz#06e1ea8082c2cb14e39806e22e2f6f757f92af39" - integrity sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk= - -debug@^2.1.1, debug@^2.1.3, debug@^2.6.8: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= - -defaults@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" - integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= - dependencies: - clone "^1.0.2" - -deglob@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/deglob/-/deglob-1.1.2.tgz#76d577c25fe3f7329412a2b59eadea57ac500e3f" - integrity sha1-dtV3wl/j9zKUEqK1nq3qV6xQDj8= - dependencies: - find-root "^1.0.0" - glob "^7.0.5" - ignore "^3.0.9" - pkg-config "^1.1.0" - run-parallel "^1.1.2" - uniq "^1.0.1" - xtend "^4.0.0" - -diff@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - -diff@^1.3.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-1.4.0.tgz#7f28d2eb9ee7b15a97efd89ce63dcfdaa3ccbabf" - integrity sha1-fyjS657nsVqX79ic5j3P2qPMur8= - -disparity@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/disparity/-/disparity-2.0.0.tgz#57ddacb47324ae5f58d2cc0da886db4ce9eeb718" - integrity sha1-V92stHMkrl9Y0swNqIbbTOnutxg= - dependencies: - ansi-styles "^2.0.1" - diff "^1.3.2" - -doctrine@^1.2.1, doctrine@^1.2.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= - dependencies: - esutils "^2.0.2" - isarray "^1.0.0" - -editorconfig@^0.13.2: - version "0.13.3" - resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.13.3.tgz#e5219e587951d60958fd94ea9a9a008cdeff1b34" - integrity sha512-WkjsUNVCu+ITKDj73QDvi0trvpdDWdkDyHybDGSXPfekLCqwmpD7CP7iPbvBgosNuLcI96XTDwNa75JyFl7tEQ== - dependencies: - bluebird "^3.0.5" - commander "^2.9.0" - lru-cache "^3.2.0" - semver "^5.1.0" - sigmund "^1.0.1" - -es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@~0.10.14: - version "0.10.53" - resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.53.tgz#93c5a3acfdbef275220ad72644ad02ee18368de1" - integrity sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q== - dependencies: - es6-iterator "~2.0.3" - es6-symbol "~3.1.3" - next-tick "~1.0.0" - -es6-iterator@^2.0.3, es6-iterator@~2.0.1, es6-iterator@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-iterator/-/es6-iterator-2.0.3.tgz#a7de889141a05a94b0854403b2d0a0fbfa98f3b7" - integrity sha1-p96IkUGgWpSwhUQDstCg+/qY87c= - dependencies: - d "1" - es5-ext "^0.10.35" - es6-symbol "^3.1.1" - -es6-map@^0.1.3: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-map/-/es6-map-0.1.5.tgz#9136e0503dcc06a301690f0bb14ff4e364e949f0" - integrity sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA= - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-set "~0.1.5" - es6-symbol "~3.1.1" - event-emitter "~0.3.5" - -es6-set@~0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/es6-set/-/es6-set-0.1.5.tgz#d2b3ec5d4d800ced818db538d28974db0a73ccb1" - integrity sha1-0rPsXU2ADO2BjbU40ol02wpzzLE= - dependencies: - d "1" - es5-ext "~0.10.14" - es6-iterator "~2.0.1" - es6-symbol "3.1.1" - event-emitter "~0.3.5" - -es6-symbol@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.1.tgz#bf00ef4fdab6ba1b46ecb7b629b4c7ed5715cc77" - integrity sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc= - dependencies: - d "1" - es5-ext "~0.10.14" - -es6-symbol@^3.1.1, es6-symbol@~3.1.1, es6-symbol@~3.1.3: - version "3.1.3" - resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.3.tgz#bad5d3c1bcdac28269f4cb331e431c78ac705d18" - integrity sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA== - dependencies: - d "^1.0.1" - ext "^1.1.2" - -es6-weak-map@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es6-weak-map/-/es6-weak-map-2.0.3.tgz#b6da1f16cc2cc0d9be43e6bdbfc5e7dfcdf31d53" - integrity sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA== - dependencies: - d "1" - es5-ext "^0.10.46" - es6-iterator "^2.0.3" - es6-symbol "^3.1.1" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escope@^3.6.0: - version "3.6.0" - resolved "https://registry.yarnpkg.com/escope/-/escope-3.6.0.tgz#e01975e812781a163a6dadfdd80398dc64c889c3" - integrity sha1-4Bl16BJ4GhY6ba392AOY3GTIicM= - dependencies: - es6-map "^0.1.3" - es6-weak-map "^2.0.1" - esrecurse "^4.1.0" - estraverse "^4.1.1" - -esformatter-eol-last@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/esformatter-eol-last/-/esformatter-eol-last-1.0.0.tgz#45a78ff4622b1d49e44f56b49905766a63290c07" - integrity sha1-RaeP9GIrHUnkT1a0mQV2amMpDAc= - dependencies: - string.prototype.endswith "^0.2.0" - -esformatter-ignore@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/esformatter-ignore/-/esformatter-ignore-0.1.3.tgz#04d3b875bfa49dde004cc58df6f6bbc3c0567f1e" - integrity sha1-BNO4db+knd4ATMWN9va7w8BWfx4= - -esformatter-jsx@^7.0.0: - version "7.4.1" - resolved "https://registry.yarnpkg.com/esformatter-jsx/-/esformatter-jsx-7.4.1.tgz#b2209ae0908f413a747b1205727cbf4ba4249602" - integrity sha1-siCa4JCPQTp0exIFcny/S6QklgI= - dependencies: - babylon "6.14.1" - esformatter-ignore "^0.1.3" - extend "3.0.0" - js-beautify "1.6.4" - -esformatter-literal-notation@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esformatter-literal-notation/-/esformatter-literal-notation-1.0.1.tgz#710e7b420175fe3f7e5afad5bbad329103842e2f" - integrity sha1-cQ57QgF1/j9+WvrVu60ykQOELi8= - dependencies: - rocambole "^0.3.6" - rocambole-token "^1.2.1" - -esformatter-parser@^1.0, esformatter-parser@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/esformatter-parser/-/esformatter-parser-1.0.0.tgz#0854072d0487539ed39cae38d8a5432c17ec11d3" - integrity sha1-CFQHLQSHU57TnK442KVDLBfsEdM= - dependencies: - acorn-to-esprima "^2.0.8" - babel-traverse "^6.9.0" - babylon "^6.8.0" - rocambole "^0.7.0" - -esformatter-quotes@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/esformatter-quotes/-/esformatter-quotes-1.1.0.tgz#e22c6c445c7f306041d81c9b9e51fca6cbfaca82" - integrity sha1-4ixsRFx/MGBB2BybnlH8psv6yoI= - -esformatter-remove-trailing-commas@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esformatter-remove-trailing-commas/-/esformatter-remove-trailing-commas-1.0.1.tgz#9397624c1faa980fc4ecc7e5e9813eb4f2b582a7" - integrity sha1-k5diTB+qmA/E7Mfl6YE+tPK1gqc= - dependencies: - rocambole-token "^1.2.1" - -esformatter-semicolon-first@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/esformatter-semicolon-first/-/esformatter-semicolon-first-1.2.0.tgz#e3b512d1d4e07310eabcabf57277ea7c8a56e242" - integrity sha1-47US0dTgcxDqvKv1cnfqfIpW4kI= - dependencies: - esformatter-parser "^1.0" - rocambole ">=0.6.0 <2.0" - rocambole-linebreak "^1.0.2" - rocambole-token "^1.2.1" - -esformatter-spaced-lined-comment@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/esformatter-spaced-lined-comment/-/esformatter-spaced-lined-comment-2.0.1.tgz#dc5f3407f93c295e1e56446bd344560da5e6dcac" - integrity sha1-3F80B/k8KV4eVkRr00RWDaXm3Kw= - -esformatter@^0.9.0: - version "0.9.6" - resolved "https://registry.yarnpkg.com/esformatter/-/esformatter-0.9.6.tgz#3608aec7828deee3cd3f46e1192aeb47268a957f" - integrity sha1-Ngiux4KN7uPNP0bhGSrrRyaKlX8= - dependencies: - acorn-to-esprima "^2.0.6" - babel-traverse "^6.4.5" - debug "^0.7.4" - disparity "^2.0.0" - esformatter-parser "^1.0.0" - glob "^5.0.3" - minimist "^1.1.1" - mout ">=0.9 <2.0" - npm-run "^2.0.0" - resolve "^1.1.5" - rocambole ">=0.7 <2.0" - rocambole-indent "^2.0.4" - rocambole-linebreak "^1.0.2" - rocambole-node "~1.0" - rocambole-token "^1.1.2" - rocambole-whitespace "^1.0.0" - stdin "*" - strip-json-comments "~0.1.1" - supports-color "^1.3.1" - user-home "^2.0.0" - -eslint-config-standard-jsx@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/eslint-config-standard-jsx/-/eslint-config-standard-jsx-1.2.1.tgz#0d19b1705f0ad48363ef2a8bbfa71df012d989b3" - integrity sha1-DRmxcF8K1INj7yqLv6cd8BLZibM= - -eslint-config-standard@5.3.1: - version "5.3.1" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-5.3.1.tgz#591c969151744132f561d3b915a812ea413fe490" - integrity sha1-WRyWkVF0QTL1YdO5FagS6kE/5JA= - -eslint-plugin-promise@^1.0.8: - version "1.3.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-1.3.2.tgz#fce332d6f5ff523200a537704863ec3c2422ba7c" - integrity sha1-/OMy1vX/UjIApTdwSGPsPCQiunw= - -eslint-plugin-react@^5.0.1: - version "5.2.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-5.2.2.tgz#7db068e1f5487f6871e4deef36a381c303eac161" - integrity sha1-fbBo4fVIf2hx5N7vNqOBwwPqwWE= - dependencies: - doctrine "^1.2.2" - jsx-ast-utils "^1.2.1" - -eslint-plugin-standard@^1.3.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-1.3.3.tgz#a3085451523431e76f409c70cb8f94e32bf0ec7f" - integrity sha1-owhUUVI0MedvQJxwy4+U4yvw7H8= - -eslint@~2.10.2: - version "2.10.2" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-2.10.2.tgz#b2309482fef043d3203365a321285e6cce01c3d7" - integrity sha1-sjCUgv7wQ9MgM2WjIShebM4Bw9c= - dependencies: - chalk "^1.1.3" - concat-stream "^1.4.6" - debug "^2.1.1" - doctrine "^1.2.1" - es6-map "^0.1.3" - escope "^3.6.0" - espree "3.1.4" - estraverse "^4.2.0" - esutils "^2.0.2" - file-entry-cache "^1.1.1" - glob "^7.0.3" - globals "^9.2.0" - ignore "^3.1.2" - imurmurhash "^0.1.4" - inquirer "^0.12.0" - is-my-json-valid "^2.10.0" - is-resolvable "^1.0.0" - js-yaml "^3.5.1" - json-stable-stringify "^1.0.0" - lodash "^4.0.0" - mkdirp "^0.5.0" - optionator "^0.8.1" - path-is-absolute "^1.0.0" - path-is-inside "^1.0.1" - pluralize "^1.2.1" - progress "^1.1.8" - require-uncached "^1.0.2" - shelljs "^0.6.0" - strip-json-comments "~1.0.1" - table "^3.7.8" - text-table "~0.2.0" - user-home "^2.0.0" - -espree@3.1.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.1.4.tgz#0726d7ac83af97a7c8498da9b363a3609d2a68a1" - integrity sha1-BybXrIOvl6fISY2ps2OjYJ0qaKE= - dependencies: - acorn "^3.1.0" - acorn-jsx "^3.0.0" - -esprima@^2.1: - version "2.7.3" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" - integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esprima@~1.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.0.4.tgz#9f557e08fc3b4d26ece9dd34f8fbf476b62585ad" - integrity sha1-n1V+CPw7TSbs6d00+Pv0drYlha0= - -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== - dependencies: - estraverse "^4.1.0" - -estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" - integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== - -esutils@^2.0.2: - version "2.0.3" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" - integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== - -event-emitter@~0.3.5: - version "0.3.5" - resolved "https://registry.yarnpkg.com/event-emitter/-/event-emitter-0.3.5.tgz#df8c69eef1647923c7157b9ce83840610b02cc39" - integrity sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk= - dependencies: - d "1" - es5-ext "~0.10.14" - -exit-hook@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" - integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g= - -expect.js@0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/expect.js/-/expect.js-0.3.1.tgz#b0a59a0d2eff5437544ebf0ceaa6015841d09b5b" - integrity sha1-sKWaDS7/VDdUTr8M6qYBWEHQm1s= - -ext@^1.1.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/ext/-/ext-1.4.0.tgz#89ae7a07158f79d35517882904324077e4379244" - integrity sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A== - dependencies: - type "^2.0.0" - -extend@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.0.tgz#5a474353b9f3353ddd8176dfd37b91c83a46f1d4" - integrity sha1-WkdDU7nzNT3dgXbf03uRyDpG8dQ= - -fast-levenshtein@~2.0.6: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= - -figures@^1.3.5: - version "1.7.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" - integrity sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4= - dependencies: - escape-string-regexp "^1.0.5" - object-assign "^4.1.0" - -file-entry-cache@^1.1.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-1.3.1.tgz#44c61ea607ae4be9c1402f41f44270cbfe334ff8" - integrity sha1-RMYepgeuS+nBQC9B9EJwy/4zT/g= - dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" - -find-root@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4" - integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng== - -flat-cache@^1.2.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.3.4.tgz#2c2ef77525cc2929007dfffa1dd314aa9c9dee6f" - integrity sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg== - dependencies: - circular-json "^0.3.1" - graceful-fs "^4.1.2" - rimraf "~2.6.2" - write "^0.2.1" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= - -generate-function@^2.0.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" - integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== - dependencies: - is-property "^1.0.2" - -generate-object-property@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/generate-object-property/-/generate-object-property-1.2.0.tgz#9c0e1c40308ce804f4783618b937fa88f99d50d0" - integrity sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA= - dependencies: - is-property "^1.0.0" - -get-stdin@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" - integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= - -get-stdin@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-5.0.1.tgz#122e161591e21ff4c52530305693f20e6393a398" - integrity sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g= - -glob@7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^5.0.3: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= - dependencies: - inflight "^1.0.4" - inherits "2" - minimatch "2 || 3" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.3, glob@^7.0.5, glob@^7.1.3: - version "7.1.6" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" - integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^9.18.0, globals@^9.2.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== - -graceful-fs@^4.1.2: - version "4.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" - integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= - dependencies: - ansi-regex "^2.0.0" - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= - -ignore@^3.0.9, ignore@^3.1.2: - version "3.3.10" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" - integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.3, inherits@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ini@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== - -inquirer@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-0.12.0.tgz#1ef2bfd63504df0bc75785fff8c2c41df12f077e" - integrity sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34= - dependencies: - ansi-escapes "^1.1.0" - ansi-regex "^2.0.0" - chalk "^1.0.0" - cli-cursor "^1.0.1" - cli-width "^2.0.0" - figures "^1.3.5" - lodash "^4.3.0" - readline2 "^1.0.1" - run-async "^0.1.0" - rx-lite "^3.1.2" - string-width "^1.0.1" - strip-ansi "^3.0.0" - through "^2.3.6" - -invariant@^2.2.2: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= - -is-my-ip-valid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz#7b351b8e8edd4d3995d4d066680e664d94696824" - integrity sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ== - -is-my-json-valid@^2.10.0: - version "2.20.0" - resolved "https://registry.yarnpkg.com/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz#1345a6fca3e8daefc10d0fa77067f54cedafd59a" - integrity sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA== - dependencies: - generate-function "^2.0.0" - generate-object-property "^1.1.0" - is-my-ip-valid "^1.0.0" - jsonpointer "^4.0.0" - xtend "^4.0.0" - -is-property@^1.0.0, is-property@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" - integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= - -is-resolvable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== - -isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= - -js-beautify@1.6.4: - version "1.6.4" - resolved "https://registry.yarnpkg.com/js-beautify/-/js-beautify-1.6.4.tgz#a9af79699742ac9a1b6fddc1fdbc78bc4d515fc3" - integrity sha1-qa95aZdCrJobb93B/bx4vE1RX8M= - dependencies: - config-chain "~1.1.5" - editorconfig "^0.13.2" - mkdirp "~0.5.0" - nopt "~3.0.1" - -"js-tokens@^3.0.0 || ^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= - -js-yaml@^3.5.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -json-stable-stringify@^1.0.0, json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= - dependencies: - jsonify "~0.0.0" - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= - -jsonpointer@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9" - integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk= - -jsx-ast-utils@^1.2.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1" - integrity sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE= - -levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -lodash@^4.0.0, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.3.0: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -lru-cache@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-3.2.0.tgz#71789b3b7f5399bec8565dda38aa30d2a097efee" - integrity sha1-cXibO39Tmb7IVl3aOKow0qCX7+4= - dependencies: - pseudomap "^1.0.1" - -"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.1.0, minimist@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" - -mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== - dependencies: - browser-stdout "1.3.1" - commander "2.15.1" - debug "3.1.0" - diff "3.5.0" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.5" - he "1.1.1" - minimatch "3.0.4" - mkdirp "0.5.1" - supports-color "5.4.0" - -"mout@>=0.9 <2.0": - version "1.2.2" - resolved "https://registry.yarnpkg.com/mout/-/mout-1.2.2.tgz#c9b718a499806a0632cede178e80f436259e777d" - integrity sha512-w0OUxFEla6z3d7sVpMZGBCpQvYh8PHS1wZ6Wu9GNKHMpAHWJ0if0LsQZh3DlOqw55HlhJEOMLpFnwtxp99Y5GA== - -mout@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/mout/-/mout-0.11.1.tgz#ba3611df5f0e5b1ffbfd01166b8f02d1f5fa2b99" - integrity sha1-ujYR318OWx/7/QEWa48C0fX6K5k= - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -multiline@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/multiline/-/multiline-1.0.2.tgz#69b1f25ff074d2828904f244ddd06b7d96ef6c93" - integrity sha1-abHyX/B00oKJBPJE3dBrfZbvbJM= - dependencies: - strip-indent "^1.0.0" - -mute-stream@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.5.tgz#8fbfabb0a98a253d3184331f9e8deb7372fac6c0" - integrity sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA= - -next-tick@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c" - integrity sha1-yobR/ogoFpsBICCOPchCS524NCw= - -nopt@~3.0.1: - version "3.0.6" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" - integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= - dependencies: - abbrev "1" - -npm-path@^1.0.0, npm-path@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/npm-path/-/npm-path-1.1.0.tgz#0474ae00419c327d54701b7cf2cd05dc88be1140" - integrity sha1-BHSuAEGcMn1UcBt88s0F3Ii+EUA= - dependencies: - which "^1.2.4" - -npm-run@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/npm-run/-/npm-run-2.0.0.tgz#28dfc0ad5e2e46fe0848e2bd58ddf002e7b73c15" - integrity sha1-KN/ArV4uRv4ISOK9WN3wAue3PBU= - dependencies: - minimist "^1.1.1" - npm-path "^1.0.1" - npm-which "^2.0.0" - serializerr "^1.0.1" - spawn-sync "^1.0.5" - sync-exec "^0.5.0" - -npm-which@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/npm-which/-/npm-which-2.0.0.tgz#0c46982160b783093661d1d01bd4496d2feabbac" - integrity sha1-DEaYIWC3gwk2YdHQG9RJbS/qu6w= - dependencies: - commander "^2.2.0" - npm-path "^1.0.0" - which "^1.0.5" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= - -object-assign@^4.0.1, object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= - dependencies: - wrappy "1" - -onetime@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" - integrity sha1-ofeDj4MUxRbwXs78vEzP4EtO14k= - -optionator@^0.8.1: - version "0.8.3" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" - integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.6" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - word-wrap "~1.2.3" - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= - -os-shim@^0.1.2: - version "0.1.3" - resolved "https://registry.yarnpkg.com/os-shim/-/os-shim-0.1.3.tgz#6b62c3791cf7909ea35ed46e17658bb417cb3917" - integrity sha1-a2LDeRz3kJ6jXtRuF2WLtBfLORc= - -packet-reader@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" - integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= - -path-is-inside@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= - -path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== - -pg-connection-string@0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" - integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc= - -pg-cursor@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/pg-cursor/-/pg-cursor-1.3.0.tgz#b220f1908976b7b40daa373c7ada5fca823ab0d9" - integrity sha1-siDxkIl2t7QNqjc8etpfyoI6sNk= - -pg-int8@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" - integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== - -pg-pool@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.7.tgz#f14ecab83507941062c313df23f6adcd9fd0ce54" - integrity sha512-UiJyO5B9zZpu32GSlP0tXy8J2NsJ9EFGFfz5v6PSbdz/1hBLX1rNiiy5+mAm5iJJYwfCv4A0EBcQLGWwjbpzZw== - -pg-types@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" - integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== - dependencies: - pg-int8 "1.0.1" - postgres-array "~2.0.0" - postgres-bytea "~1.0.0" - postgres-date "~1.0.4" - postgres-interval "^1.1.0" - -pg@*: - version "7.15.1" - resolved "https://registry.yarnpkg.com/pg/-/pg-7.15.1.tgz#a0bac84ebaeb809f3a369fb695ae89b314b08b22" - integrity sha512-o293Pxx5bNRpTv3Dh4+IIhPbTw19Bo4zvppLgR+MAV2I7AF3sMr9gPB4JPvBffWb24pDfC+7Ghe6xh2VxVMBpQ== - dependencies: - buffer-writer "2.0.0" - packet-reader "1.0.0" - pg-connection-string "0.1.3" - pg-pool "^2.0.7" - pg-types "^2.1.0" - pgpass "1.x" - semver "4.3.2" - -pgpass@1.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" - integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY= - dependencies: - split "^1.0.0" - -pkg-config@^1.0.1, pkg-config@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/pkg-config/-/pkg-config-1.1.1.tgz#557ef22d73da3c8837107766c52eadabde298fe4" - integrity sha1-VX7yLXPaPIg3EHdmxS6tq94pj+Q= - dependencies: - debug-log "^1.0.0" - find-root "^1.0.0" - xtend "^4.0.1" - -pluralize@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" - integrity sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU= - -postgres-array@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" - integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== - -postgres-bytea@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" - integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU= - -postgres-date@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.4.tgz#1c2728d62ef1bff49abdd35c1f86d4bdf118a728" - integrity sha512-bESRvKVuTrjoBluEcpv2346+6kgB7UlnqWZsnbnCccTNq/pqfj1j6oBaN5+b/NrDXepYUT/HKadqv3iS9lJuVA== - -postgres-interval@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695" - integrity sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ== - dependencies: - xtend "^4.0.0" - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= - -process-nextick-args@~2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" - integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== - -progress@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" - integrity sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74= - -proto-list@~1.2.1: - version "1.2.4" - resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" - integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= - -protochain@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/protochain/-/protochain-1.0.5.tgz#991c407e99de264aadf8f81504b5e7faf7bfa260" - integrity sha1-mRxAfpneJkqt+PgVBLXn+ve/omA= - -pseudomap@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= - -readable-stream@^2.2.2: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readline2@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/readline2/-/readline2-1.0.1.tgz#41059608ffc154757b715d9989d199ffbf372e35" - integrity sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - mute-stream "0.0.5" - -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - -repeat-string@^1.5.0: - version "1.6.1" - resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= - -require-uncached@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - integrity sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM= - dependencies: - caller-path "^0.1.0" - resolve-from "^1.0.0" - -resolve-from@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - integrity sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY= - -resolve@^1.1.5: - version "1.14.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.1.tgz#9e018c540fcf0c427d678b9931cbf45e984bcaff" - integrity sha512-fn5Wobh4cxbLzuHaE+nphztHy43/b++4M6SsGFC2gB8uYwf0C8LcarfCz1un7UTW8OFQg9iNjZ4xpcFVGebDPg== - dependencies: - path-parse "^1.0.6" - -restore-cursor@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" - integrity sha1-NGYfRohjJ/7SmRR5FSJS35LapUE= - dependencies: - exit-hook "^1.0.0" - onetime "^1.0.0" - -rimraf@~2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" - integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== - dependencies: - glob "^7.1.3" - -rocambole-indent@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/rocambole-indent/-/rocambole-indent-2.0.4.tgz#a18a24977ca0400b861daa4631e861dcb52d085c" - integrity sha1-oYokl3ygQAuGHapGMehh3LUtCFw= - dependencies: - debug "^2.1.3" - mout "^0.11.0" - rocambole-token "^1.2.1" - -rocambole-linebreak@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/rocambole-linebreak/-/rocambole-linebreak-1.0.2.tgz#03621515b43b4721c97e5a1c1bca5a0366368f2f" - integrity sha1-A2IVFbQ7RyHJflocG8paA2Y2jy8= - dependencies: - debug "^2.1.3" - rocambole-token "^1.2.1" - semver "^4.3.1" - -rocambole-node@~1.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/rocambole-node/-/rocambole-node-1.0.0.tgz#db5b49de7407b0080dd514872f28e393d0f7ff3f" - integrity sha1-21tJ3nQHsAgN1RSHLyjjk9D3/z8= - -rocambole-token@^1.1.2, rocambole-token@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/rocambole-token/-/rocambole-token-1.2.1.tgz#c785df7428dc3cb27ad7897047bd5238cc070d35" - integrity sha1-x4XfdCjcPLJ614lwR71SOMwHDTU= - -rocambole-whitespace@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/rocambole-whitespace/-/rocambole-whitespace-1.0.0.tgz#63330949256b29941f59b190459f999c6b1d3bf9" - integrity sha1-YzMJSSVrKZQfWbGQRZ+ZnGsdO/k= - dependencies: - debug "^2.1.3" - repeat-string "^1.5.0" - rocambole-token "^1.2.1" - -"rocambole@>=0.6.0 <2.0", "rocambole@>=0.7 <2.0", rocambole@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/rocambole/-/rocambole-0.7.0.tgz#f6c79505517dc42b6fb840842b8b953b0f968585" - integrity sha1-9seVBVF9xCtvuECEK4uVOw+WhYU= - dependencies: - esprima "^2.1" - -rocambole@^0.3.6: - version "0.3.6" - resolved "https://registry.yarnpkg.com/rocambole/-/rocambole-0.3.6.tgz#4debbf5943144bc7b6006d95be8facc0b74352a7" - integrity sha1-Teu/WUMUS8e2AG2Vvo+swLdDUqc= - dependencies: - esprima "~1.0" - -run-async@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-0.1.0.tgz#c8ad4a5e110661e402a7d21b530e009f25f8e389" - integrity sha1-yK1KXhEGYeQCp9IbUw4AnyX444k= - dependencies: - once "^1.3.0" - -run-parallel@^1.1.2: - version "1.1.9" - resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" - integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== - -rx-lite@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-3.1.2.tgz#19ce502ca572665f3b647b10939f97fd1615f102" - integrity sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI= - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -semver@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" - integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= - -semver@^4.3.1: - version "4.3.6" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da" - integrity sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto= - -semver@^5.1.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -serializerr@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/serializerr/-/serializerr-1.0.3.tgz#12d4c5aa1c3ffb8f6d1dc5f395aa9455569c3f91" - integrity sha1-EtTFqhw/+49tHcXzlaqUVVacP5E= - dependencies: - protochain "^1.0.5" - -shelljs@^0.6.0: - version "0.6.1" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.6.1.tgz#ec6211bed1920442088fe0f70b2837232ed2c8a8" - integrity sha1-7GIRvtGSBEIIj+D3Cyg3Iy7SyKg= - -sigmund@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= - -slice-ansi@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" - integrity sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU= - -spawn-sync@^1.0.5: - version "1.0.15" - resolved "https://registry.yarnpkg.com/spawn-sync/-/spawn-sync-1.0.15.tgz#b00799557eb7fb0c8376c29d44e8a1ea67e57476" - integrity sha1-sAeZVX63+wyDdsKdROih6mfldHY= - dependencies: - concat-stream "^1.4.7" - os-shim "^0.1.2" - -split@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - integrity sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg== - dependencies: - through "2" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -standard-engine@^4.0.0: - version "4.1.3" - resolved "https://registry.yarnpkg.com/standard-engine/-/standard-engine-4.1.3.tgz#7a31aad54f03d9f39355f43389ce0694f4094155" - integrity sha1-ejGq1U8D2fOTVfQzic4GlPQJQVU= - dependencies: - defaults "^1.0.2" - deglob "^1.0.0" - find-root "^1.0.0" - get-stdin "^5.0.1" - minimist "^1.1.0" - multiline "^1.0.2" - pkg-config "^1.0.1" - xtend "^4.0.0" - -standard-format@^2.2.4: - version "2.2.4" - resolved "https://registry.yarnpkg.com/standard-format/-/standard-format-2.2.4.tgz#b90fb39a635f749cd4fd117fe4730d31179aaeef" - integrity sha1-uQ+zmmNfdJzU/RF/5HMNMRearu8= - dependencies: - deglob "^1.0.0" - esformatter "^0.9.0" - esformatter-eol-last "^1.0.0" - esformatter-jsx "^7.0.0" - esformatter-literal-notation "^1.0.0" - esformatter-quotes "^1.0.0" - esformatter-remove-trailing-commas "^1.0.1" - esformatter-semicolon-first "^1.1.0" - esformatter-spaced-lined-comment "^2.0.0" - minimist "^1.1.0" - stdin "0.0.1" - -standard@7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/standard/-/standard-7.1.2.tgz#40166eeec2405065d1a4f0e3f15babc6e274607e" - integrity sha1-QBZu7sJAUGXRpPDj8VurxuJ0YH4= - dependencies: - eslint "~2.10.2" - eslint-config-standard "5.3.1" - eslint-config-standard-jsx "1.2.1" - eslint-plugin-promise "^1.0.8" - eslint-plugin-react "^5.0.1" - eslint-plugin-standard "^1.3.1" - standard-engine "^4.0.0" - -stdin@*, stdin@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/stdin/-/stdin-0.0.1.tgz#d3041981aaec3dfdbc77a1b38d6372e38f5fb71e" - integrity sha1-0wQZgarsPf28d6GzjWNy449ftx4= - -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string-width@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string.prototype.endswith@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/string.prototype.endswith/-/string.prototype.endswith-0.2.0.tgz#a19c20dee51a98777e9a47e10f09be393b9bba75" - integrity sha1-oZwg3uUamHd+mkfhDwm+OTubunU= - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= - dependencies: - ansi-regex "^3.0.0" - -strip-indent@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" - integrity sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI= - dependencies: - get-stdin "^4.0.1" - -strip-json-comments@~0.1.1: - version "0.1.3" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-0.1.3.tgz#164c64e370a8a3cc00c9e01b539e569823f0ee54" - integrity sha1-Fkxk43Coo8wAyeAbU55WmCPw7lQ= - -strip-json-comments@~1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-1.0.4.tgz#1e15fbcac97d3ee99bf2d73b4c656b082bbafb91" - integrity sha1-HhX7ysl9Pumb8tc7TGVrCCu6+5E= - -supports-color@5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== - dependencies: - has-flag "^3.0.0" - -supports-color@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-1.3.1.tgz#15758df09d8ff3b4acc307539fabe27095e1042d" - integrity sha1-FXWN8J2P87SswwdTn6vicJXhBC0= - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= - -sync-exec@^0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/sync-exec/-/sync-exec-0.5.0.tgz#3f7258e4a5ba17245381909fa6a6f6cf506e1661" - integrity sha1-P3JY5KW6FyRTgZCfpqb2z1BuFmE= - -table@^3.7.8: - version "3.8.3" - resolved "https://registry.yarnpkg.com/table/-/table-3.8.3.tgz#2bbc542f0fda9861a755d3947fefd8b3f513855f" - integrity sha1-K7xULw/amGGnVdOUf+/Ys/UThV8= - dependencies: - ajv "^4.7.0" - ajv-keywords "^1.0.0" - chalk "^1.1.1" - lodash "^4.0.0" - slice-ansi "0.0.4" - string-width "^2.0.0" - -text-table@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= - -through@2, through@^2.3.6: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= - -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha1-uDVx+k2MJbguIxsG46MFXeTKGkc= - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - integrity sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= - dependencies: - prelude-ls "~1.1.2" - -type@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0" - integrity sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg== - -type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" - integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= - -uniq@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" - integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= - -user-home@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/user-home/-/user-home-2.0.0.tgz#9c70bfd8169bc1dcbf48604e0f04b8b49cde9e9f" - integrity sha1-nHC/2Babwdy/SGBODwS4tJzenp8= - dependencies: - os-homedir "^1.0.0" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -which@^1.0.5, which@^1.2.4: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -word-wrap@~1.2.3: - version "1.2.3" - resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" - integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= - -write@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - integrity sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c= - dependencies: - mkdirp "^0.5.1" - -xtend@^4.0.0, xtend@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" - integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== diff --git a/packages/pg-query-stream/.gitignore b/packages/pg-query-stream/.gitignore deleted file mode 100644 index 3c3629e64..000000000 --- a/packages/pg-query-stream/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/packages/pg-query-stream/yarn.lock b/packages/pg-query-stream/yarn.lock deleted file mode 100644 index 3f1706479..000000000 --- a/packages/pg-query-stream/yarn.lock +++ /dev/null @@ -1,1627 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -JSONStream@~0.7.1: - version "0.7.4" - resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-0.7.4.tgz#734290e41511eea7c2cfe151fbf9a563a97b9786" - dependencies: - jsonparse "0.0.5" - through ">=2.2.7 <3" - -acorn-jsx@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" - dependencies: - acorn "^3.0.4" - -acorn@^3.0.4: - version "3.3.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" - -acorn@^5.5.0: - version "5.7.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-5.7.3.tgz#67aa231bf8812974b85235a96771eb6bd07ea279" - integrity sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw== - -ajv-keywords@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" - integrity sha1-YXmX/F9gV2iUxDX5QNgZ4TW4B2I= - -ajv@^5.2.3, ajv@^5.3.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - integrity sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU= - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -ansi-colors@3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" - integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== - -ansi-escapes@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-2.0.0.tgz#5bae52be424878dd9783e8910e3fc2922e83c81b" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - -ansi-regex@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" - integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== - dependencies: - color-convert "^1.9.0" - -argparse@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" - integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== - dependencies: - sprintf-js "~1.0.2" - -array-union@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" - dependencies: - array-uniq "^1.0.1" - -array-uniq@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" - -arrify@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - -assertions@~2.3.0: - version "2.3.4" - resolved "https://registry.yarnpkg.com/assertions/-/assertions-2.3.4.tgz#a9433ced1fce57cc999af0965d1008e96c2796e6" - dependencies: - fomatto "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6" - render "0.1" - traverser "1" - -babel-code-frame@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.22.0.tgz#027620bee567a88c32561574e7fd0801d33118e4" - dependencies: - chalk "^1.1.0" - esutils "^2.0.2" - js-tokens "^3.0.0" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - -base64-js@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.2.tgz#024f0f72afa25b75f9c0ee73cd4f55ec1bed9784" - -bops@0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/bops/-/bops-0.0.6.tgz#082d1d55fa01e60dbdc2ebc2dba37f659554cf3a" - dependencies: - base64-js "0.0.2" - to-utf8 "0.0.1" - -brace-expansion@^1.1.7: - version "1.1.8" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -browser-stdout@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" - integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== - -buffer-writer@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/buffer-writer/-/buffer-writer-2.0.0.tgz#ce7eb81a38f7829db09c873f2fbb792c0c98ec04" - integrity sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw== - -builtin-modules@^1.0.0, builtin-modules@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - -caller-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-0.1.0.tgz#94085ef63581ecd3daa92444a8fe94e82577751f" - dependencies: - callsites "^0.2.0" - -callsites@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-0.2.0.tgz#afab96262910a7f33c19a5775825c69f34e350ca" - -camelcase@^5.0.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" - integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== - -chalk@^1.1.0: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" - integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -circular-json@^0.3.1: - version "0.3.3" - resolved "https://registry.yarnpkg.com/circular-json/-/circular-json-0.3.3.tgz#815c99ea84f6809529d2f45791bdf82711352d66" - -cli-cursor@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" - dependencies: - restore-cursor "^2.0.0" - -cli-width@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.1.0.tgz#b234ca209b29ef66fc518d9b98d5847b00edf00a" - -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== - dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -color-convert@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a" - dependencies: - color-name "^1.1.1" - -color-name@^1.1.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - -concat-stream@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" - dependencies: - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -concat-stream@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.0.1.tgz#018b18bc1c7d073a2dc82aa48442341a2c4dd79f" - dependencies: - bops "0.0.6" - -contains-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - -core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - -cross-spawn@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - -curry@0.0.x: - version "0.0.4" - resolved "https://registry.yarnpkg.com/curry/-/curry-0.0.4.tgz#1750d518d919c44f3d37ff44edc693de1f0d5fcb" - -debug@3.2.6, debug@^3.1.0: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - -debug@^2.6.8: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -decamelize@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= - -deep-is@~0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" - -define-properties@^1.1.2, define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" - -del@^2.0.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/del/-/del-2.2.2.tgz#c12c981d067846c84bcaf862cff930d907ffd1a8" - dependencies: - globby "^5.0.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - rimraf "^2.2.8" - -diff@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== - -doctrine@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - dependencies: - esutils "^2.0.2" - isarray "^1.0.0" - -doctrine@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" - integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== - dependencies: - esutils "^2.0.2" - -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - -error-ex@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.1.tgz#f855a86ce61adc4e8621c3cda21e7a7612c3a8dc" - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.5.1: - version "1.16.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.16.0.tgz#d3a26dc9c3283ac9750dca569586e976d9dcc06d" - integrity sha512-xdQnfykZ9JMEiasTAJZJdMWCQ1Vm00NBw79/AWi7ELfZuuPCSOMDZbT9mkOfSctVtfhb+sAAzrm+j//GjjLHLg== - dependencies: - es-to-primitive "^1.2.0" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.0" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-inspect "^1.6.0" - object-keys "^1.1.1" - string.prototype.trimleft "^2.1.0" - string.prototype.trimright "^2.1.0" - -es-to-primitive@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377" - integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - -eslint-config-standard@^10.2.1: - version "10.2.1" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-10.2.1.tgz#c061e4d066f379dc17cd562c64e819b4dd454591" - -eslint-import-resolver-node@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.1.tgz#4422574cde66a9a7b099938ee4d508a199e0e3cc" - dependencies: - debug "^2.6.8" - resolve "^1.2.0" - -eslint-module-utils@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.1.1.tgz#abaec824177613b8a95b299639e1b6facf473449" - dependencies: - debug "^2.6.8" - pkg-dir "^1.0.0" - -eslint-plugin-import@^2.7.0: - version "2.7.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.7.0.tgz#21de33380b9efb55f5ef6d2e210ec0e07e7fa69f" - dependencies: - builtin-modules "^1.1.1" - contains-path "^0.1.0" - debug "^2.6.8" - doctrine "1.5.0" - eslint-import-resolver-node "^0.3.1" - eslint-module-utils "^2.1.1" - has "^1.0.1" - lodash.cond "^4.3.0" - minimatch "^3.0.3" - read-pkg-up "^2.0.0" - -eslint-plugin-node@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-5.1.1.tgz#a7ed956e780c22aef6afd1116005acd82f26eac6" - dependencies: - ignore "^3.3.3" - minimatch "^3.0.4" - resolve "^1.3.3" - semver "5.3.0" - -eslint-plugin-promise@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz#78fbb6ffe047201627569e85a6c5373af2a68fca" - -eslint-plugin-standard@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-3.0.1.tgz#34d0c915b45edc6f010393c7eef3823b08565cf2" - -eslint-scope@^3.7.1: - version "3.7.1" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" - dependencies: - esrecurse "^4.1.0" - estraverse "^4.1.1" - -eslint-visitor-keys@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== - -eslint@^4.4.0: - version "4.18.2" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-4.18.2.tgz#0f81267ad1012e7d2051e186a9004cc2267b8d45" - integrity sha512-qy4i3wODqKMYfz9LUI8N2qYDkHkoieTbiHpMrYUI/WbjhXJQr7lI4VngixTgaG+yHX+NBCv7nW4hA0ShbvaNKw== - dependencies: - ajv "^5.3.0" - babel-code-frame "^6.22.0" - chalk "^2.1.0" - concat-stream "^1.6.0" - cross-spawn "^5.1.0" - debug "^3.1.0" - doctrine "^2.1.0" - eslint-scope "^3.7.1" - eslint-visitor-keys "^1.0.0" - espree "^3.5.2" - esquery "^1.0.0" - esutils "^2.0.2" - file-entry-cache "^2.0.0" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.0.1" - ignore "^3.3.3" - imurmurhash "^0.1.4" - inquirer "^3.0.6" - is-resolvable "^1.0.0" - js-yaml "^3.9.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.4" - minimatch "^3.0.2" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" - pluralize "^7.0.0" - progress "^2.0.0" - require-uncached "^1.0.3" - semver "^5.3.0" - strip-ansi "^4.0.0" - strip-json-comments "~2.0.1" - table "4.0.2" - text-table "~0.2.0" - -espree@^3.5.2: - version "3.5.4" - resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.4.tgz#b0f447187c8a8bed944b815a660bddf5deb5d1a7" - integrity sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A== - dependencies: - acorn "^5.5.0" - acorn-jsx "^3.0.0" - -esprima@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" - integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== - -esquery@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.0.tgz#cfba8b57d7fba93f17298a8a006a04cda13d80fa" - dependencies: - estraverse "^4.0.0" - -esrecurse@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.0.tgz#fa9568d98d3823f9a41d91e902dcab9ea6e5b163" - dependencies: - estraverse "^4.1.0" - object-assign "^4.0.1" - -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.2.0.tgz#0dee3fed31fcd469618ce7342099fc1afa0bdb13" - -esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - -external-editor@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-2.0.4.tgz#1ed9199da9cbfe2ef2f7a31b2fde8b0d12368972" - dependencies: - iconv-lite "^0.4.17" - jschardet "^1.4.2" - tmp "^0.0.31" - -fast-deep-equal@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff" - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I= - -fast-levenshtein@~2.0.4: - version "2.0.6" - resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" - -figures@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" - dependencies: - escape-string-regexp "^1.0.5" - -file-entry-cache@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-2.0.0.tgz#c392990c3e684783d838b8c84a45d8a048458361" - dependencies: - flat-cache "^1.2.1" - object-assign "^4.0.1" - -find-up@3.0.0, find-up@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" - integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== - dependencies: - locate-path "^3.0.0" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -find-up@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - dependencies: - locate-path "^2.0.0" - -flat-cache@^1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-1.2.2.tgz#fa86714e72c21db88601761ecf2f555d1abc6b96" - dependencies: - circular-json "^0.3.1" - del "^2.0.2" - graceful-fs "^4.1.2" - write "^0.2.1" - -flat@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" - integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== - dependencies: - is-buffer "~2.0.3" - -"fomatto@git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6": - version "0.6.0" - resolved "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6" - -from@~0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/from/-/from-0.0.2.tgz#7fffac647a2f99b20d57b8e28379455cbb4189d0" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - -function-bind@^1.0.2: - version "1.1.0" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771" - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - -get-caller-file@^2.0.1: - version "2.0.5" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" - integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== - -glob@7.1.3, glob@^7.0.3, glob@^7.0.5, glob@^7.1.2: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -globals@^11.0.1: - version "11.12.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" - integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== - -globby@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/globby/-/globby-5.0.0.tgz#ebd84667ca0dbb330b99bcfc68eac2bc54370e0d" - dependencies: - array-union "^1.0.1" - arrify "^1.0.0" - glob "^7.0.3" - object-assign "^4.0.1" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -graceful-fs@^4.1.2: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - -growl@1.10.5: - version "1.10.5" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" - integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - dependencies: - ansi-regex "^2.0.0" - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= - -has-symbols@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44" - integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q= - -has@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.1.tgz#8461733f538b0837c9361e39a9ab9e9704dc2f28" - dependencies: - function-bind "^1.0.2" - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -he@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" - integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== - -hosted-git-info@^2.1.4: - version "2.5.0" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" - -iconv-lite@^0.4.17: - version "0.4.18" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.18.tgz#23d8656b16aae6742ac29732ea8f0336a4789cf2" - -ignore@^3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.3.tgz#432352e57accd87ab3110e82d3fea0e47812156d" - -imurmurhash@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.3, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -inquirer@^3.0.6: - version "3.2.1" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.2.1.tgz#06ceb0f540f45ca548c17d6840959878265fa175" - dependencies: - ansi-escapes "^2.0.0" - chalk "^2.0.0" - cli-cursor "^2.1.0" - cli-width "^2.0.0" - external-editor "^2.0.4" - figures "^2.0.0" - lodash "^4.3.0" - mute-stream "0.0.7" - run-async "^2.2.0" - rx-lite "^4.0.8" - rx-lite-aggregates "^4.0.8" - string-width "^2.1.0" - strip-ansi "^4.0.0" - through "^2.3.6" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - -is-buffer@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" - integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== - -is-builtin-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - dependencies: - builtin-modules "^1.0.0" - -is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== - -is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - -is-path-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" - -is-path-in-cwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz#6477582b8214d602346094567003be8a9eac04dc" - dependencies: - is-path-inside "^1.0.0" - -is-path-inside@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.0.tgz#fc06e5a1683fbda13de667aff717bbc10a48f37f" - dependencies: - path-is-inside "^1.0.1" - -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE= - dependencies: - has "^1.0.1" - -is-resolvable@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.0.0.tgz#8df57c61ea2e3c501408d100fb013cf8d6e0cc62" - dependencies: - tryit "^1.0.1" - -is-symbol@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" - integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw== - dependencies: - has-symbols "^1.0.0" - -isarray@^1.0.0, isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - -isexe@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - -js-tokens@^3.0.0: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - -js-yaml@3.13.1, js-yaml@^3.9.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - -jschardet@^1.4.2: - version "1.5.0" - resolved "https://registry.yarnpkg.com/jschardet/-/jschardet-1.5.0.tgz#a61f310306a5a71188e1b1acd08add3cfbb08b1e" - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - -json-stable-stringify-without-jsonify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" - integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= - -jsonparse@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-0.0.5.tgz#330542ad3f0a654665b778f3eb2d9a9fa507ac64" - -levn@^0.3.0, levn@~0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" - dependencies: - prelude-ls "~1.1.2" - type-check "~0.3.2" - -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.0.0" - -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - -locate-path@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" - integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== - dependencies: - p-locate "^3.0.0" - path-exists "^3.0.0" - -lodash.cond@^4.3.0: - version "4.5.2" - resolved "https://registry.yarnpkg.com/lodash.cond/-/lodash.cond-4.5.2.tgz#f471a1da486be60f6ab955d17115523dd1d255d5" - -lodash@^4.17.15, lodash@^4.17.4, lodash@^4.3.0: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== - -log-symbols@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== - dependencies: - chalk "^2.0.1" - -lru-cache@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - -macgyver@~1.10: - version "1.10.1" - resolved "https://registry.yarnpkg.com/macgyver/-/macgyver-1.10.1.tgz#b09d1599d8b36ed5b16f59589515d9d14bc2fd88" - -mimic-fn@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.1.0.tgz#e667783d92e89dbd342818b5230b9d62a672ad18" - -minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - -mkdirp@0.5.1, mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" - -mocha@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" - integrity sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A== - dependencies: - ansi-colors "3.2.3" - browser-stdout "1.3.1" - debug "3.2.6" - diff "3.5.0" - escape-string-regexp "1.0.5" - find-up "3.0.0" - glob "7.1.3" - growl "1.10.5" - he "1.2.0" - js-yaml "3.13.1" - log-symbols "2.2.0" - minimatch "3.0.4" - mkdirp "0.5.1" - ms "2.1.1" - node-environment-flags "1.0.5" - object.assign "4.1.0" - strip-json-comments "2.0.1" - supports-color "6.0.0" - which "1.3.1" - wide-align "1.1.3" - yargs "13.3.0" - yargs-parser "13.1.1" - yargs-unparser "1.6.0" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - -ms@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" - integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== - -mute-stream@0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" - -natural-compare@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" - -node-environment-flags@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" - integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== - dependencies: - object.getownpropertydescriptors "^2.0.3" - semver "^5.7.0" - -normalize-package-data@^2.3.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - dependencies: - hosted-git-info "^2.1.4" - is-builtin-module "^1.0.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -object-assign@^4.0.1: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.0.tgz#7a3b3d0e98063d43f4c03f2e8ae6cd51a86883a0" - -object-inspect@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== - -object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" - integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== - -object.assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - -object.getownpropertydescriptors@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz#8758c846f5b407adab0f236e0986f14b051caa16" - integrity sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY= - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.1" - -once@^1.3.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - dependencies: - wrappy "1" - -onetime@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" - dependencies: - mimic-fn "^1.0.0" - -optionator@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.2.tgz#364c5e409d3f4d6301d6c0b4c05bba50180aeb64" - dependencies: - deep-is "~0.1.3" - fast-levenshtein "~2.0.4" - levn "~0.3.0" - prelude-ls "~1.1.2" - type-check "~0.3.2" - wordwrap "~1.0.0" - -os-tmpdir@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - -p-limit@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.1.0.tgz#b07ff2d9a5d88bec806035895a2bab66a27988bc" - -p-limit@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== - dependencies: - p-try "^2.0.0" - -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - dependencies: - p-limit "^1.1.0" - -p-locate@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" - integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== - dependencies: - p-limit "^2.0.0" - -p-try@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" - integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== - -packet-reader@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" - integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - dependencies: - error-ex "^1.2.0" - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - dependencies: - pinkie-promise "^2.0.0" - -path-exists@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - -path-is-absolute@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - -path-is-inside@^1.0.1, path-is-inside@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - -path-parse@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" - -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - dependencies: - pify "^2.0.0" - -pg-connection-string@0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" - -pg-cursor@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pg-cursor/-/pg-cursor-2.0.1.tgz#f3bcb3d40b29d86d50014daa0a58f1f0fb71a7f9" - integrity sha512-AfPaRh6N32HrXB8/D0JXfJWdLCn8U+Z4LEf8C954aSFTjhZqt7QbyAYyN5k1E4cv0HQjwW70G1xywQ5ZECzPPg== - -pg-int8@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" - integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== - -pg-pool@^2.0.4: - version "2.0.7" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.7.tgz#f14ecab83507941062c313df23f6adcd9fd0ce54" - integrity sha512-UiJyO5B9zZpu32GSlP0tXy8J2NsJ9EFGFfz5v6PSbdz/1hBLX1rNiiy5+mAm5iJJYwfCv4A0EBcQLGWwjbpzZw== - -pg-types@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" - integrity sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA== - dependencies: - pg-int8 "1.0.1" - postgres-array "~2.0.0" - postgres-bytea "~1.0.0" - postgres-date "~1.0.4" - postgres-interval "^1.1.0" - -pg@^7.5.0: - version "7.12.1" - resolved "https://registry.yarnpkg.com/pg/-/pg-7.12.1.tgz#880636d46d2efbe0968e64e9fe0eeece8ef72a7e" - integrity sha512-l1UuyfEvoswYfcUe6k+JaxiN+5vkOgYcVSbSuw3FvdLqDbaoa2RJo1zfJKfPsSYPFVERd4GHvX3s2PjG1asSDA== - dependencies: - buffer-writer "2.0.0" - packet-reader "1.0.0" - pg-connection-string "0.1.3" - pg-pool "^2.0.4" - pg-types "^2.1.0" - pgpass "1.x" - semver "4.3.2" - -pgpass@1.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" - integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY= - dependencies: - split "^1.0.0" - -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - -pkg-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - dependencies: - find-up "^1.0.0" - -pluralize@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-7.0.0.tgz#298b89df8b93b0221dbf421ad2b1b1ea23fc6777" - integrity sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow== - -postgres-array@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e" - integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA== - -postgres-bytea@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35" - -postgres-date@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.4.tgz#1c2728d62ef1bff49abdd35c1f86d4bdf118a728" - integrity sha512-bESRvKVuTrjoBluEcpv2346+6kgB7UlnqWZsnbnCccTNq/pqfj1j6oBaN5+b/NrDXepYUT/HKadqv3iS9lJuVA== - -postgres-interval@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/postgres-interval/-/postgres-interval-1.1.1.tgz#acdb0f897b4b1c6e496d9d4e0a853e1c428f06f0" - dependencies: - xtend "^4.0.0" - -prelude-ls@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" - -prettier@^1.18.2: - version "1.18.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.18.2.tgz#6823e7c5900017b4bd3acf46fe9ac4b4d7bda9ea" - integrity sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw== - -process-nextick-args@~1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" - -progress@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.0.tgz#8a1be366bf8fc23db2bd23f10c6fe920b4389d1f" - -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - dependencies: - find-up "^2.0.0" - read-pkg "^2.0.0" - -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" - -readable-stream@^2.2.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~1.0.6" - safe-buffer "~5.1.1" - string_decoder "~1.0.3" - util-deprecate "~1.0.1" - -render@0.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/render/-/render-0.1.4.tgz#cfb33a34e26068591d418469e23d8cc5ce1ceff5" - dependencies: - traverser "0.0.x" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= - -require-main-filename@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" - integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== - -require-uncached@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/require-uncached/-/require-uncached-1.0.3.tgz#4e0d56d6c9662fd31e43011c4b95aa49955421d3" - dependencies: - caller-path "^0.1.0" - resolve-from "^1.0.0" - -resolve-from@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" - -resolve@^1.2.0, resolve@^1.3.3: - version "1.4.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.4.0.tgz#a75be01c53da25d934a98ebd0e4c4a7312f92a86" - dependencies: - path-parse "^1.0.5" - -restore-cursor@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" - dependencies: - onetime "^2.0.0" - signal-exit "^3.0.2" - -rimraf@^2.2.8: - version "2.6.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.1.tgz#c2338ec643df7a1b7fe5c54fa86f57428a55f33d" - dependencies: - glob "^7.0.5" - -run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - dependencies: - is-promise "^2.1.0" - -rx-lite-aggregates@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz#753b87a89a11c95467c4ac1626c4efc4e05c67be" - dependencies: - rx-lite "*" - -rx-lite@*, rx-lite@^4.0.8: - version "4.0.8" - resolved "https://registry.yarnpkg.com/rx-lite/-/rx-lite-4.0.8.tgz#0b1e11af8bc44836f04a6407e92da42467b79444" - -safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" - -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.7.0: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" - -semver@5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= - -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - dependencies: - shebang-regex "^1.0.0" - -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - -signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - -slice-ansi@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-1.0.0.tgz#044f1a49d8842ff307aad6b505ed178bd950134d" - integrity sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg== - dependencies: - is-fullwidth-code-point "^2.0.0" - -spdx-correct@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-1.0.2.tgz#4b3073d933ff51f3912f03ac5519498a4150db40" - dependencies: - spdx-license-ids "^1.0.2" - -spdx-expression-parse@~1.0.0: - version "1.0.4" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz#9bdf2f20e1f40ed447fbe273266191fced51626c" - -spdx-license-ids@^1.0.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz#c9df7a3424594ade6bd11900d596696dc06bac57" - -split@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" - dependencies: - through "2" - -sprintf-js@~1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= - -stream-spec@~0.3.5: - version "0.3.6" - resolved "https://registry.yarnpkg.com/stream-spec/-/stream-spec-0.3.6.tgz#2fddac4a07bf3e9f8963c677a6b5a6cc2115255e" - dependencies: - macgyver "~1.10" - -stream-tester@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stream-tester/-/stream-tester-0.0.5.tgz#4f86f2531149adaf6dd4b3ff262edf64ae9a171a" - dependencies: - assertions "~2.3.0" - from "~0.0.2" - through "~0.0.3" - -"string-width@^1.0.2 || 2", string-width@^2.1.0, string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - -string.prototype.trimleft@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" - integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== - dependencies: - define-properties "^1.1.3" - function-bind "^1.1.1" - -string.prototype.trimright@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" - integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== - dependencies: - define-properties "^1.1.3" - function-bind "^1.1.1" - -string_decoder@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - dependencies: - ansi-regex "^3.0.0" - -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-bom@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" - -strip-json-comments@2.0.1, strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - -supports-color@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" - integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== - dependencies: - has-flag "^3.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== - dependencies: - has-flag "^3.0.0" - -table@4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/table/-/table-4.0.2.tgz#a33447375391e766ad34d3486e6e2aedc84d2e36" - integrity sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA== - dependencies: - ajv "^5.2.3" - ajv-keywords "^2.1.0" - chalk "^2.1.0" - lodash "^4.17.4" - slice-ansi "1.0.0" - string-width "^2.1.1" - -text-table@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - -through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3.4: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - -through@~0.0.3: - version "0.0.4" - resolved "https://registry.yarnpkg.com/through/-/through-0.0.4.tgz#0bf2f0fffafaac4bacbc533667e98aad00b588c8" - -tmp@^0.0.31: - version "0.0.31" - resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" - dependencies: - os-tmpdir "~1.0.1" - -to-utf8@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/to-utf8/-/to-utf8-0.0.1.tgz#d17aea72ff2fba39b9e43601be7b3ff72e089852" - -traverser@0.0.x: - version "0.0.5" - resolved "https://registry.yarnpkg.com/traverser/-/traverser-0.0.5.tgz#c66f38c456a0c21a88014b1223580c7ebe0631eb" - dependencies: - curry "0.0.x" - -traverser@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/traverser/-/traverser-1.0.0.tgz#6f59e5813759aeeab3646b8f4513fd4a62e4fe20" - dependencies: - curry "0.0.x" - -tryit@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/tryit/-/tryit-1.0.3.tgz#393be730a9446fd1ead6da59a014308f36c289cb" - -type-check@~0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" - dependencies: - prelude-ls "~1.1.2" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - -validate-npm-package-license@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz#2804babe712ad3379459acfbe24746ab2c303fbc" - dependencies: - spdx-correct "~1.0.0" - spdx-expression-parse "~1.0.0" - -which-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" - integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= - -which@1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^1.2.9: - version "1.3.0" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" - dependencies: - isexe "^2.0.0" - -wide-align@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" - integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== - dependencies: - string-width "^1.0.2 || 2" - -wordwrap@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" - -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== - dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - -write@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/write/-/write-0.2.1.tgz#5fc03828e264cea3fe91455476f7a3c566cb0757" - dependencies: - mkdirp "^0.5.1" - -xtend@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - -y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== - -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - -yargs-parser@13.1.1, yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" - -yargs-unparser@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" - integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== - dependencies: - flat "^4.1.0" - lodash "^4.17.15" - yargs "^13.3.0" - -yargs@13.3.0, yargs@^13.3.0: - version "13.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.1" diff --git a/yarn.lock b/yarn.lock index acd799c6a..e3e2dcf83 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1189,6 +1189,11 @@ before-after-hook@^2.0.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635" integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A== +bluebird@3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.1.tgz#b731ddf48e2dd3bedac2e75e1215a11bcb91fa07" + integrity sha1-tzHd9I4t077awudeEhWhG8uR+gc= + bluebird@3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" @@ -1511,6 +1516,11 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" +commander@2.15.1: + version "2.15.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" + integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== + commander@~2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -2246,6 +2256,11 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" +expect.js@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/expect.js/-/expect.js-0.3.1.tgz#b0a59a0d2eff5437544ebf0ceaa6015841d09b5b" + integrity sha1-sKWaDS7/VDdUTr8M6qYBWEHQm1s= + extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" @@ -2645,6 +2660,18 @@ glob-to-regexp@^0.3.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= +glob@7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" @@ -2777,6 +2804,11 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +he@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" + integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= + he@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -3461,7 +3493,7 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: +lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: version "4.17.15" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== @@ -3732,6 +3764,23 @@ mkdirp@*, mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: dependencies: minimist "0.0.8" +mocha@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" + integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== + dependencies: + browser-stdout "1.3.1" + commander "2.15.1" + debug "3.1.0" + diff "3.5.0" + escape-string-regexp "1.0.5" + glob "7.1.2" + growl "1.10.5" + he "1.1.1" + minimatch "3.0.4" + mkdirp "0.5.1" + supports-color "5.4.0" + mocha@^6.2.2: version "6.2.2" resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" @@ -4352,16 +4401,16 @@ pg-copy-streams@0.3.0: resolved "https://registry.yarnpkg.com/pg-copy-streams/-/pg-copy-streams-0.3.0.tgz#a4fbc2a3b788d4e9da6f77ceb35422d8d7043b7f" integrity sha1-pPvCo7eI1Onab3fOs1Qi2NcEO38= +pg-cursor@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/pg-cursor/-/pg-cursor-1.3.0.tgz#b220f1908976b7b40daa373c7ada5fca823ab0d9" + integrity sha1-siDxkIl2t7QNqjc8etpfyoI6sNk= + pg-int8@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c" integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw== -pg-pool@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/pg-pool/-/pg-pool-2.0.7.tgz#f14ecab83507941062c313df23f6adcd9fd0ce54" - integrity sha512-UiJyO5B9zZpu32GSlP0tXy8J2NsJ9EFGFfz5v6PSbdz/1hBLX1rNiiy5+mAm5iJJYwfCv4A0EBcQLGWwjbpzZw== - pg-types@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/pg-types/-/pg-types-2.2.0.tgz#2d0250d636454f7cfa3b6ae0382fdfa8063254a3" @@ -5303,6 +5352,13 @@ strong-log-transformer@^2.0.0: minimist "^1.2.0" through "^2.3.4" +supports-color@5.4.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" + integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== + dependencies: + has-flag "^3.0.0" + supports-color@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" From bb8e806bc53e179cd19f3461669d891dd0358b74 Mon Sep 17 00:00:00 2001 From: Andrew Heuermann Date: Fri, 27 Dec 2019 15:09:58 -0600 Subject: [PATCH 0570/1037] Adding ability to pass through idle_in_transaction_session_timeout --- packages/pg/lib/client.js | 3 + packages/pg/lib/connection-parameters.js | 1 + packages/pg/lib/defaults.js | 4 ++ ...le_in_transaction_session_timeout-tests.js | 63 +++++++++++++++++++ .../connection-parameters/creation-tests.js | 4 +- 5 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 077a9f676..93807e48c 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -371,6 +371,9 @@ Client.prototype.getStartupConf = function () { if (params.statement_timeout) { data.statement_timeout = String(parseInt(params.statement_timeout, 10)) } + if (params.idle_in_transaction_session_timeout) { + data.idle_in_transaction_session_timeout = String(parseInt(params.idle_in_transaction_session_timeout, 10)) + } return data } diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index 00ea76111..0d5e0376d 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -65,6 +65,7 @@ var ConnectionParameters = function (config) { this.application_name = val('application_name', config, 'PGAPPNAME') this.fallback_application_name = val('fallback_application_name', config, false) this.statement_timeout = val('statement_timeout', config, false) + this.idle_in_transaction_session_timeout = val('idle_in_transaction_session_timeout', config, false) this.query_timeout = val('query_timeout', config, false) if (config.connectionTimeoutMillis === undefined) { diff --git a/packages/pg/lib/defaults.js b/packages/pg/lib/defaults.js index bd1bf6de6..120b8c7b5 100644 --- a/packages/pg/lib/defaults.js +++ b/packages/pg/lib/defaults.js @@ -59,6 +59,10 @@ module.exports = { // false=unlimited statement_timeout: false, + // Terminate any session with an open transaction that has been idle for longer than the specified duration in milliseconds + // false=unlimited + idle_in_transaction_session_timeout: false, + // max milliseconds to wait for query to complete (client side) query_timeout: false, diff --git a/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js b/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js new file mode 100644 index 000000000..b40a5ace6 --- /dev/null +++ b/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js @@ -0,0 +1,63 @@ +'use strict' +var helper = require('./test-helper') +var Client = helper.Client + +var suite = new helper.Suite() + +var conInfo = helper.config + +function getConInfo (override) { + return Object.assign({}, conInfo, override ) +} + +function getIdleTransactionSessionTimeout (conf, cb) { + var client = new Client(conf) + client.connect(assert.success(function () { + client.query('SHOW idle_in_transaction_session_timeout', assert.success(function (res) { + var timeout = res.rows[0].idle_in_transaction_session_timeout + cb(timeout) + client.end() + })) + })) +} + +if (!helper.args.native) { // idle_in_transaction_session_timeout is not supported with the native client + suite.test('No default idle_in_transaction_session_timeout ', function (done) { + getConInfo() + getIdleTransactionSessionTimeout({}, function (res) { + assert.strictEqual(res, '0') // 0 = no timeout + done() + }) + }) + + suite.test('idle_in_transaction_session_timeout integer is used', function (done) { + var conf = getConInfo({ + 'idle_in_transaction_session_timeout': 3000 + }) + getIdleTransactionSessionTimeout(conf, function (res) { + assert.strictEqual(res, '3s') + done() + }) + }) + + suite.test('idle_in_transaction_session_timeout float is used', function (done) { + var conf = getConInfo({ + 'idle_in_transaction_session_timeout': 3000.7 + }) + getIdleTransactionSessionTimeout(conf, function (res) { + assert.strictEqual(res, '3s') + done() + }) + }) + + suite.test('idle_in_transaction_session_timeout string is used', function (done) { + var conf = getConInfo({ + 'idle_in_transaction_session_timeout': '3000' + }) + getIdleTransactionSessionTimeout(conf, function (res) { + assert.strictEqual(res, '3s') + done() + }) + }) + +} diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index fc9f6521f..bb0733d2c 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -23,6 +23,7 @@ var compare = function (actual, expected, type) { assert.equal(actual.password, expected.password, type + ' password') assert.equal(actual.binary, expected.binary, type + ' binary') assert.equal(actual.statement_timout, expected.statement_timout, type + ' statement_timeout') + assert.equal(actual.idle_in_transaction_session_timeout, expected.idle_in_transaction_session_timeout, type + 'idle_in_transaction_session_timeout') } test('ConnectionParameters initializing from defaults', function () { @@ -62,7 +63,8 @@ test('ConnectionParameters initializing from config', function () { ssl: { asdf: 'blah' }, - statement_timeout: 15000 + statement_timeout: 15000, + idle_in_transaction_session_timeout: 15000 } var subject = new ConnectionParameters(config) compare(subject, config, 'config') From 63637786753843a884aa741f904f46155c65d4ac Mon Sep 17 00:00:00 2001 From: Andrew Heuermann Date: Fri, 27 Dec 2019 15:36:41 -0600 Subject: [PATCH 0571/1037] Fixing test --- .../pg/test/unit/connection-parameters/creation-tests.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index bb0733d2c..5d200be0a 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -22,8 +22,8 @@ var compare = function (actual, expected, type) { assert.equal(actual.host, expected.host, type + ' host') assert.equal(actual.password, expected.password, type + ' password') assert.equal(actual.binary, expected.binary, type + ' binary') - assert.equal(actual.statement_timout, expected.statement_timout, type + ' statement_timeout') - assert.equal(actual.idle_in_transaction_session_timeout, expected.idle_in_transaction_session_timeout, type + 'idle_in_transaction_session_timeout') + assert.equal(actual.statement_timeout, expected.statement_timeout, type + ' statement_timeout') + assert.equal(actual.idle_in_transaction_session_timeout, expected.idle_in_transaction_session_timeout, type + ' idle_in_transaction_session_timeout') } test('ConnectionParameters initializing from defaults', function () { @@ -39,7 +39,9 @@ test('ConnectionParameters initializing from defaults with connectionString set' port: 7777, password: 'mypassword', host: 'foo.bar.net', - binary: defaults.binary + binary: defaults.binary, + statement_timeout: false, + idle_in_transaction_session_timeout: false, } var original_value = defaults.connectionString From 839043206de96fee710c55776a803895702dc299 Mon Sep 17 00:00:00 2001 From: Andrew Heuermann Date: Sat, 28 Dec 2019 09:01:35 -0600 Subject: [PATCH 0572/1037] Only run tests on >= v10 --- ...le_in_transaction_session_timeout-tests.js | 74 +++++++++++-------- 1 file changed, 44 insertions(+), 30 deletions(-) diff --git a/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js b/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js index b40a5ace6..4435a40b6 100644 --- a/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js +++ b/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js @@ -10,6 +10,19 @@ function getConInfo (override) { return Object.assign({}, conInfo, override ) } +function testClientVersion(cb) { + var client = new Client({}) + client.connect(assert.success(function () { + helper.versionGTE(client, 100000, assert.success(function(isGreater) { + if (!isGreater) { + console.log('skip idle_in_transaction_session_timeout at client-level is only available in v10 and above'); + return client.end(); + } + cb(); + })) + })) +} + function getIdleTransactionSessionTimeout (conf, cb) { var client = new Client(conf) client.connect(assert.success(function () { @@ -22,42 +35,43 @@ function getIdleTransactionSessionTimeout (conf, cb) { } if (!helper.args.native) { // idle_in_transaction_session_timeout is not supported with the native client - suite.test('No default idle_in_transaction_session_timeout ', function (done) { - getConInfo() - getIdleTransactionSessionTimeout({}, function (res) { - assert.strictEqual(res, '0') // 0 = no timeout - done() + testClientVersion(function(){ + suite.test('No default idle_in_transaction_session_timeout ', function (done) { + getConInfo() + getIdleTransactionSessionTimeout({}, function (res) { + assert.strictEqual(res, '0') // 0 = no timeout + done() + }) }) - }) - suite.test('idle_in_transaction_session_timeout integer is used', function (done) { - var conf = getConInfo({ - 'idle_in_transaction_session_timeout': 3000 + suite.test('idle_in_transaction_session_timeout integer is used', function (done) { + var conf = getConInfo({ + 'idle_in_transaction_session_timeout': 3000 + }) + getIdleTransactionSessionTimeout(conf, function (res) { + assert.strictEqual(res, '3s') + done() + }) }) - getIdleTransactionSessionTimeout(conf, function (res) { - assert.strictEqual(res, '3s') - done() - }) - }) - suite.test('idle_in_transaction_session_timeout float is used', function (done) { - var conf = getConInfo({ - 'idle_in_transaction_session_timeout': 3000.7 - }) - getIdleTransactionSessionTimeout(conf, function (res) { - assert.strictEqual(res, '3s') - done() + suite.test('idle_in_transaction_session_timeout float is used', function (done) { + var conf = getConInfo({ + 'idle_in_transaction_session_timeout': 3000.7 + }) + getIdleTransactionSessionTimeout(conf, function (res) { + assert.strictEqual(res, '3s') + done() + }) }) - }) - suite.test('idle_in_transaction_session_timeout string is used', function (done) { - var conf = getConInfo({ - 'idle_in_transaction_session_timeout': '3000' - }) - getIdleTransactionSessionTimeout(conf, function (res) { - assert.strictEqual(res, '3s') - done() + suite.test('idle_in_transaction_session_timeout string is used', function (done) { + var conf = getConInfo({ + 'idle_in_transaction_session_timeout': '3000' + }) + getIdleTransactionSessionTimeout(conf, function (res) { + assert.strictEqual(res, '3s') + done() + }) }) }) - } From 6ddbe6ab60072d2e67ea5ab3a82fc7a0da72f5a2 Mon Sep 17 00:00:00 2001 From: Andrew Heuermann Date: Sat, 28 Dec 2019 09:24:45 -0600 Subject: [PATCH 0573/1037] Close connection after version check --- .../idle_in_transaction_session_timeout-tests.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js b/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js index 4435a40b6..18162f545 100644 --- a/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js +++ b/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js @@ -14,11 +14,13 @@ function testClientVersion(cb) { var client = new Client({}) client.connect(assert.success(function () { helper.versionGTE(client, 100000, assert.success(function(isGreater) { - if (!isGreater) { - console.log('skip idle_in_transaction_session_timeout at client-level is only available in v10 and above'); - return client.end(); - } - cb(); + return client.end(assert.success(function () { + if (!isGreater) { + console.log('skip idle_in_transaction_session_timeout at client-level is only available in v10 and above'); + return; + } + cb(); + })) })) })) } From af4d05445d099a8176df185476d5e853c9c13ef8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sat, 28 Dec 2019 17:16:42 +0000 Subject: [PATCH 0574/1037] Publish - pg-cursor@2.1.1 - pg-pool@2.0.9 - pg-query-stream@2.1.1 - pg@7.16.1 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 3 +-- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 397de6eb3..3f5d4991d 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.1.0", + "version": "2.1.1", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -21,7 +21,7 @@ "eslint-config-prettier": "^6.4.0", "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "^7.16.0", + "pg": "^7.16.1", "prettier": "^1.18.2" }, "prettier": { diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 5b8ebd038..dc0275699 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "2.0.8", + "version": "2.0.9", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { @@ -33,7 +33,6 @@ "mocha": "^5.2.0", "pg-cursor": "^1.3.0" }, - "dependencies": {}, "peerDependencies": { "pg": ">5.0" } diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 6bab12d09..bdefca7b0 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "2.1.0", + "version": "2.1.1", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -27,12 +27,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^6.2.2", - "pg": "^7.16.0", + "pg": "^7.16.1", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.1.0" + "pg-cursor": "^2.1.1" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 147c10ccb..b3a585fd9 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.16.0", + "version": "7.16.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "packet-reader": "1.0.0", "pg-connection-string": "0.1.3", "pg-packet-stream": "^1.1.0", - "pg-pool": "^2.0.7", + "pg-pool": "^2.0.9", "pg-types": "^2.1.0", "pgpass": "1.x", "semver": "4.3.2" From c8b9488d7cc7e4349a015fcc4503bcc18d7e6584 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 29 Dec 2019 17:45:50 +0000 Subject: [PATCH 0575/1037] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76a3aa492..d9d646527 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### pg@7.17.0 + +- Add support for `idle_in_transaction_session_timeout` [option](https://github.com/brianc/node-postgres/pull/2049). + ### 7.16.0 - Add optional, opt-in behavior to test new, [faster query pipeline](https://github.com/brianc/node-postgres/pull/2044). This is experimental, and not documented yet. The pipeline changes will grow significantly after the 8.0 release. From 6d93951783dc774731fe0b18d07ed8bf2d78d0b2 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 29 Dec 2019 17:50:24 +0000 Subject: [PATCH 0576/1037] Publish - pg-cursor@2.1.2 - pg-query-stream@2.1.2 - pg@7.17.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 3f5d4991d..6a0913471 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.1.1", + "version": "2.1.2", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -21,7 +21,7 @@ "eslint-config-prettier": "^6.4.0", "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "^7.16.1", + "pg": "^7.17.0", "prettier": "^1.18.2" }, "prettier": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index bdefca7b0..359e54e2d 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "2.1.1", + "version": "2.1.2", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -27,12 +27,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^6.2.2", - "pg": "^7.16.1", + "pg": "^7.17.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.1.1" + "pg-cursor": "^2.1.2" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index b3a585fd9..2fc8c856b 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.16.1", + "version": "7.17.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 8eca181d20849aeb440b84f112d68671e90aafe6 Mon Sep 17 00:00:00 2001 From: Brian C Date: Sun, 29 Dec 2019 23:08:09 -0600 Subject: [PATCH 0577/1037] Fix pg-query-stream implementation (#2051) * Fix pg-query-stream There were some subtle behaviors with the stream being implemented incorrectly & not working as expected with async iteration. I've modified the code based on #2050 and comments in #2035 to have better test coverage of async iterables and update the internals significantly to more closely match the readable stream interface. Note: this is a __breaking__ (semver major) change to this package as the close event behavior is changed slightly, and `highWaterMark` is no longer supported. It shouldn't impact most usage, but breaking regardless. * Remove a bunch of additional code * Add test for destroy + error propagation * Add failing test for destroying unsubmitted stream * Do not throw an uncatchable error when closing an unused cursor --- packages/pg-cursor/index.js | 2 +- packages/pg-cursor/test/close.js | 5 ++ packages/pg-query-stream/README.md | 2 +- packages/pg-query-stream/index.js | 57 +++++--------- .../pg-query-stream/test/async-iterator.es6 | 55 ++++++++++++++ packages/pg-query-stream/test/close.js | 74 ++++++++++++++----- packages/pg-query-stream/test/config.js | 4 +- 7 files changed, 138 insertions(+), 61 deletions(-) diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index 624877680..727fe9081 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -182,7 +182,7 @@ Cursor.prototype.end = util.deprecate(function (cb) { }, 'Cursor.end is deprecated. Call end on the client itself to end a connection to the database.') Cursor.prototype.close = function (cb) { - if (this.state === 'done') { + if (!this.connection || this.state === 'done') { if (cb) { return setImmediate(cb) } else { diff --git a/packages/pg-cursor/test/close.js b/packages/pg-cursor/test/close.js index 785a71098..e63512abd 100644 --- a/packages/pg-cursor/test/close.js +++ b/packages/pg-cursor/test/close.js @@ -46,4 +46,9 @@ describe('close', function () { }) }) }) + + it('is a no-op to "close" the cursor before submitting it', function (done) { + const cursor = new Cursor(text) + cursor.close(done) + }) }) diff --git a/packages/pg-query-stream/README.md b/packages/pg-query-stream/README.md index d00550aec..312387aa7 100644 --- a/packages/pg-query-stream/README.md +++ b/packages/pg-query-stream/README.md @@ -47,7 +47,7 @@ I'm very open to contribution! Open a pull request with your code or idea and w The MIT License (MIT) -Copyright (c) 2013 Brian M. Carlson +Copyright (c) 2013-2019 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 diff --git a/packages/pg-query-stream/index.js b/packages/pg-query-stream/index.js index 9c34207ec..4576f5fb5 100644 --- a/packages/pg-query-stream/index.js +++ b/packages/pg-query-stream/index.js @@ -1,14 +1,12 @@ -'use strict' -var Cursor = require('pg-cursor') -var Readable = require('stream').Readable +const { Readable } = require('stream') +const Cursor = require('pg-cursor') class PgQueryStream extends Readable { - constructor (text, values, options) { - super(Object.assign({ objectMode: true }, options)) - this.cursor = new Cursor(text, values, options) - this._reading = false - this._closed = false - this.batchSize = (options || {}).batchSize || 100 + constructor(text, values, config = {}) { + const { batchSize = 100 } = config; + // https://nodejs.org/api/stream.html#stream_new_stream_readable_options + super({ objectMode: true, emitClose: true, autoDestroy: true, highWaterMark: batchSize }) + this.cursor = new Cursor(text, values, config) // delegate Submittable callbacks to cursor this.handleRowDescription = this.cursor.handleRowDescription.bind(this.cursor) @@ -19,40 +17,25 @@ class PgQueryStream extends Readable { this.handleError = this.cursor.handleError.bind(this.cursor) } - submit (connection) { + submit(connection) { this.cursor.submit(connection) } - close (callback) { - this._closed = true - const cb = callback || (() => this.emit('close')) - this.cursor.close(cb) + _destroy(_err, cb) { + this.cursor.close((err) => { + cb(err || _err) + }) } - _read (size) { - if (this._reading || this._closed) { - return false - } - this._reading = true - const readAmount = Math.max(size, this.batchSize) - this.cursor.read(readAmount, (err, rows) => { - if (this._closed) { - return - } + // https://nodejs.org/api/stream.html#stream_readable_read_size_1 + _read(size) { + this.cursor.read(size, (err, rows, result) => { if (err) { - return this.emit('error', err) - } - // if we get a 0 length array we've read to the end of the cursor - if (!rows.length) { - this._closed = true - setImmediate(() => this.emit('close')) - return this.push(null) - } - - // push each row into the stream - this._reading = false - for (var i = 0; i < rows.length; i++) { - this.push(rows[i]) + // https://nodejs.org/api/stream.html#stream_errors_while_reading + this.destroy(err) + } else { + for (const row of rows) this.push(row) + if (rows.length < size) this.push(null) } }) } diff --git a/packages/pg-query-stream/test/async-iterator.es6 b/packages/pg-query-stream/test/async-iterator.es6 index e84089b6c..47bda86d2 100644 --- a/packages/pg-query-stream/test/async-iterator.es6 +++ b/packages/pg-query-stream/test/async-iterator.es6 @@ -54,4 +54,59 @@ describe('Async iterator', () => { assert.equal(allRows.length, 603) await pool.end() }) + + it('can break out of iteration early', async () => { + const pool = new pg.Pool({ max: 1 }) + const client = await pool.connect() + const rows = [] + for await (const row of client.query(new QueryStream(queryText, [], { batchSize: 1 }))) { + rows.push(row) + break; + } + for await (const row of client.query(new QueryStream(queryText, []))) { + rows.push(row) + break; + } + for await (const row of client.query(new QueryStream(queryText, []))) { + rows.push(row) + break; + } + assert.strictEqual(rows.length, 3) + client.release() + await pool.end() + }) + + it('only returns rows on first iteration', async () => { + const pool = new pg.Pool({ max: 1 }) + const client = await pool.connect() + const rows = [] + const stream = client.query(new QueryStream(queryText, [])) + for await (const row of stream) { + rows.push(row) + break; + } + for await (const row of stream) { + rows.push(row) + } + for await (const row of stream) { + rows.push(row) + } + assert.strictEqual(rows.length, 1) + client.release() + await pool.end() + }) + + it('can read with delays', async () => { + const pool = new pg.Pool({ max: 1 }) + const client = await pool.connect() + const rows = [] + const stream = client.query(new QueryStream(queryText, [], { batchSize: 1 })) + for await (const row of stream) { + rows.push(row) + await new Promise((resolve) => setTimeout(resolve, 1)) + } + assert.strictEqual(rows.length, 201) + client.release() + await pool.end() + }) }) diff --git a/packages/pg-query-stream/test/close.js b/packages/pg-query-stream/test/close.js index be103c7f6..d7e44b675 100644 --- a/packages/pg-query-stream/test/close.js +++ b/packages/pg-query-stream/test/close.js @@ -4,18 +4,22 @@ var concat = require('concat-stream') var QueryStream = require('../') var helper = require('./helper') +if (process.version.startsWith('v8.')) { + return console.error('warning! node versions less than 10lts no longer supported & stream closing semantics may not behave properly'); +} + helper('close', function (client) { it('emits close', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], {batchSize: 2, highWaterMark: 2}) + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], { batchSize: 2, highWaterMark: 2 }) var query = client.query(stream) - query.pipe(concat(function () {})) + query.pipe(concat(function () { })) query.on('close', done) }) }) helper('early close', function (client) { it('can be closed early', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [20000], {batchSize: 2, highWaterMark: 2}) + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [20000], { batchSize: 2, highWaterMark: 2 }) var query = client.query(stream) var readCount = 0 query.on('readable', function () { @@ -23,30 +27,62 @@ helper('early close', function (client) { query.read() }) query.once('readable', function () { - query.close() + query.destroy() }) query.on('close', function () { assert(readCount < 10, 'should not have read more than 10 rows') done() }) }) -}) -helper('close callback', function (client) { - it('notifies an optional callback when the conneciton is closed', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [10], {batchSize: 2, highWaterMark: 2}) - var query = client.query(stream) - query.once('readable', function () { // only reading once - query.read() - }) - query.once('readable', function () { - query.close(function () { - // nothing to assert. This test will time out if the callback does not work. - done() + it('can destroy stream while reading', function (done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') + client.query(stream) + stream.on('data', () => done(new Error('stream should not have returned rows'))) + setTimeout(() => { + stream.destroy() + stream.on('close', done) + }, 100) + }) + + it('emits an error when calling destroy with an error', function (done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') + client.query(stream) + stream.on('data', () => done(new Error('stream should not have returned rows'))) + setTimeout(() => { + stream.destroy(new Error('intentional error')) + stream.on('error', (err) => { + // make sure there's an error + assert(err); + assert.strictEqual(err.message, 'intentional error'); + done(); }) + }, 100) + }) + + it('can destroy stream while reading an error', function (done) { + var stream = new QueryStream('SELECT * from pg_sleep(1), basdfasdf;') + client.query(stream) + stream.on('data', () => done(new Error('stream should not have returned rows'))) + stream.once('error', () => { + stream.destroy() + // wait a bit to let any other errors shake through + setTimeout(done, 100) }) - query.on('close', function () { - assert(false, 'close event should not fire') // no close event because we did not read to the end of the stream. - }) + }) + + it('does not crash when destroying the stream immediately after calling read', function (done) { + var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') + client.query(stream) + stream.on('data', () => done(new Error('stream should not have returned rows'))) + stream.destroy() + stream.on('close', done) + }) + + it('does not crash when destroying the stream before its submitted', function (done) { + var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') + stream.on('data', () => done(new Error('stream should not have returned rows'))) + stream.destroy() + stream.on('close', done) }) }) diff --git a/packages/pg-query-stream/test/config.js b/packages/pg-query-stream/test/config.js index 4ed5b1b93..78251c894 100644 --- a/packages/pg-query-stream/test/config.js +++ b/packages/pg-query-stream/test/config.js @@ -2,9 +2,7 @@ var assert = require('assert') var QueryStream = require('../') var stream = new QueryStream('SELECT NOW()', [], { - highWaterMark: 999, batchSize: 88 }) -assert.equal(stream._readableState.highWaterMark, 999) -assert.equal(stream.batchSize, 88) +assert.equal(stream._readableState.highWaterMark, 88) From 19308f9ceba0774dad864304deb83fd11e956b56 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 9 Jan 2020 21:30:53 -0600 Subject: [PATCH 0578/1037] Result.fields should always be an array (#2060) This fixes a subtle backwards incompatible change. Added a test to prevent further regressions. Closes #2056 --- packages/pg/lib/result.js | 2 +- .../test/integration/gh-issues/2056-tests.js | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 packages/pg/test/integration/gh-issues/2056-tests.js diff --git a/packages/pg/lib/result.js b/packages/pg/lib/result.js index d959e808a..233455b06 100644 --- a/packages/pg/lib/result.js +++ b/packages/pg/lib/result.js @@ -17,7 +17,7 @@ var Result = function (rowMode, types) { this.rowCount = null this.oid = null this.rows = [] - this.fields = undefined + this.fields = [] this._parsers = undefined this._types = types this.RowCtor = null diff --git a/packages/pg/test/integration/gh-issues/2056-tests.js b/packages/pg/test/integration/gh-issues/2056-tests.js new file mode 100644 index 000000000..f2912fc62 --- /dev/null +++ b/packages/pg/test/integration/gh-issues/2056-tests.js @@ -0,0 +1,22 @@ + +"use strict" +var helper = require('./../test-helper') +var assert = require('assert') + +const suite = new helper.Suite() + +suite.test('All queries should return a result array', (done) => { + const client = new helper.pg.Client() + client.connect() + const promises = [] + promises.push(client.query('CREATE TEMP TABLE foo(bar TEXT)')) + promises.push(client.query('INSERT INTO foo(bar) VALUES($1)', ['qux'])) + promises.push(client.query('SELECT * FROM foo WHERE bar = $1', ['foo'])) + Promise.all(promises).then(results => { + results.forEach(res => { + assert(Array.isArray(res.fields)) + assert(Array.isArray(res.rows)) + }) + client.end(done) + }) +}) From 08954600467b9ffc5c5c31eb72c11e87b10efe7e Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 9 Jan 2020 23:33:40 -0600 Subject: [PATCH 0579/1037] pg-query-stream@3.0 release (#2059) * Fix one unintentional possible breaking change & update readme * Update changelog more * Update CHANGELOG.md Co-Authored-By: Charmander <~@charmander.me> Co-authored-by: Charmander <~@charmander.me> --- CHANGELOG.md | 6 ++++++ packages/pg-query-stream/index.js | 4 ++-- packages/pg-query-stream/test/config.js | 26 +++++++++++++++++++++---- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9d646527..7d7f86170 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### pg-query-stream@3.0.0 + +- [Rewrote stream internals](https://github.com/brianc/node-postgres/pull/2051) to better conform to node stream semantics. This should make pg-query-stream much better at respecting [highWaterMark](https://nodejs.org/api/stream.html#stream_new_stream_readable_options) and getting rid of some edge case bugs when using pg-query-stream as an async iterator. Due to the size and nature of this change (effectively a full re-write) it's safest to bump the semver major here, though almost all tests remain untouched and still passing, which brings us to a breaking change to the API.... +- Changed `stream.close` to `stream.destroy` which is the [official](https://nodejs.org/api/stream.html#stream_readable_destroy_error) way to terminate a readable stream. This is a __breaking change__ if you rely on the `stream.close` method on pg-query-stream...though should be just a find/replace type operation to upgrade as the semantics remain very similar (not exactly the same, since internals are rewritten, but more in line with how streams are "supposed" to behave). +- Unified the `config.batchSize` and `config.highWaterMark` to both do the same thing: control how many rows are buffered in memory. The `ReadableStream` will manage exactly how many rows are requested from the cursor at a time. This should give better out of the box performance and help with efficient async interation. + ### pg@7.17.0 - Add support for `idle_in_transaction_session_timeout` [option](https://github.com/brianc/node-postgres/pull/2049). diff --git a/packages/pg-query-stream/index.js b/packages/pg-query-stream/index.js index 4576f5fb5..20073381d 100644 --- a/packages/pg-query-stream/index.js +++ b/packages/pg-query-stream/index.js @@ -3,9 +3,9 @@ const Cursor = require('pg-cursor') class PgQueryStream extends Readable { constructor(text, values, config = {}) { - const { batchSize = 100 } = config; + const { batchSize, highWaterMark = 100 } = config; // https://nodejs.org/api/stream.html#stream_new_stream_readable_options - super({ objectMode: true, emitClose: true, autoDestroy: true, highWaterMark: batchSize }) + super({ objectMode: true, emitClose: true, autoDestroy: true, highWaterMark: batchSize || highWaterMark }) this.cursor = new Cursor(text, values, config) // delegate Submittable callbacks to cursor diff --git a/packages/pg-query-stream/test/config.js b/packages/pg-query-stream/test/config.js index 78251c894..1634f6174 100644 --- a/packages/pg-query-stream/test/config.js +++ b/packages/pg-query-stream/test/config.js @@ -1,8 +1,26 @@ var assert = require('assert') var QueryStream = require('../') -var stream = new QueryStream('SELECT NOW()', [], { - batchSize: 88 -}) +describe('stream config options', () => { + // this is mostly for backwards compatability. + it('sets readable.highWaterMark based on batch size', () => { + var stream = new QueryStream('SELECT NOW()', [], { + batchSize: 88 + }) + assert.equal(stream._readableState.highWaterMark, 88) + }) + + it('sets readable.highWaterMark based on highWaterMark config', () => { + var stream = new QueryStream('SELECT NOW()', [], { + highWaterMark: 88 + }) + + assert.equal(stream._readableState.highWaterMark, 88) + }) -assert.equal(stream._readableState.highWaterMark, 88) + it('defaults to 100 for highWaterMark', () => { + var stream = new QueryStream('SELECT NOW()', []) + + assert.equal(stream._readableState.highWaterMark, 100) + }) +}) From a046a5a4a5b86a035c4f04200e271ff59d426951 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Thu, 9 Jan 2020 22:40:22 -0800 Subject: [PATCH 0580/1037] Fix typo in changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d7f86170..b385e0e00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ We do not include break-fix version release in this file. - [Rewrote stream internals](https://github.com/brianc/node-postgres/pull/2051) to better conform to node stream semantics. This should make pg-query-stream much better at respecting [highWaterMark](https://nodejs.org/api/stream.html#stream_new_stream_readable_options) and getting rid of some edge case bugs when using pg-query-stream as an async iterator. Due to the size and nature of this change (effectively a full re-write) it's safest to bump the semver major here, though almost all tests remain untouched and still passing, which brings us to a breaking change to the API.... - Changed `stream.close` to `stream.destroy` which is the [official](https://nodejs.org/api/stream.html#stream_readable_destroy_error) way to terminate a readable stream. This is a __breaking change__ if you rely on the `stream.close` method on pg-query-stream...though should be just a find/replace type operation to upgrade as the semantics remain very similar (not exactly the same, since internals are rewritten, but more in line with how streams are "supposed" to behave). -- Unified the `config.batchSize` and `config.highWaterMark` to both do the same thing: control how many rows are buffered in memory. The `ReadableStream` will manage exactly how many rows are requested from the cursor at a time. This should give better out of the box performance and help with efficient async interation. +- Unified the `config.batchSize` and `config.highWaterMark` to both do the same thing: control how many rows are buffered in memory. The `ReadableStream` will manage exactly how many rows are requested from the cursor at a time. This should give better out of the box performance and help with efficient async iteration. ### pg@7.17.0 From 5cf8f5f8d7f59d8374180589db1bfa4b06751539 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 10 Jan 2020 09:22:00 -0600 Subject: [PATCH 0581/1037] Publish - pg-cursor@2.1.3 - pg-query-stream@3.0.0 - pg@7.17.1 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 6a0913471..c48e01b63 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.1.2", + "version": "2.1.3", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -21,7 +21,7 @@ "eslint-config-prettier": "^6.4.0", "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "^7.17.0", + "pg": "^7.17.1", "prettier": "^1.18.2" }, "prettier": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 359e54e2d..a4accfc49 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "2.1.2", + "version": "3.0.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -27,12 +27,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^6.2.2", - "pg": "^7.17.0", + "pg": "^7.17.1", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.1.2" + "pg-cursor": "^2.1.3" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 2fc8c856b..91e27a887 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.17.0", + "version": "7.17.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From ae3f13fad653ec46309bb7afd3e756667b7e0c2f Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Mon, 13 Jan 2020 11:00:01 -0800 Subject: [PATCH 0582/1037] Fix tests skipped because of missing suffixes (#2071) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix tests skipped because of missing suffixes Mocha will happen eventually! * Skip password tests when they can’t work Will be made more visible when tests are ported to Mocha. * Add testing with a user with a password to CI Should reveal a bug in the password enumerability work, I think. * Explain new CI matrix entry for password authentication [ci skip] --- .travis.yml | 16 ++++++++++++++-- ...mic-password.js => dynamic-password-tests.js} | 5 +++++ ...set-keepalives.js => set-keepalives-tests.js} | 0 3 files changed, 19 insertions(+), 2 deletions(-) rename packages/pg/test/integration/connection/{dynamic-password.js => dynamic-password-tests.js} (97%) rename packages/pg/test/unit/client/{set-keepalives.js => set-keepalives-tests.js} (100%) diff --git a/.travis.yml b/.travis.yml index 03849285a..61a7a79af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: node_js dist: bionic -before_script: - - node packages/pg/script/create-test-tables.js pg://postgres@127.0.0.1:5432/postgres +before_script: | + node packages/pg/script/create-test-tables.js postgresql:/// env: - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres @@ -17,6 +17,18 @@ addons: matrix: include: + # Run tests/paths that require password authentication + - node_js: lts/erbium + env: + - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres PGPASSWORD=test-password + before_script: | + sudo -u postgres sed -i \ + -e '/^local/ s/trust$/peer/' \ + -e '/^host/ s/trust$/md5/' \ + /etc/postgresql/10/main/pg_hba.conf + sudo -u postgres psql -c "ALTER ROLE postgres PASSWORD 'test-password'; SELECT pg_reload_conf()" + node packages/pg/script/create-test-tables.js postgresql:/// + - node_js: lts/carbon addons: postgresql: "9.5" diff --git a/packages/pg/test/integration/connection/dynamic-password.js b/packages/pg/test/integration/connection/dynamic-password-tests.js similarity index 97% rename from packages/pg/test/integration/connection/dynamic-password.js rename to packages/pg/test/integration/connection/dynamic-password-tests.js index ebda433c1..20b509533 100644 --- a/packages/pg/test/integration/connection/dynamic-password.js +++ b/packages/pg/test/integration/connection/dynamic-password-tests.js @@ -8,6 +8,11 @@ const Client = pg.Client; const password = process.env.PGPASSWORD || null const sleep = millis => new Promise(resolve => setTimeout(resolve, millis)) +if (!password) { + // skip these tests; no password will be requested + return +} + suite.testAsync('Get password from a sync function', () => { let wasCalled = false function getPassword() { diff --git a/packages/pg/test/unit/client/set-keepalives.js b/packages/pg/test/unit/client/set-keepalives-tests.js similarity index 100% rename from packages/pg/test/unit/client/set-keepalives.js rename to packages/pg/test/unit/client/set-keepalives-tests.js From d456f1cda036aef063c2e3223f88f776072bde8a Mon Sep 17 00:00:00 2001 From: Daniel Hritzkiv Date: Tue, 14 Jan 2020 11:00:55 -0500 Subject: [PATCH 0583/1037] Update package.json (#2074) Change the homepage URL's scheme to https --- packages/pg/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg/package.json b/packages/pg/package.json index 91e27a887..87e7a1eb1 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -11,7 +11,7 @@ "postgresql", "rdbms" ], - "homepage": "http://github.com/brianc/node-postgres", + "homepage": "https://github.com/brianc/node-postgres", "repository": { "type": "git", "url": "git://github.com/brianc/node-postgres.git" From ee8d32f97cd5e5907c8cd9d815c7fe57a7031f7f Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 15 Jan 2020 12:59:26 -0800 Subject: [PATCH 0584/1037] Deprecate implicit TLS `rejectUnauthorized: false` (#2075) Yes, it treats `undefined` as `false`. Discussion in #2009. Introduced unintentionally in pg 0.8.7. --- packages/pg/lib/compat/warn-deprecation.js | 4 ++-- packages/pg/lib/connection-fast.js | 5 +++++ packages/pg/lib/connection.js | 5 +++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/pg/lib/compat/warn-deprecation.js b/packages/pg/lib/compat/warn-deprecation.js index 362183558..558275900 100644 --- a/packages/pg/lib/compat/warn-deprecation.js +++ b/packages/pg/lib/compat/warn-deprecation.js @@ -5,7 +5,7 @@ const util = require('util') const dummyFunctions = new Map() // Node 4 doesn’t support process.emitWarning(message, 'DeprecationWarning', code). -const emitDeprecationWarning = (message, code) => { +const warnDeprecation = (message, code) => { let dummy = dummyFunctions.get(code) if (dummy === undefined) { @@ -16,4 +16,4 @@ const emitDeprecationWarning = (message, code) => { dummy() } -module.exports = emitDeprecationWarning +module.exports = warnDeprecation diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index 38f55bdcd..a31d92a20 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -15,6 +15,8 @@ var Writer = require('buffer-writer') // eslint-disable-next-line var PacketStream = require('pg-packet-stream') +var warnDeprecation = require('./compat/warn-deprecation') + var TEXT_MODE = 0 // TODO(bmc) support binary mode here @@ -105,6 +107,9 @@ Connection.prototype.connect = function (port, host) { secureOptions: self.ssl.secureOptions, NPNProtocols: self.ssl.NPNProtocols } + if (typeof self.ssl.rejectUnauthorized !== 'boolean') { + warnDeprecation('Implicit disabling of certificate verification is deprecated and will be removed in pg 8. Specify `rejectUnauthorized: true` to require a valid CA or `rejectUnauthorized: false` to explicitly opt out of MITM protection.', 'PG-SSL-VERIFY') + } if (net.isIP(host) === 0) { options.servername = host } diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 4fae92083..435c1a965 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -14,6 +14,8 @@ var util = require('util') var Writer = require('buffer-writer') var Reader = require('packet-reader') +var warnDeprecation = require('./compat/warn-deprecation') + var TEXT_MODE = 0 var BINARY_MODE = 1 var Connection = function (config) { @@ -103,6 +105,9 @@ Connection.prototype.connect = function (port, host) { secureOptions: self.ssl.secureOptions, NPNProtocols: self.ssl.NPNProtocols } + if (typeof self.ssl.rejectUnauthorized !== 'boolean') { + warnDeprecation('Implicit disabling of certificate verification is deprecated and will be removed in pg 8. Specify `rejectUnauthorized: true` to require a valid CA or `rejectUnauthorized: false` to explicitly opt out of MITM protection.', 'PG-SSL-VERIFY') + } if (net.isIP(host) === 0) { options.servername = host } From 3f6760c62ee2a901d374b5e50c2f025b7d550315 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 15 Jan 2020 15:44:08 -0800 Subject: [PATCH 0585/1037] Update copyright years MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit because someone will make a PR otherwise. No, this isn’t actually necessary. --- LICENSE | 2 +- README.md | 2 +- packages/pg-query-stream/README.md | 2 +- packages/pg/README.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/LICENSE b/LICENSE index 389a2783c..aa66489de 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2010 - 2019 Brian Carlson +Copyright (c) 2010 - 2020 Brian 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 diff --git a/README.md b/README.md index 2207db8a1..20dee38db 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ The causes and solutions to common errors can be found among the [Frequently Ask ## License -Copyright (c) 2010-2019 Brian Carlson (brian.m.carlson@gmail.com) +Copyright (c) 2010-2020 Brian Carlson (brian.m.carlson@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/packages/pg-query-stream/README.md b/packages/pg-query-stream/README.md index 312387aa7..043928ad5 100644 --- a/packages/pg-query-stream/README.md +++ b/packages/pg-query-stream/README.md @@ -47,7 +47,7 @@ I'm very open to contribution! Open a pull request with your code or idea and w The MIT License (MIT) -Copyright (c) 2013-2019 Brian M. Carlson +Copyright (c) 2013-2020 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 diff --git a/packages/pg/README.md b/packages/pg/README.md index adf0eba12..ba5de31bd 100644 --- a/packages/pg/README.md +++ b/packages/pg/README.md @@ -69,7 +69,7 @@ The causes and solutions to common errors can be found among the [Frequently Ask ## License -Copyright (c) 2010-2019 Brian Carlson (brian.m.carlson@gmail.com) +Copyright (c) 2010-2020 Brian Carlson (brian.m.carlson@gmail.com) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 727f1a0ee371a0ee04887aff2e0cf46883c720dd Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 28 Jan 2020 10:53:29 -0600 Subject: [PATCH 0586/1037] Do not return broken clients to the pool (#2083) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Prevent requeuing a broken client If a client is not queryable, the pool should prevent requeuing instead of strictly enforcing errors to be propagated back to it. * Write tests for change * Use node 13.6 in travis Some weird behavior changed w/ async iteration in node 13.7...I'm not sure if this was an unintentional break or not but it definitely diverges in behavior from node 12 and earlier versions in node 13...so for now going to run tests on 13.6 to unblock the tests from running while I track this down. * Update packages/pg-pool/test/releasing-clients.js Co-Authored-By: Charmander <~@charmander.me> * Update .travis.yml Co-authored-by: Johannes Würbach Co-authored-by: Charmander <~@charmander.me> --- .travis.yml | 5 +- packages/pg-pool/index.js | 9 +++- packages/pg-pool/test/releasing-clients.js | 54 ++++++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 packages/pg-pool/test/releasing-clients.js diff --git a/.travis.yml b/.travis.yml index 61a7a79af..b00d6e695 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,7 +10,10 @@ env: node_js: - lts/dubnium - lts/erbium - - 13 + # node 13.7 seems to have changed behavior of async iterators exiting early on streams + # if 13.8 still has this problem when it comes down I'll talk to the node team about the change + # in the mean time...peg to 13.6 + - 13.6 addons: postgresql: "10" diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 1c7faf210..83ec51e09 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -25,6 +25,10 @@ class PendingItem { } } +function throwOnDoubleRelease () { + throw new Error('Release called on client which has already been released to the pool.') +} + function promisify (Promise, callback) { if (callback) { return { callback: callback, result: undefined } @@ -244,7 +248,7 @@ class Pool extends EventEmitter { client.release = (err) => { if (released) { - throw new Error('Release called on client which has already been released to the pool.') + throwOnDoubleRelease() } released = true @@ -280,7 +284,8 @@ class Pool extends EventEmitter { _release (client, idleListener, err) { client.on('error', idleListener) - if (err || this.ending) { + // TODO(bmc): expose a proper, public interface _queryable and _ending + if (err || this.ending || !client._queryable || client._ending) { this._remove(client) this._pulseQueue() return diff --git a/packages/pg-pool/test/releasing-clients.js b/packages/pg-pool/test/releasing-clients.js new file mode 100644 index 000000000..da8e09c16 --- /dev/null +++ b/packages/pg-pool/test/releasing-clients.js @@ -0,0 +1,54 @@ +const Pool = require('../') + +const expect = require('expect.js') +const net = require('net') + +describe('releasing clients', () => { + it('removes a client which cannot be queried', async () => { + // make a pool w/ only 1 client + const pool = new Pool({ max: 1 }) + expect(pool.totalCount).to.eql(0) + const client = await pool.connect() + expect(pool.totalCount).to.eql(1) + expect(pool.idleCount).to.eql(0) + // reach into the client and sever its connection + client.connection.end() + + // wait for the client to error out + const err = await new Promise((resolve) => client.once('error', resolve)) + expect(err).to.be.ok() + expect(pool.totalCount).to.eql(1) + expect(pool.idleCount).to.eql(0) + + // try to return it to the pool - this removes it because its broken + client.release() + expect(pool.totalCount).to.eql(0) + expect(pool.idleCount).to.eql(0) + + // make sure pool still works + const { rows } = await pool.query('SELECT NOW()') + expect(rows).to.have.length(1) + await pool.end() + }) + + it('removes a client which is ending', async () => { + // make a pool w/ only 1 client + const pool = new Pool({ max: 1 }) + expect(pool.totalCount).to.eql(0) + const client = await pool.connect() + expect(pool.totalCount).to.eql(1) + expect(pool.idleCount).to.eql(0) + // end the client gracefully (but you shouldn't do this with pooled clients) + client.end() + + // try to return it to the pool + client.release() + expect(pool.totalCount).to.eql(0) + expect(pool.idleCount).to.eql(0) + + // make sure pool still works + const { rows } = await pool.query('SELECT NOW()') + expect(rows).to.have.length(1) + await pool.end() + }) +}) From 0ff40e733b58096dd3e14a7a1c787a22058f54a1 Mon Sep 17 00:00:00 2001 From: Daniel Rozenberg Date: Tue, 28 Jan 2020 19:28:03 -0500 Subject: [PATCH 0587/1037] host= query param takes precedence --- index.js | 5 ++++- test/parse.js | 13 +++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/index.js b/index.js index 3cabb372f..29d3653c5 100644 --- a/index.js +++ b/index.js @@ -35,7 +35,10 @@ function parse(str) { config.client_encoding = result.query.encoding; return config; } - config.host = result.hostname; + if (!config.host) { + // Only set the host if there is no equivalent query param. + config.host = result.hostname; + } // result.pathname is not always guaranteed to have a '/' prefix (e.g. relative urls) // only strip the slash if it is present. diff --git a/test/parse.js b/test/parse.js index 4de28719e..c973fb5c8 100644 --- a/test/parse.js +++ b/test/parse.js @@ -120,6 +120,19 @@ describe('parse', function(){ (subject.database === null).should.equal(true); }); + it('configuration parameter host', function() { + var subject = parse('pg://user:pass@/dbname?host=/unix/socket'); + subject.user.should.equal('user'); + subject.password.should.equal('pass'); + subject.host.should.equal('/unix/socket'); + subject.database.should.equal('dbname'); + }); + + it('configuration parameter host overrides url host', function() { + var subject = parse('pg://user:pass@localhost/dbname?host=/unix/socket'); + subject.host.should.equal('/unix/socket'); + }); + it('configuration parameter application_name', function(){ var connectionString = 'pg:///?application_name=TheApp'; var subject = parse(connectionString); From b309db074ff545ed93c6396a98029b5cce7b943d Mon Sep 17 00:00:00 2001 From: Daniel Rozenberg Date: Tue, 28 Jan 2020 19:29:38 -0500 Subject: [PATCH 0588/1037] Support URL-encoded socket names --- index.js | 10 ++++++++-- test/parse.js | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 29d3653c5..7cfc82938 100644 --- a/index.js +++ b/index.js @@ -40,11 +40,17 @@ function parse(str) { config.host = result.hostname; } + // If the host is missing it might be a URL-encoded path to a socket. + var pathname = result.pathname; + if (!config.host && pathname && pathname.toLowerCase().startsWith('%2f')) { + var pathnameSplit = pathname.split('/'); + config.host = decodeURIComponent(pathnameSplit[0]); + pathname = pathnameSplit.splice(1).join('/'); + } // result.pathname is not always guaranteed to have a '/' prefix (e.g. relative urls) // only strip the slash if it is present. - var pathname = result.pathname; if (pathname && pathname.charAt(0) === '/') { - pathname = result.pathname.slice(1) || null; + pathname = pathname.slice(1) || null; } config.database = pathname && decodeURI(pathname); diff --git a/test/parse.js b/test/parse.js index c973fb5c8..07f886e1f 100644 --- a/test/parse.js +++ b/test/parse.js @@ -133,6 +133,30 @@ describe('parse', function(){ subject.host.should.equal('/unix/socket'); }); + it('url with encoded socket', function() { + var subject = parse('pg://user:pass@%2Funix%2Fsocket/dbname'); + subject.user.should.equal('user'); + subject.password.should.equal('pass'); + subject.host.should.equal('/unix/socket'); + subject.database.should.equal('dbname'); + }); + + it('url with real host and an encoded db name', function() { + var subject = parse('pg://user:pass@localhost/%2Fdbname'); + subject.user.should.equal('user'); + subject.password.should.equal('pass'); + subject.host.should.equal('localhost'); + subject.database.should.equal('%2Fdbname'); + }); + + it('configuration parameter host treats encoded socket as part of the db name', function() { + var subject = parse('pg://user:pass@%2Funix%2Fsocket/dbname?host=localhost'); + subject.user.should.equal('user'); + subject.password.should.equal('pass'); + subject.host.should.equal('localhost'); + subject.database.should.equal('%2Funix%2Fsocket/dbname'); + }); + it('configuration parameter application_name', function(){ var connectionString = 'pg:///?application_name=TheApp'; var subject = parse(connectionString); From 7ec9b70180b5aaadb75c4fde3f35ff86031ce279 Mon Sep 17 00:00:00 2001 From: Daniel Rozenberg Date: Tue, 28 Jan 2020 19:40:51 -0500 Subject: [PATCH 0589/1037] Use regex instead of startsWith which is unsupported in node 0.10 --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 7cfc82938..7e914ba1b 100644 --- a/index.js +++ b/index.js @@ -42,7 +42,7 @@ function parse(str) { // If the host is missing it might be a URL-encoded path to a socket. var pathname = result.pathname; - if (!config.host && pathname && pathname.toLowerCase().startsWith('%2f')) { + if (!config.host && pathname && /^%2f/i.test(pathname)) { var pathnameSplit = pathname.split('/'); config.host = decodeURIComponent(pathnameSplit[0]); pathname = pathnameSplit.splice(1).join('/'); From 11ab1daaddd6d77238e4ea5bbbeb7f3a9041746c Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 29 Jan 2020 10:18:20 -0600 Subject: [PATCH 0590/1037] Close connection on SSL connection errors (#2082) * Close connection on SSL connection errors Fixes #2079 * Fix test * Remove console.log * Fix tests, implement same behavior for native client * Fix tests --- packages/pg-pool/test/error-handling.js | 8 +-- packages/pg/lib/connection.js | 21 ++++++- packages/pg/lib/native/client.js | 5 +- .../test/integration/gh-issues/2056-tests.js | 1 + .../test/integration/gh-issues/2079-tests.js | 56 +++++++++++++++++++ 5 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 packages/pg/test/integration/gh-issues/2079-tests.js diff --git a/packages/pg-pool/test/error-handling.js b/packages/pg-pool/test/error-handling.js index 72d97ede0..90de4ec41 100644 --- a/packages/pg-pool/test/error-handling.js +++ b/packages/pg-pool/test/error-handling.js @@ -211,14 +211,14 @@ describe('pool error handling', function () { const pool = new Pool({ max: 1, port: closeServer.address().port, host: 'localhost' }) pool.connect((err) => { expect(err).to.be.an(Error) - if (err.errno) { - expect(err.errno).to.be('ECONNRESET') + if (err.code) { + expect(err.code).to.be('ECONNRESET') } }) pool.connect((err) => { expect(err).to.be.an(Error) - if (err.errno) { - expect(err.errno).to.be('ECONNRESET') + if (err.code) { + expect(err.code).to.be('ECONNRESET') } closeServer.close(() => { pool.end(done) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 435c1a965..6fa0696c9 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -85,11 +85,13 @@ Connection.prototype.connect = function (port, host) { this.stream.once('data', function (buffer) { var responseCode = buffer.toString('utf8') switch (responseCode) { - case 'N': // Server does not support SSL connections - return self.emit('error', new Error('The server does not support SSL connections')) case 'S': // Server supports SSL connections, continue with a secure connection break + case 'N': // Server does not support SSL connections + self.stream.end() + return self.emit('error', new Error('The server does not support SSL connections')) default: // Any other response byte, including 'E' (ErrorResponse) indicating a server error + self.stream.end() return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') @@ -112,9 +114,18 @@ Connection.prototype.connect = function (port, host) { options.servername = host } self.stream = tls.connect(options) - self.attachListeners(self.stream) self.stream.on('error', reportStreamError) + // send SSLRequest packet + const buff = Buffer.alloc(8) + buff.writeUInt32BE(8) + buff.writeUInt32BE(80877103, 4) + if (self.stream.writable) { + self.stream.write(buff) + } + + self.attachListeners(self.stream) + self.emit('sslconnect') }) } @@ -345,6 +356,10 @@ Connection.prototype.end = function () { // 0x58 = 'X' this.writer.add(emptyBuffer) this._ending = true + if (!this.stream.writable) { + this.stream.end() + return + } return this.stream.write(END_BUFFER, () => { this.stream.end() }) diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index 6859bc2cc..581ef72d1 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -89,7 +89,10 @@ Client.prototype._connect = function (cb) { this.connectionParameters.getLibpqConnectionString(function (err, conString) { if (err) return cb(err) self.native.connect(conString, function (err) { - if (err) return cb(err) + if (err) { + self.native.end() + return cb(err) + } // set internal states to connected self._connected = true diff --git a/packages/pg/test/integration/gh-issues/2056-tests.js b/packages/pg/test/integration/gh-issues/2056-tests.js index f2912fc62..e025a1adc 100644 --- a/packages/pg/test/integration/gh-issues/2056-tests.js +++ b/packages/pg/test/integration/gh-issues/2056-tests.js @@ -5,6 +5,7 @@ var assert = require('assert') const suite = new helper.Suite() + suite.test('All queries should return a result array', (done) => { const client = new helper.pg.Client() client.connect() diff --git a/packages/pg/test/integration/gh-issues/2079-tests.js b/packages/pg/test/integration/gh-issues/2079-tests.js new file mode 100644 index 000000000..bec8e481f --- /dev/null +++ b/packages/pg/test/integration/gh-issues/2079-tests.js @@ -0,0 +1,56 @@ + +"use strict" +var helper = require('./../test-helper') +var assert = require('assert') + +const suite = new helper.Suite() + +// makes a backend server that responds with a non 'S' ssl response buffer +let makeTerminatingBackend = (byte) => { + const { createServer } = require('net') + + const server = createServer((socket) => { + // attach a listener so the socket can drain + // https://www.postgresql.org/docs/9.3/protocol-message-formats.html + socket.on('data', (buff) => { + const code = buff.readInt32BE(4) + // I don't see anything in the docs about 80877104 + // but libpq is sending it... + if (code === 80877103 || code === 80877104) { + const packet = Buffer.from(byte, 'utf-8') + socket.write(packet) + } + }) + socket.on('close', () => { + server.close() + }) + }) + + server.listen() + const { port } = server.address() + return port +} + +suite.test('SSL connection error allows event loop to exit', (done) => { + const port = makeTerminatingBackend('N') + const client = new helper.pg.Client({ ssl: 'require', port }) + // since there was a connection error the client's socket should be closed + // and the event loop will have no refs and exit cleanly + client.connect((err) => { + assert(err instanceof Error) + done() + }) +}) + + +suite.test('Non "S" response code allows event loop to exit', (done) => { + const port = makeTerminatingBackend('X') + const client = new helper.pg.Client({ ssl: 'require', port }) + // since there was a connection error the client's socket should be closed + // and the event loop will have no refs and exit cleanly + client.connect((err) => { + assert(err instanceof Error) + done() + }) +}) + From 717ffd0e70875d281b066be88c434572ee46bfa0 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 29 Jan 2020 10:46:03 -0600 Subject: [PATCH 0591/1037] Update ignores --- .gitignore | 1 + lerna.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index df95fda07..bae2a20a1 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ package-lock.json *.swp dist .DS_Store +.vscode/ diff --git a/lerna.json b/lerna.json index dbbf2c9c5..eb366709a 100644 --- a/lerna.json +++ b/lerna.json @@ -6,6 +6,7 @@ "useWorkspaces": true, "version": "independent", "ignoreChanges": [ - "**/*.md" + "**/*.md", + "**/test/**" ] } From d9fcda8cf7a3519bde4799039aef94daec3fbef6 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 29 Jan 2020 10:48:38 -0600 Subject: [PATCH 0592/1037] Publish - pg-cursor@2.1.4 - pg-pool@2.0.10 - pg-query-stream@3.0.1 - pg@7.18.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index c48e01b63..78a124113 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.1.3", + "version": "2.1.4", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -21,7 +21,7 @@ "eslint-config-prettier": "^6.4.0", "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "^7.17.1", + "pg": "^7.18.0", "prettier": "^1.18.2" }, "prettier": { diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index dc0275699..3813df242 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "2.0.9", + "version": "2.0.10", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index a4accfc49..7b02f4b51 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.0.0", + "version": "3.0.1", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -27,12 +27,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^6.2.2", - "pg": "^7.17.1", + "pg": "^7.18.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.1.3" + "pg-cursor": "^2.1.4" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 87e7a1eb1..428b5a3b9 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.17.1", + "version": "7.18.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "packet-reader": "1.0.0", "pg-connection-string": "0.1.3", "pg-packet-stream": "^1.1.0", - "pg-pool": "^2.0.9", + "pg-pool": "^2.0.10", "pg-types": "^2.1.0", "pgpass": "1.x", "semver": "4.3.2" From c0df3b3e954a1e45646ec5abd1467d12bde94637 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 29 Jan 2020 10:53:59 -0600 Subject: [PATCH 0593/1037] Update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b385e0e00..6390d3825 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### pg@7.18.0 + +- This will likely be the last minor release before pg@8.0. +- This version contains a few bug fixes and adds a deprecation warning for [a pending change in 8.0](https://github.com/brianc/node-postgres/issues/2009#issuecomment-579371651) which will flip the default behavior over SSL from `rejectUnauthorized` from `false` to `true` making things more secure in the general use case. + ### pg-query-stream@3.0.0 - [Rewrote stream internals](https://github.com/brianc/node-postgres/pull/2051) to better conform to node stream semantics. This should make pg-query-stream much better at respecting [highWaterMark](https://nodejs.org/api/stream.html#stream_new_stream_readable_options) and getting rid of some edge case bugs when using pg-query-stream as an async iterator. Due to the size and nature of this change (effectively a full re-write) it's safest to bump the semver major here, though almost all tests remain untouched and still passing, which brings us to a breaking change to the API.... From 5be3d95f624e70153a8516f44bfb38b9be706ddf Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 29 Jan 2020 18:10:23 -0600 Subject: [PATCH 0594/1037] Remove double-send of ssl request packet (#2086) * Remove double-send of ssl request packet I missed the fact that we are already sending this. Since I don't have good test coverage for ssl [which I am planning on fixing next](https://github.com/brianc/node-postgres/issues/2009) this got missed. I'm forcing an SSL test on travis. This will break for me locally as I don't have SSL enabled on my local test DB. Something I will also remedy. --- .gitignore | 1 + packages/pg/lib/connection.js | 10 ---------- .../pg/test/integration/gh-issues/2085-tests.js | 15 +++++++++++++++ 3 files changed, 16 insertions(+), 10 deletions(-) create mode 100644 packages/pg/test/integration/gh-issues/2085-tests.js diff --git a/.gitignore b/.gitignore index bae2a20a1..b6e058f2e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ package-lock.json dist .DS_Store .vscode/ +manually-test-on-heroku.js diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 6fa0696c9..a63d9cde7 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -115,17 +115,7 @@ Connection.prototype.connect = function (port, host) { } self.stream = tls.connect(options) self.stream.on('error', reportStreamError) - - // send SSLRequest packet - const buff = Buffer.alloc(8) - buff.writeUInt32BE(8) - buff.writeUInt32BE(80877103, 4) - if (self.stream.writable) { - self.stream.write(buff) - } - self.attachListeners(self.stream) - self.emit('sslconnect') }) } diff --git a/packages/pg/test/integration/gh-issues/2085-tests.js b/packages/pg/test/integration/gh-issues/2085-tests.js new file mode 100644 index 000000000..36f30c747 --- /dev/null +++ b/packages/pg/test/integration/gh-issues/2085-tests.js @@ -0,0 +1,15 @@ + + +"use strict" +var helper = require('./../test-helper') +var assert = require('assert') + +const suite = new helper.Suite() + +suite.testAsync('it should connect over ssl', async () => { + const client = new helper.pg.Client({ ssl: 'require'}) + await client.connect() + const { rows } = await client.query('SELECT NOW()') + assert.strictEqual(rows.length, 1) + await client.end() +}) From b3f0728a1102772a5c6320c78c2533354d78a39b Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 29 Jan 2020 18:20:42 -0600 Subject: [PATCH 0595/1037] Publish - pg-cursor@2.1.5 - pg-query-stream@3.0.2 - pg@7.18.1 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 78a124113..67bfcf2fc 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.1.4", + "version": "2.1.5", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -21,7 +21,7 @@ "eslint-config-prettier": "^6.4.0", "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "^7.18.0", + "pg": "^7.18.1", "prettier": "^1.18.2" }, "prettier": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 7b02f4b51..6b591aeed 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.0.1", + "version": "3.0.2", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -27,12 +27,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^6.2.2", - "pg": "^7.18.0", + "pg": "^7.18.1", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.1.4" + "pg-cursor": "^2.1.5" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 428b5a3b9..1872880d9 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.18.0", + "version": "7.18.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From e404dd517e80a5f2e3b228788ad5d4f71cc20072 Mon Sep 17 00:00:00 2001 From: Karl Becker Date: Thu, 13 Feb 2020 14:13:46 -0500 Subject: [PATCH 0596/1037] Little typo fix, and add GitHub Sponsors (#2104) Since I believe GitHub Sponsors is your preferred way to donate now, maybe you want to totally get rid of the mention of Patreon, or mention that GitHub Sponsors is preferred? --- SPONSORS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SPONSORS.md b/SPONSORS.md index 6e3ba707e..211dfb996 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -1,4 +1,4 @@ -node-postgres is made possible by the helpful contributors from the community well as the following generous supporters on [Patreon](https://www.patreon.com/node_postgres). +node-postgres is made possible by the helpful contributors from the community as well as the following generous supporters on [GitHub Sponsors](https://github.com/sponsors/brianc) and [Patreon](https://www.patreon.com/node_postgres). # Leaders From 823153138fefc63c5767508d5522cdf58902b1f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Bra=C5=A1na?= Date: Fri, 14 Feb 2020 17:23:41 +0100 Subject: [PATCH 0597/1037] Destroy socket when there was an error on it (#1975) When error happens on socket, potentially dead socket is kept open indefinitely by calling "connection.end()". Similar issue is that it keeps socket open until long-running query is finished even though the connection was ended. --- packages/pg/lib/client.js | 2 +- .../connection-pool/error-tests.js | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 93807e48c..05efbdc5a 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -545,7 +545,7 @@ Client.prototype.query = function (config, values, callback) { Client.prototype.end = function (cb) { this._ending = true - if (this.activeQuery) { + if (this.activeQuery || !this._queryable) { // if we have an active query we need to force a disconnect // on the socket - otherwise a hung query could block end forever this.connection.stream.destroy() diff --git a/packages/pg/test/integration/connection-pool/error-tests.js b/packages/pg/test/integration/connection-pool/error-tests.js index 597c29b38..9fe760431 100644 --- a/packages/pg/test/integration/connection-pool/error-tests.js +++ b/packages/pg/test/integration/connection-pool/error-tests.js @@ -1,6 +1,7 @@ 'use strict' var helper = require('./test-helper') const pg = helper.pg +const native = helper.args.native const suite = new helper.Suite() suite.test('connecting to invalid port', (cb) => { @@ -99,3 +100,31 @@ suite.test('connection-level errors cause future queries to fail', (cb) => { })) })) }) + +suite.test('handles socket error during pool.query and destroys it immediately', (cb) => { + const pool = new pg.Pool({ max: 1 }) + + if (native) { + pool.query('SELECT pg_sleep(10)', [], (err) => { + assert.equal(err.message, 'canceling statement due to user request') + cb() + }) + + setTimeout(() => { + pool._clients[0].native.cancel((err) => { + assert.ifError(err) + }) + }, 100) + } else { + pool.query('SELECT pg_sleep(10)', [], (err) => { + assert.equal(err.message, 'network issue') + assert.equal(stream.destroyed, true) + cb() + }) + + const stream = pool._clients[0].connection.stream + setTimeout(() => { + stream.emit('error', new Error('network issue')) + }, 100) + } +}) From b4e0ba329ade3d976e0804dd0d79438274e7233f Mon Sep 17 00:00:00 2001 From: "Dustin J. Mitchell" Date: Sun, 16 Feb 2020 12:30:46 -0500 Subject: [PATCH 0598/1037] Include documentation on the URL format in the README This summarizes the common forms, but omits some of the more particular, and unnecessary forms, such as specifying UNIX domain sockets with `pg://` URLs. --- README.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/README.md b/README.md index 4943d885b..d5b45ab9e 100644 --- a/README.md +++ b/README.md @@ -19,3 +19,54 @@ var parse = require('pg-connection-string').parse; var config = parse('postgres://someuser:somepassword@somehost:381/somedatabase') ``` + +The resulting config contains a subset of the following properties: + +* `host` - Postgres server hostname or, for UNIX doamain sockets, the socket filename +* `port` - port on which to connect +* `user` - User with which to authenticate to the server +* `password` - Corresponding password +* `database` - Database name within the server +* `client_encoding` - string encoding the client will use +* `ssl`, either a boolean or an object with properties + * `cert` + * `key` + * `ca` +* any other query parameters (for example, `application_name`) are preserved intact. + +## Connection Strings + +The short summary of acceptable URLs is: + + * `socket:?` - UNIX domain socket + * `postgres://:@:/?` - TCP connection + +But see below for more details. + +### UNIX Domain Sockets + +When user and password are not given, the socket path follows `socket:`, as in `socket:/var/run/pgsql`. +This form can be shortened to just a path: `/var/run/pgsql`. + +When user and password are given, they are included in the typical URL positions, with an empty `host`, as in `socket://user:pass@/var/run/pgsql`. + +Query parameters follow a `?` character, including the following special query parameters: + + * `db=` - sets the database name (urlencoded) + * `encoding=` - sets the `client_encoding` property + +### TCP Connections + +TCP connections to the Postgres server are indicated with `pg:` or `postgres:` schemes (in fact, any scheme but `socket:` is accepted). +If username and password are included, they should be urlencoded. +The database name, however, should *not* be urlencoded. + +Query parameters follow a `?` character, including the following special query parameters: + * `host=` - sets `host` property, overriding the URL's host + * `encoding=` - sets the `client_encoding` property + * `ssl=1`, `ssl=true`, `ssl=0`, `ssl=false` - sets `ssl` to true or false, accordingly + * `sslcert=` - reads data from the given file and includes the result as `ssl.cert` + * `sslkey=` - reads data from the given file and includes the result as `ssl.key` + * `sslrootcert=` - reads data from the given file and includes the result as `ssl.ca` + +A bare relative URL, such as `salesdata`, will indicate a database name while leaving other properties empty. From c2f4b284b1748562244fa56bcaa250413c00c454 Mon Sep 17 00:00:00 2001 From: Kyle Lilly Date: Wed, 19 Feb 2020 13:12:47 -0500 Subject: [PATCH 0599/1037] Implement handleEmptyQuery for pg-query-stream. (#2106) --- packages/pg-query-stream/index.js | 1 + packages/pg-query-stream/test/empty-query.js | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 packages/pg-query-stream/test/empty-query.js diff --git a/packages/pg-query-stream/index.js b/packages/pg-query-stream/index.js index 20073381d..20c56b387 100644 --- a/packages/pg-query-stream/index.js +++ b/packages/pg-query-stream/index.js @@ -15,6 +15,7 @@ class PgQueryStream extends Readable { this.handleCommandComplete = this.cursor.handleCommandComplete.bind(this.cursor) this.handleReadyForQuery = this.cursor.handleReadyForQuery.bind(this.cursor) this.handleError = this.cursor.handleError.bind(this.cursor) + this.handleEmptyQuery = this.cursor.handleEmptyQuery.bind(this.cursor) } submit(connection) { diff --git a/packages/pg-query-stream/test/empty-query.js b/packages/pg-query-stream/test/empty-query.js new file mode 100644 index 000000000..756031747 --- /dev/null +++ b/packages/pg-query-stream/test/empty-query.js @@ -0,0 +1,20 @@ +const assert = require('assert') +const helper = require('./helper') +const QueryStream = require('../') + +helper('empty-query', function (client) { + it('handles empty query', function(done) { + const stream = new QueryStream('-- this is a comment', []) + const query = client.query(stream) + query.on('end', function () { + // nothing should happen for empty query + done(); + }).on('data', function () { + // noop to kick off reading + }) + }) + + it('continues to function after stream', function (done) { + client.query('SELECT NOW()', done) + }) +}) \ No newline at end of file From 069c2e4ba70655202ad5fb07c145a053018a0606 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 20 Feb 2020 10:32:38 -0600 Subject: [PATCH 0600/1037] Update sponsors --- README.md | 16 +++++++++++++--- SPONSORS.md | 1 + packages/pg/README.md | 16 +++++++++++++--- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 20dee38db..b3c921327 100644 --- a/README.md +++ b/README.md @@ -50,11 +50,21 @@ When you open an issue please provide: You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on Twitter. -### Sponsorship :star: +## Sponsorship :two_hearts: -[If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable please consider supporting](https://github.com/sponsors/brianc) its development. +node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) and these featured sponsors: -Also, you can view a historical list of all [previous and existing sponsors](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md). +
+ + + + + + + +
+ +If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable [please consider supporting](https://github.com/sponsors/brianc) its development. ## Contributing diff --git a/SPONSORS.md b/SPONSORS.md index 211dfb996..9b0431654 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -6,6 +6,7 @@ node-postgres is made possible by the helpful contributors from the community as - [Third Iron](https://thirdiron.com/) - [Timescale](https://timescale.com) - [Nafundi](https://nafundi.com) +- [CrateDB](https://crate.io/) # Supporters diff --git a/packages/pg/README.md b/packages/pg/README.md index ba5de31bd..0d7953f4e 100644 --- a/packages/pg/README.md +++ b/packages/pg/README.md @@ -44,11 +44,21 @@ When you open an issue please provide: You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that's your thing. I try to always announce noteworthy changes & developments with node-postgres on Twitter. -### Sponsorship :star: +## Sponsorship :two_hearts: -[If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable please consider supporting](https://github.com/sponsors/brianc) its development. +node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) and these featured sponsors: -Also, you can view a historical list of all [previous and existing sponsors](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md). +
+ + + + + + + +
+ +If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable [please consider supporting](https://github.com/sponsors/brianc) its development. ## Contributing From 29877530c6f7b5ebc0bf814e3a711b4b66e4d51a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 20 Feb 2020 10:33:37 -0600 Subject: [PATCH 0601/1037] Publish - pg-cursor@2.1.6 - pg-query-stream@3.0.3 - pg@7.18.2 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 67bfcf2fc..39bcc522f 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.1.5", + "version": "2.1.6", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -21,7 +21,7 @@ "eslint-config-prettier": "^6.4.0", "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "^7.18.1", + "pg": "^7.18.2", "prettier": "^1.18.2" }, "prettier": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 6b591aeed..87d4b4560 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.0.2", + "version": "3.0.3", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -27,12 +27,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^6.2.2", - "pg": "^7.18.1", + "pg": "^7.18.2", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.1.5" + "pg-cursor": "^2.1.6" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 1872880d9..9e06af528 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.18.1", + "version": "7.18.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 1c8b6b93cfa108a0ad0e0940f1bb26ecd101087b Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 25 Feb 2020 08:48:58 -0600 Subject: [PATCH 0602/1037] Call callback when end called on unconnected client (#2109) * Call callback when end called on unconnected client Closes #2108 * Revert a bit of the change * Use readyState because pending doesn't exist in node 8.x * Update packages/pg/lib/client.js use bring your own promise Co-Authored-By: Charmander <~@charmander.me> Co-authored-by: Charmander <~@charmander.me> --- packages/pg/lib/client.js | 9 +++++++++ .../pg/test/integration/gh-issues/2108-tests.js | 13 +++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 packages/pg/test/integration/gh-issues/2108-tests.js diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 05efbdc5a..cdae3b7c2 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -545,6 +545,15 @@ Client.prototype.query = function (config, values, callback) { Client.prototype.end = function (cb) { this._ending = true + // if we have never connected, then end is a noop, callback immediately + if (this.connection.stream.readyState === 'closed') { + if (cb) { + cb() + } else { + return this._Promise.resolve() + } + } + if (this.activeQuery || !this._queryable) { // if we have an active query we need to force a disconnect // on the socket - otherwise a hung query could block end forever diff --git a/packages/pg/test/integration/gh-issues/2108-tests.js b/packages/pg/test/integration/gh-issues/2108-tests.js new file mode 100644 index 000000000..9832dae37 --- /dev/null +++ b/packages/pg/test/integration/gh-issues/2108-tests.js @@ -0,0 +1,13 @@ +"use strict" +var helper = require('./../test-helper') +const suite = new helper.Suite() + +suite.test('Closing an unconnected client calls callback', (done) => { + const client = new helper.pg.Client() + client.end(done) +}) + +suite.testAsync('Closing an unconnected client resolves promise', () => { + const client = new helper.pg.Client() + return client.end() +}) From 11d7c591fad46eb3cf15c10aef3d1454c7f14ee6 Mon Sep 17 00:00:00 2001 From: "Sam :D" <46730010+sam-g99@users.noreply.github.com> Date: Wed, 26 Feb 2020 11:49:41 -0500 Subject: [PATCH 0603/1037] typo fix (#2118) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b3c921327..d22ac0c61 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ I will __happily__ accept your pull request if it: - looks reasonable - does not break backwards compatibility -If your change involves breaking backwards compatibility please please point that out in the pull request & we can discuss & plan when and how to release it and what type of documentation or communicate it will require. +If your change involves breaking backwards compatibility please please point that out in the pull request & we can discuss & plan when and how to release it and what type of documentation or communication it will require. ## Troubleshooting and FAQ From 5233b3e77e396a368130709e762fca836290a528 Mon Sep 17 00:00:00 2001 From: "Herman J. Radtke III" Date: Thu, 19 Mar 2020 21:56:45 -0700 Subject: [PATCH 0604/1037] Release v2.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 415638f07..49345369c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "2.1.0", + "version": "2.2.0", "description": "Functions for dealing with a PostgresSQL connection string", "main": "./index.js", "types": "./index.d.ts", From c036779d9c1618011f799f853b1426736e7d5f5c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2020 10:31:04 -0500 Subject: [PATCH 0605/1037] Bump acorn from 7.1.0 to 7.1.1 (#2136) Bumps [acorn](https://github.com/acornjs/acorn) from 7.1.0 to 7.1.1. - [Release notes](https://github.com/acornjs/acorn/releases) - [Commits](https://github.com/acornjs/acorn/compare/7.1.0...7.1.1) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index e3e2dcf83..43c90a76a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -901,9 +901,9 @@ acorn-jsx@^5.1.0: integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== acorn@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.0.tgz#949d36f2c292535da602283586c2477c57eb2d6c" - integrity sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ== + version "7.1.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" + integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== agent-base@4, agent-base@^4.3.0: version "4.3.0" From aafd8ac64e588e689ed08e7957bc3c91f8fe01e3 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 30 Mar 2020 10:31:35 -0500 Subject: [PATCH 0606/1037] 8.0 Release (#2117) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Drop support for EOL versions of node (#2062) * Drop support for EOL versions of node * Re-add testing for node@8.x * Revert changes to .travis.yml * Update packages/pg-pool/package.json Co-Authored-By: Charmander <~@charmander.me> Co-authored-by: Charmander <~@charmander.me> * Remove password from stringified outputs (#2066) * Remove password from stringified outputs Theres a security concern where if you're not careful and you include your client or pool instance in console.log or stack traces it might include the database password. To widen the pit of success I'm making that field non-enumerable. You can still get at it...it just wont show up "by accident" when you're logging things now. The backwards compatiblity impact of this is very small, but it is still technically somewhat an API change so...8.0. * Implement feedback * Fix more whitespace the autoformatter changed * Simplify code a bit * Remove password from stringified outputs (#2070) * Keep ConnectionParameters’s password property writable `Client` writes to it when `password` is a function. * Avoid creating password property on pool options when it didn’t exist previously. * Allow password option to be non-enumerable to avoid breaking uses like `new Pool(existingPool.options)`. * Make password property definitions consistent in formatting and configurability. Co-authored-by: Charmander <~@charmander.me> * Make `native` non-enumerable (#2065) * Make `native` non-enumerable Making it non-enumerable means less spurious "Cannot find module" errors in your logs when iterating over `pg` objects. `Object.defineProperty` has been available since Node 0.12. See https://github.com/brianc/node-postgres/issues/1894#issuecomment-543300178 * Add test for `native` enumeration Co-authored-by: Gabe Gorelick * Use class-extends to wrap Pool (#1541) * Use class-extends to wrap Pool * Minimize diff * Test `BoundPool` inheritance Co-authored-by: Charmander <~@charmander.me> Co-authored-by: Brian C * Continue support for creating a pg.Pool from another instance’s options (#2076) * Add failing test for creating a `BoundPool` from another instance’s settings * Continue support for creating a pg.Pool from another instance’s options by dropping the requirement for the `password` property to be enumerable. * Use user name as default database when user is non-default (#1679) Not entirely backwards-compatible. * Make native client password property consistent with others i.e. configurable. * Make notice messages not an instance of Error (#2090) * Make notice messages not an instance of Error Slight API cleanup to make a notice instance the same shape as it was, but not be an instance of error. This is a backwards incompatible change though I expect the impact to be minimal. Closes #1982 * skip notice test in travis * Pin node@13.6 for regression in async iterators * Check and see if node 13.8 is still borked on async iterator * Yeah, node still has changed edge case behavior on stream * Emit notice messages on travis * Revert "Revert "Support additional tls.connect() options (#1996)" (#2010)" (#2113) This reverts commit 510a273ce45fb73d0355cf384e97ea695c8a5bcc. * Fix ssl tests (#2116) * Convert Query to an ES6 class (#2126) The last missing `new` deprecation warning for pg 8. Co-authored-by: Charmander <~@charmander.me> Co-authored-by: Gabe Gorelick Co-authored-by: Natalie Wolfe --- packages/pg-pool/index.js | 12 + packages/pg-pool/package.json | 2 +- packages/pg/Makefile | 4 +- packages/pg/lib/client.js | 11 +- packages/pg/lib/compat/check-constructor.js | 22 -- packages/pg/lib/compat/warn-deprecation.js | 19 - packages/pg/lib/connection-fast.js | 20 +- packages/pg/lib/connection-parameters.js | 16 +- packages/pg/lib/connection.js | 28 +- packages/pg/lib/defaults.js | 2 +- packages/pg/lib/index.js | 50 +-- packages/pg/lib/native/client.js | 10 +- packages/pg/lib/query.js | 374 +++++++++--------- packages/pg/package.json | 2 +- .../integration/client/configuration-tests.js | 24 +- .../test/integration/client/notice-tests.js | 32 +- .../test/integration/gh-issues/1542-tests.js | 25 ++ .../test/integration/gh-issues/1992-tests.js | 11 + .../test/integration/gh-issues/2064-tests.js | 32 ++ .../test/integration/gh-issues/2085-tests.js | 16 +- .../connection-parameters/creation-tests.js | 7 +- .../connection-pool/configuration-tests.js | 14 + 22 files changed, 416 insertions(+), 317 deletions(-) delete mode 100644 packages/pg/lib/compat/check-constructor.js delete mode 100644 packages/pg/lib/compat/warn-deprecation.js create mode 100644 packages/pg/test/integration/gh-issues/1542-tests.js create mode 100644 packages/pg/test/integration/gh-issues/1992-tests.js create mode 100644 packages/pg/test/integration/gh-issues/2064-tests.js create mode 100644 packages/pg/test/unit/connection-pool/configuration-tests.js diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 83ec51e09..e144bb83b 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -64,6 +64,18 @@ class Pool extends EventEmitter { constructor (options, Client) { super() this.options = Object.assign({}, options) + + if (options != null && 'password' in options) { + // "hiding" the password so it doesn't show up in stack traces + // or if the client is console.logged + Object.defineProperty(this.options, 'password', { + configurable: true, + enumerable: false, + writable: true, + value: options.password + }) + } + 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 diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 3813df242..8d5cf2a9d 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -34,6 +34,6 @@ "pg-cursor": "^1.3.0" }, "peerDependencies": { - "pg": ">5.0" + "pg": ">=8.0" } } diff --git a/packages/pg/Makefile b/packages/pg/Makefile index 52d0545d3..a5b0bc1da 100644 --- a/packages/pg/Makefile +++ b/packages/pg/Makefile @@ -62,6 +62,4 @@ test-pool: lint: @echo "***Starting lint***" - node -e "process.exit(Number(process.versions.node.split('.')[0]) < 8 ? 0 : 1)" \ - && echo "***Skipping lint (node version too old)***" \ - || node_modules/.bin/eslint lib + node_modules/.bin/eslint lib diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index cdae3b7c2..ac7ab4c27 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -30,7 +30,16 @@ var Client = function (config) { this.database = this.connectionParameters.database this.port = this.connectionParameters.port this.host = this.connectionParameters.host - this.password = this.connectionParameters.password + + // "hiding" the password so it doesn't show up in stack traces + // or if the client is console.logged + Object.defineProperty(this, 'password', { + configurable: true, + enumerable: false, + writable: true, + value: this.connectionParameters.password + }) + this.replication = this.connectionParameters.replication var c = config || {} diff --git a/packages/pg/lib/compat/check-constructor.js b/packages/pg/lib/compat/check-constructor.js deleted file mode 100644 index 5920633a0..000000000 --- a/packages/pg/lib/compat/check-constructor.js +++ /dev/null @@ -1,22 +0,0 @@ -'use strict' - -const warnDeprecation = require('./warn-deprecation') - -// Node 4 doesn’t support new.target. -let hasNewTarget - -try { - // eslint-disable-next-line no-eval - eval('(function () { new.target })') - hasNewTarget = true -} catch (error) { - hasNewTarget = false -} - -const checkConstructor = (name, code, getNewTarget) => { - if (hasNewTarget && getNewTarget() === undefined) { - warnDeprecation(`Constructing a ${name} without new is deprecated and will stop working in pg 8.`, code) - } -} - -module.exports = checkConstructor diff --git a/packages/pg/lib/compat/warn-deprecation.js b/packages/pg/lib/compat/warn-deprecation.js deleted file mode 100644 index 558275900..000000000 --- a/packages/pg/lib/compat/warn-deprecation.js +++ /dev/null @@ -1,19 +0,0 @@ -'use strict' - -const util = require('util') - -const dummyFunctions = new Map() - -// Node 4 doesn’t support process.emitWarning(message, 'DeprecationWarning', code). -const warnDeprecation = (message, code) => { - let dummy = dummyFunctions.get(code) - - if (dummy === undefined) { - dummy = util.deprecate(() => {}, message) - dummyFunctions.set(code, dummy) - } - - dummy() -} - -module.exports = warnDeprecation diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index a31d92a20..631ea3b0e 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -15,8 +15,6 @@ var Writer = require('buffer-writer') // eslint-disable-next-line var PacketStream = require('pg-packet-stream') -var warnDeprecation = require('./compat/warn-deprecation') - var TEXT_MODE = 0 // TODO(bmc) support binary mode here @@ -95,21 +93,9 @@ Connection.prototype.connect = function (port, host) { return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') - const options = { - socket: self.stream, - checkServerIdentity: self.ssl.checkServerIdentity || tls.checkServerIdentity, - rejectUnauthorized: self.ssl.rejectUnauthorized, - ca: self.ssl.ca, - pfx: self.ssl.pfx, - key: self.ssl.key, - passphrase: self.ssl.passphrase, - cert: self.ssl.cert, - secureOptions: self.ssl.secureOptions, - NPNProtocols: self.ssl.NPNProtocols - } - if (typeof self.ssl.rejectUnauthorized !== 'boolean') { - warnDeprecation('Implicit disabling of certificate verification is deprecated and will be removed in pg 8. Specify `rejectUnauthorized: true` to require a valid CA or `rejectUnauthorized: false` to explicitly opt out of MITM protection.', 'PG-SSL-VERIFY') - } + const options = Object.assign({ + socket: self.stream + }, self.ssl) if (net.isIP(host) === 0) { options.servername = host } diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index 0d5e0376d..cd6d3b8a9 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -52,9 +52,23 @@ var ConnectionParameters = function (config) { this.user = val('user', config) this.database = val('database', config) + + if (this.database === undefined) { + this.database = this.user + } + this.port = parseInt(val('port', config), 10) this.host = val('host', config) - this.password = val('password', config) + + // "hiding" the password so it doesn't show up in stack traces + // or if the client is console.logged + Object.defineProperty(this, 'password', { + configurable: true, + enumerable: false, + writable: true, + value: val('password', config) + }) + this.binary = val('binary', config) this.ssl = typeof config.ssl === 'undefined' ? useSsl() : config.ssl this.client_encoding = val('client_encoding', config) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index a63d9cde7..b7fde90a2 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -14,8 +14,6 @@ var util = require('util') var Writer = require('buffer-writer') var Reader = require('packet-reader') -var warnDeprecation = require('./compat/warn-deprecation') - var TEXT_MODE = 0 var BINARY_MODE = 1 var Connection = function (config) { @@ -95,21 +93,9 @@ Connection.prototype.connect = function (port, host) { return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') - const options = { - socket: self.stream, - checkServerIdentity: self.ssl.checkServerIdentity || tls.checkServerIdentity, - rejectUnauthorized: self.ssl.rejectUnauthorized, - ca: self.ssl.ca, - pfx: self.ssl.pfx, - key: self.ssl.key, - passphrase: self.ssl.passphrase, - cert: self.ssl.cert, - secureOptions: self.ssl.secureOptions, - NPNProtocols: self.ssl.NPNProtocols - } - if (typeof self.ssl.rejectUnauthorized !== 'boolean') { - warnDeprecation('Implicit disabling of certificate verification is deprecated and will be removed in pg 8. Specify `rejectUnauthorized: true` to require a valid CA or `rejectUnauthorized: false` to explicitly opt out of MITM protection.', 'PG-SSL-VERIFY') - } + const options = Object.assign({ + socket: self.stream + }, self.ssl) if (net.isIP(host) === 0) { options.servername = host } @@ -602,7 +588,7 @@ Connection.prototype._readValue = function (buffer) { } // parses error -Connection.prototype.parseE = function (buffer, length) { +Connection.prototype.parseE = function (buffer, length, isNotice) { var fields = {} var fieldType = this.readString(buffer, 1) while (fieldType !== '\0') { @@ -611,10 +597,10 @@ Connection.prototype.parseE = function (buffer, length) { } // the msg is an Error instance - var msg = new Error(fields.M) + var msg = isNotice ? { message: fields.M } : new Error(fields.M) // for compatibility with Message - msg.name = 'error' + msg.name = isNotice ? 'notice' : 'error' msg.length = length msg.severity = fields.S @@ -638,7 +624,7 @@ Connection.prototype.parseE = function (buffer, length) { // same thing, different name Connection.prototype.parseN = function (buffer, length) { - var msg = this.parseE(buffer, length) + var msg = this.parseE(buffer, length, true) msg.name = 'notice' return msg } diff --git a/packages/pg/lib/defaults.js b/packages/pg/lib/defaults.js index 120b8c7b5..eb58550d6 100644 --- a/packages/pg/lib/defaults.js +++ b/packages/pg/lib/defaults.js @@ -15,7 +15,7 @@ module.exports = { user: process.platform === 'win32' ? process.env.USERNAME : process.env.USER, // name of database to connect - database: process.platform === 'win32' ? process.env.USERNAME : process.env.USER, + database: undefined, // database user's password password: null, diff --git a/packages/pg/lib/index.js b/packages/pg/lib/index.js index de33c086d..c73064cf2 100644 --- a/packages/pg/lib/index.js +++ b/packages/pg/lib/index.js @@ -7,25 +7,17 @@ * README.md file in the root directory of this source tree. */ -var util = require('util') var Client = require('./client') var defaults = require('./defaults') var Connection = require('./connection') var Pool = require('pg-pool') -const checkConstructor = require('./compat/check-constructor') const poolFactory = (Client) => { - var BoundPool = function (options) { - // eslint-disable-next-line no-eval - checkConstructor('pg.Pool', 'PG-POOL-NEW', () => eval('new.target')) - - var config = Object.assign({ Client: Client }, options) - return new Pool(config) + return class BoundPool extends Pool { + constructor (options) { + super(options, Client) + } } - - util.inherits(BoundPool, Pool) - - return BoundPool } var PG = function (clientConstructor) { @@ -44,20 +36,28 @@ if (typeof process.env.NODE_PG_FORCE_NATIVE !== 'undefined') { module.exports = new PG(Client) // lazy require native module...the native module may not have installed - module.exports.__defineGetter__('native', function () { - delete module.exports.native - var native = null - try { - native = new PG(require('./native')) - } catch (err) { - if (err.code !== 'MODULE_NOT_FOUND') { - throw err + Object.defineProperty(module.exports, 'native', { + configurable: true, + enumerable: false, + get() { + var native = null + try { + native = new PG(require('./native')) + } catch (err) { + if (err.code !== 'MODULE_NOT_FOUND') { + throw err + } + /* eslint-disable no-console */ + console.error(err.message) + /* eslint-enable no-console */ } - /* eslint-disable no-console */ - console.error(err.message) - /* eslint-enable no-console */ + + // overwrite module.exports.native so that getter is never called again + Object.defineProperty(module.exports, 'native', { + value: native + }) + + return native } - module.exports.native = native - return native }) } diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index 581ef72d1..165147f9b 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -43,7 +43,15 @@ var Client = module.exports = function (config) { // for the time being. TODO: deprecate all this jazz var cp = this.connectionParameters = new ConnectionParameters(config) this.user = cp.user - this.password = cp.password + + // "hiding" the password so it doesn't show up in stack traces + // or if the client is console.logged + Object.defineProperty(this, 'password', { + configurable: true, + enumerable: false, + writable: true, + value: cp.password + }) this.database = cp.database this.host = cp.host this.port = cp.port diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index 548380fe1..4fcfe391e 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -7,226 +7,220 @@ * README.md file in the root directory of this source tree. */ -var EventEmitter = require('events').EventEmitter -var util = require('util') -const checkConstructor = require('./compat/check-constructor') - -var Result = require('./result') -var utils = require('./utils') - -var Query = function (config, values, callback) { - // use of "new" optional in pg 7 - // eslint-disable-next-line no-eval - checkConstructor('Query', 'PG-QUERY-NEW', () => eval('new.target')) - if (!(this instanceof Query)) { return new Query(config, values, callback) } - - config = utils.normalizeQueryConfig(config, values, callback) - - this.text = config.text - this.values = config.values - this.rows = config.rows - this.types = config.types - this.name = config.name - this.binary = config.binary - // use unique portal name each time - this.portal = config.portal || '' - this.callback = config.callback - this._rowMode = config.rowMode - if (process.domain && config.callback) { - this.callback = process.domain.bind(config.callback) - } - this._result = new Result(this._rowMode, this.types) - - // potential for multiple results - this._results = this._result - this.isPreparedStatement = false - this._canceledDueToError = false - this._promise = null - EventEmitter.call(this) -} - -util.inherits(Query, EventEmitter) - -Query.prototype.requiresPreparation = function () { - // named queries must always be prepared - if (this.name) { return true } - // always prepare if there are max number of rows expected per - // portal execution - if (this.rows) { return true } - // don't prepare empty text queries - if (!this.text) { return false } - // prepare if there are values - if (!this.values) { return false } - return this.values.length > 0 -} - -Query.prototype._checkForMultirow = function () { - // if we already have a result with a command property - // then we've already executed one query in a multi-statement simple query - // turn our results into an array of results - if (this._result.command) { - if (!Array.isArray(this._results)) { - this._results = [this._result] +const { EventEmitter } = require('events') + +const Result = require('./result') +const utils = require('./utils') + +class Query extends EventEmitter { + constructor(config, values, callback) { + super() + + config = utils.normalizeQueryConfig(config, values, callback) + + this.text = config.text + this.values = config.values + this.rows = config.rows + this.types = config.types + this.name = config.name + this.binary = config.binary + // use unique portal name each time + this.portal = config.portal || '' + this.callback = config.callback + this._rowMode = config.rowMode + if (process.domain && config.callback) { + this.callback = process.domain.bind(config.callback) } this._result = new Result(this._rowMode, this.types) - this._results.push(this._result) + + // potential for multiple results + this._results = this._result + this.isPreparedStatement = false + this._canceledDueToError = false + this._promise = null + } + + requiresPreparation() { + // named queries must always be prepared + if (this.name) { return true } + // always prepare if there are max number of rows expected per + // portal execution + if (this.rows) { return true } + // don't prepare empty text queries + if (!this.text) { return false } + // prepare if there are values + if (!this.values) { return false } + return this.values.length > 0 + } + + _checkForMultirow() { + // if we already have a result with a command property + // then we've already executed one query in a multi-statement simple query + // turn our results into an array of results + if (this._result.command) { + if (!Array.isArray(this._results)) { + this._results = [this._result] + } + this._result = new Result(this._rowMode, this.types) + this._results.push(this._result) + } } -} -// associates row metadata from the supplied -// message with this query object -// metadata used when parsing row results -Query.prototype.handleRowDescription = function (msg) { - this._checkForMultirow() - this._result.addFields(msg.fields) - this._accumulateRows = this.callback || !this.listeners('row').length -} + // associates row metadata from the supplied + // message with this query object + // metadata used when parsing row results + handleRowDescription(msg) { + this._checkForMultirow() + this._result.addFields(msg.fields) + this._accumulateRows = this.callback || !this.listeners('row').length + } -Query.prototype.handleDataRow = function (msg) { - var row + handleDataRow(msg) { + let row - if (this._canceledDueToError) { - return - } + if (this._canceledDueToError) { + return + } - try { - row = this._result.parseRow(msg.fields) - } catch (err) { - this._canceledDueToError = err - return - } + try { + row = this._result.parseRow(msg.fields) + } catch (err) { + this._canceledDueToError = err + return + } - this.emit('row', row, this._result) - if (this._accumulateRows) { - this._result.addRow(row) + this.emit('row', row, this._result) + if (this._accumulateRows) { + this._result.addRow(row) + } } -} -Query.prototype.handleCommandComplete = function (msg, con) { - this._checkForMultirow() - this._result.addCommandComplete(msg) - // need to sync after each command complete of a prepared statement - if (this.isPreparedStatement) { - con.sync() + handleCommandComplete(msg, con) { + this._checkForMultirow() + this._result.addCommandComplete(msg) + // need to sync after each command complete of a prepared statement + if (this.isPreparedStatement) { + con.sync() + } } -} -// if a named prepared statement is created with empty query text -// the backend will send an emptyQuery message but *not* a command complete message -// execution on the connection will hang until the backend receives a sync message -Query.prototype.handleEmptyQuery = function (con) { - if (this.isPreparedStatement) { - con.sync() + // if a named prepared statement is created with empty query text + // the backend will send an emptyQuery message but *not* a command complete message + // execution on the connection will hang until the backend receives a sync message + handleEmptyQuery(con) { + if (this.isPreparedStatement) { + con.sync() + } } -} -Query.prototype.handleReadyForQuery = function (con) { - if (this._canceledDueToError) { - return this.handleError(this._canceledDueToError, con) - } - if (this.callback) { - this.callback(null, this._results) + handleReadyForQuery(con) { + if (this._canceledDueToError) { + return this.handleError(this._canceledDueToError, con) + } + if (this.callback) { + this.callback(null, this._results) + } + this.emit('end', this._results) } - this.emit('end', this._results) -} -Query.prototype.handleError = function (err, connection) { - // need to sync after error during a prepared statement - if (this.isPreparedStatement) { - connection.sync() - } - if (this._canceledDueToError) { - err = this._canceledDueToError - this._canceledDueToError = false - } - // if callback supplied do not emit error event as uncaught error - // events will bubble up to node process - if (this.callback) { - return this.callback(err) + handleError(err, connection) { + // need to sync after error during a prepared statement + if (this.isPreparedStatement) { + connection.sync() + } + if (this._canceledDueToError) { + err = this._canceledDueToError + this._canceledDueToError = false + } + // if callback supplied do not emit error event as uncaught error + // events will bubble up to node process + if (this.callback) { + return this.callback(err) + } + this.emit('error', err) } - this.emit('error', err) -} -Query.prototype.submit = function (connection) { - if (typeof this.text !== 'string' && typeof this.name !== 'string') { - return new Error('A query must have either text or a name. Supplying neither is unsupported.') - } - const previous = connection.parsedStatements[this.name] - if (this.text && previous && this.text !== previous) { - return new Error(`Prepared statements must be unique - '${this.name}' was used for a different statement`) + submit(connection) { + if (typeof this.text !== 'string' && typeof this.name !== 'string') { + return new Error('A query must have either text or a name. Supplying neither is unsupported.') + } + const previous = connection.parsedStatements[this.name] + if (this.text && previous && this.text !== previous) { + return new Error(`Prepared statements must be unique - '${this.name}' was used for a different statement`) + } + if (this.values && !Array.isArray(this.values)) { + return new Error('Query values must be an array') + } + if (this.requiresPreparation()) { + this.prepare(connection) + } else { + connection.query(this.text) + } + return null } - if (this.values && !Array.isArray(this.values)) { - return new Error('Query values must be an array') + + hasBeenParsed(connection) { + return this.name && connection.parsedStatements[this.name] } - if (this.requiresPreparation()) { - this.prepare(connection) - } else { - connection.query(this.text) + + handlePortalSuspended(connection) { + this._getRows(connection, this.rows) } - return null -} -Query.prototype.hasBeenParsed = function (connection) { - return this.name && connection.parsedStatements[this.name] -} + _getRows(connection, rows) { + connection.execute({ + portal: this.portal, + rows: rows + }, true) + connection.flush() + } + + prepare(connection) { + // prepared statements need sync to be called after each command + // complete or when an error is encountered + this.isPreparedStatement = true + // TODO refactor this poor encapsulation + if (!this.hasBeenParsed(connection)) { + connection.parse({ + text: this.text, + name: this.name, + types: this.types + }, true) + } -Query.prototype.handlePortalSuspended = function (connection) { - this._getRows(connection, this.rows) -} + if (this.values) { + try { + this.values = this.values.map(utils.prepareValue) + } catch (err) { + this.handleError(err, connection) + return + } + } -Query.prototype._getRows = function (connection, rows) { - connection.execute({ - portal: this.portal, - rows: rows - }, true) - connection.flush() -} + // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY + connection.bind({ + portal: this.portal, + statement: this.name, + values: this.values, + binary: this.binary + }, true) -Query.prototype.prepare = function (connection) { - var self = this - // prepared statements need sync to be called after each command - // complete or when an error is encountered - this.isPreparedStatement = true - // TODO refactor this poor encapsulation - if (!this.hasBeenParsed(connection)) { - connection.parse({ - text: self.text, - name: self.name, - types: self.types + connection.describe({ + type: 'P', + name: this.portal || '' }, true) - } - if (self.values) { - try { - self.values = self.values.map(utils.prepareValue) - } catch (err) { - this.handleError(err, connection) - return - } + this._getRows(connection, this.rows) } - // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY - connection.bind({ - portal: self.portal, - statement: self.name, - values: self.values, - binary: self.binary - }, true) - - connection.describe({ - type: 'P', - name: self.portal || '' - }, true) - - this._getRows(connection, this.rows) -} + handleCopyInResponse(connection) { + connection.sendCopyFail('No source stream defined') + } -Query.prototype.handleCopyInResponse = function (connection) { - connection.sendCopyFail('No source stream defined') + // eslint-disable-next-line no-unused-vars + handleCopyData(msg, connection) { + // noop + } } -// eslint-disable-next-line no-unused-vars -Query.prototype.handleCopyData = function (msg, connection) { - // noop -} module.exports = Query diff --git a/packages/pg/package.json b/packages/pg/package.json index 9e06af528..6aec51616 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -51,6 +51,6 @@ ], "license": "MIT", "engines": { - "node": ">= 4.5.0" + "node": ">= 8.0.0" } } diff --git a/packages/pg/test/integration/client/configuration-tests.js b/packages/pg/test/integration/client/configuration-tests.js index 87bb52d47..a6756ddee 100644 --- a/packages/pg/test/integration/client/configuration-tests.js +++ b/packages/pg/test/integration/client/configuration-tests.js @@ -14,7 +14,7 @@ for (var key in process.env) { suite.test('default values are used in new clients', function () { assert.same(pg.defaults, { user: process.env.USER, - database: process.env.USER, + database: undefined, password: null, port: 5432, rows: 0, @@ -54,6 +54,28 @@ suite.test('modified values are passed to created clients', function () { }) }) +suite.test('database defaults to user when user is non-default', () => { + { + pg.defaults.database = undefined + + const client = new Client({ + user: 'foo', + }) + + assert.strictEqual(client.database, 'foo') + } + + { + pg.defaults.database = 'bar' + + const client = new Client({ + user: 'foo', + }) + + assert.strictEqual(client.database, 'bar') + } +}) + suite.test('cleanup', () => { // restore process.env for (var key in realEnv) { diff --git a/packages/pg/test/integration/client/notice-tests.js b/packages/pg/test/integration/client/notice-tests.js index f3dc5090e..a6fc8a56f 100644 --- a/packages/pg/test/integration/client/notice-tests.js +++ b/packages/pg/test/integration/client/notice-tests.js @@ -1,12 +1,13 @@ 'use strict' -var helper = require('./test-helper') +const helper = require('./test-helper') +const assert = require('assert') const suite = new helper.Suite() suite.test('emits notify message', function (done) { - var client = helper.client() + const client = helper.client() client.query('LISTEN boom', assert.calls(function () { - var otherClient = helper.client() - var bothEmitted = -1 + const otherClient = helper.client() + let bothEmitted = -1 otherClient.query('LISTEN boom', assert.calls(function () { assert.emits(client, 'notification', function (msg) { // make sure PQfreemem doesn't invalidate string pointers @@ -32,25 +33,34 @@ suite.test('emits notify message', function (done) { }) // this test fails on travis due to their config -suite.test('emits notice message', false, function (done) { +suite.test('emits notice message', function (done) { if (helper.args.native) { - console.error('need to get notice message working on native') + console.error('notice messages do not work curreintly with node-libpq') return done() } - // TODO this doesn't work on all versions of postgres - var client = helper.client() + + const client = helper.client() const text = ` DO language plpgsql $$ BEGIN - RAISE NOTICE 'hello, world!'; + RAISE NOTICE 'hello, world!' USING ERRCODE = '23505', DETAIL = 'this is a test'; END $$; ` - client.query(text, () => { - client.end() + client.query('SET SESSION client_min_messages=notice', (err) => { + assert.ifError(err) + client.query(text, () => { + client.end() + }) }) assert.emits(client, 'notice', function (notice) { assert.ok(notice != null) + // notice messages should not be error instances + assert(notice instanceof Error === false) + assert.strictEqual(notice.name, 'notice') + assert.strictEqual(notice.message, 'hello, world!') + assert.strictEqual(notice.detail, 'this is a test') + assert.strictEqual(notice.code, '23505') done() }) }) diff --git a/packages/pg/test/integration/gh-issues/1542-tests.js b/packages/pg/test/integration/gh-issues/1542-tests.js new file mode 100644 index 000000000..4d30d6020 --- /dev/null +++ b/packages/pg/test/integration/gh-issues/1542-tests.js @@ -0,0 +1,25 @@ + +"use strict" +const helper = require('./../test-helper') +const assert = require('assert') + +const suite = new helper.Suite() + +suite.testAsync('BoundPool can be subclassed', async () => { + const Pool = helper.pg.Pool; + class SubPool extends Pool { + + } + const subPool = new SubPool() + const client = await subPool.connect() + client.release() + await subPool.end() + assert(subPool instanceof helper.pg.Pool) +}) + +suite.test('calling pg.Pool without new throws', () => { + const Pool = helper.pg.Pool; + assert.throws(() => { + const pool = Pool() + }) +}) diff --git a/packages/pg/test/integration/gh-issues/1992-tests.js b/packages/pg/test/integration/gh-issues/1992-tests.js new file mode 100644 index 000000000..1832f5f8a --- /dev/null +++ b/packages/pg/test/integration/gh-issues/1992-tests.js @@ -0,0 +1,11 @@ + +"use strict" +const helper = require('./../test-helper') +const assert = require('assert') + +const suite = new helper.Suite() + +suite.test('Native should not be enumerable', () => { + const keys = Object.keys(helper.pg) + assert.strictEqual(keys.indexOf('native'), -1) +}) diff --git a/packages/pg/test/integration/gh-issues/2064-tests.js b/packages/pg/test/integration/gh-issues/2064-tests.js new file mode 100644 index 000000000..64c150bd0 --- /dev/null +++ b/packages/pg/test/integration/gh-issues/2064-tests.js @@ -0,0 +1,32 @@ + +"use strict" +const helper = require('./../test-helper') +const assert = require('assert') +const util = require('util') + +const suite = new helper.Suite() + +const password = 'FAIL THIS TEST' + +suite.test('Password should not exist in toString() output', () => { + const pool = new helper.pg.Pool({ password }) + const client = new helper.pg.Client({ password }) + assert(pool.toString().indexOf(password) === -1); + assert(client.toString().indexOf(password) === -1); +}) + +suite.test('Password should not exist in util.inspect output', () => { + const pool = new helper.pg.Pool({ password }) + const client = new helper.pg.Client({ password }) + const depth = 20; + assert(util.inspect(pool, { depth }).indexOf(password) === -1); + assert(util.inspect(client, { depth }).indexOf(password) === -1); +}) + +suite.test('Password should not exist in json.stringfy output', () => { + const pool = new helper.pg.Pool({ password }) + const client = new helper.pg.Client({ password }) + const depth = 20; + assert(JSON.stringify(pool).indexOf(password) === -1); + assert(JSON.stringify(client).indexOf(password) === -1); +}) diff --git a/packages/pg/test/integration/gh-issues/2085-tests.js b/packages/pg/test/integration/gh-issues/2085-tests.js index 36f30c747..8ccdca150 100644 --- a/packages/pg/test/integration/gh-issues/2085-tests.js +++ b/packages/pg/test/integration/gh-issues/2085-tests.js @@ -7,9 +7,23 @@ var assert = require('assert') const suite = new helper.Suite() suite.testAsync('it should connect over ssl', async () => { - const client = new helper.pg.Client({ ssl: 'require'}) + const ssl = helper.args.native ? 'require' : { + rejectUnauthorized: false + } + const client = new helper.pg.Client({ ssl }) await client.connect() const { rows } = await client.query('SELECT NOW()') assert.strictEqual(rows.length, 1) await client.end() }) + +suite.testAsync('it should fail with self-signed cert error w/o rejectUnauthorized being passed', async () => { + const ssl = helper.args.native ? 'verify-ca' : { } + const client = new helper.pg.Client({ ssl }) + try { + await client.connect() + } catch (e) { + return; + } + throw new Error('this test should have thrown an error due to self-signed cert') +}) diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index 5d200be0a..fdb4e6627 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -16,8 +16,13 @@ test('ConnectionParameters construction', function () { }) var compare = function (actual, expected, type) { + const expectedDatabase = + expected.database === undefined + ? expected.user + : expected.database + assert.equal(actual.user, expected.user, type + ' user') - assert.equal(actual.database, expected.database, type + ' database') + assert.equal(actual.database, expectedDatabase, type + ' database') assert.equal(actual.port, expected.port, type + ' port') assert.equal(actual.host, expected.host, type + ' host') assert.equal(actual.password, expected.password, type + ' password') diff --git a/packages/pg/test/unit/connection-pool/configuration-tests.js b/packages/pg/test/unit/connection-pool/configuration-tests.js new file mode 100644 index 000000000..10c991839 --- /dev/null +++ b/packages/pg/test/unit/connection-pool/configuration-tests.js @@ -0,0 +1,14 @@ +'use strict' + +const assert = require('assert') +const helper = require('../test-helper') + +test('pool with copied settings includes password', () => { + const original = new helper.pg.Pool({ + password: 'original', + }) + + const copy = new helper.pg.Pool(original.options) + + assert.equal(copy.options.password, 'original') +}) From a227d3e8d47e1eb53296a3a013f2e7514cd152c3 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 30 Mar 2020 10:45:12 -0500 Subject: [PATCH 0607/1037] Publish - pg-cursor@2.1.7 - pg-pool@3.0.0 - pg-query-stream@3.0.4 - pg@8.0.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 39bcc522f..9694f9745 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.1.6", + "version": "2.1.7", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -21,7 +21,7 @@ "eslint-config-prettier": "^6.4.0", "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "^7.18.2", + "pg": "^8.0.0", "prettier": "^1.18.2" }, "prettier": { diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 8d5cf2a9d..788a49292 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "2.0.10", + "version": "3.0.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 87d4b4560..6c35db0c1 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.0.3", + "version": "3.0.4", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -27,12 +27,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^6.2.2", - "pg": "^7.18.2", + "pg": "^8.0.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.1.6" + "pg-cursor": "^2.1.7" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 6aec51616..edd24337b 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "7.18.2", + "version": "8.0.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "packet-reader": "1.0.0", "pg-connection-string": "0.1.3", "pg-packet-stream": "^1.1.0", - "pg-pool": "^2.0.10", + "pg-pool": "^3.0.0", "pg-types": "^2.1.0", "pgpass": "1.x", "semver": "4.3.2" From 90c6d1390e5fb5ef3df72b698edf1406c46a5020 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 1 Apr 2020 09:15:54 -0500 Subject: [PATCH 0608/1037] Update changelog closes #2150 --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6390d3825..41eaca70e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### pg@8.0.0 + +#### note: for detailed release notes please [check here](https://node-postgres.com/announcements#2020-02-25) + +- Remove versions of node older than `6 lts` from the test matrix. `pg>=8.0` may still work on older versions but it is no longer officially supported. +- Change default behavior when not specifying `rejectUnauthorized` with the SSL connection parameters. Previously we defaulted to `rejectUnauthorized: false` when it was not specifically included. We now default to `rejectUnauthorized: true.` Manually specify `{ ssl: { rejectUnauthorized: false } }` for old behavior. +- Change [default database](https://github.com/brianc/node-postgres/pull/1679) when not specified to use the `user` config option if available. Previously `process.env.USER` was used. +- Change `pg.Pool` and `pg.Query` to [be](https://github.com/brianc/node-postgres/pull/2126) an [es6 class](https://github.com/brianc/node-postgres/pull/2063). +- Make `pg.native` non enumerable. +- `notice` messages are [no longer instances](https://github.com/brianc/node-postgres/pull/2090) of `Error`. +- Passwords no longer [show up](https://github.com/brianc/node-postgres/pull/2070) when instances of clients or pools are logged. + ### pg@7.18.0 - This will likely be the last minor release before pg@8.0. From 2013d77b28be5a0d563addb1852eb97e9693e452 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 2 Apr 2020 16:48:22 -0500 Subject: [PATCH 0609/1037] Parser speed improvements (#2151) * Change from transform stream * Yeah a thing * Make tests pass, add new code to travis * Update 'best' benchmarks and include tsc in pretest script * Need to add build early so we can create test tables * logging --- .travis.yml | 4 ++ package.json | 2 + packages/pg-packet-stream/package.json | 6 +- .../src/inbound-parser.test.ts | 64 ++++++++----------- packages/pg-packet-stream/src/index.ts | 32 +++++----- packages/pg-packet-stream/src/messages.ts | 43 ++++++++++++- packages/pg/bench.js | 5 +- packages/pg/lib/connection-fast.js | 35 +++++----- 8 files changed, 114 insertions(+), 77 deletions(-) diff --git a/.travis.yml b/.travis.yml index b00d6e695..579ad5ac9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,10 +2,13 @@ language: node_js dist: bionic before_script: | + yarn build node packages/pg/script/create-test-tables.js postgresql:/// env: - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres + # test w/ new faster parsing code + - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres PG_FAST_CONNECTION=true node_js: - lts/dubnium @@ -30,6 +33,7 @@ matrix: -e '/^host/ s/trust$/md5/' \ /etc/postgresql/10/main/pg_hba.conf sudo -u postgres psql -c "ALTER ROLE postgres PASSWORD 'test-password'; SELECT pg_reload_conf()" + yarn build node packages/pg/script/create-test-tables.js postgresql:/// - node_js: lts/carbon diff --git a/package.json b/package.json index ce7f9f3b8..03e3827e1 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,8 @@ ], "scripts": { "test": "yarn lerna exec yarn test", + "build": "yarn lerna exec --scope pg-packet-stream yarn build", + "pretest": "yarn build", "lint": "yarn lerna exec --parallel yarn lint" }, "devDependencies": { diff --git a/packages/pg-packet-stream/package.json b/packages/pg-packet-stream/package.json index 9cc325274..bf9c13e84 100644 --- a/packages/pg-packet-stream/package.json +++ b/packages/pg-packet-stream/package.json @@ -16,7 +16,9 @@ }, "scripts": { "test": "mocha dist/**/*.test.js", - "prepublish": "tsc", - "pretest": "tsc" + "build": "tsc", + "build:watch": "tsc --watch", + "prepublish": "yarn build", + "pretest": "yarn build" } } diff --git a/packages/pg-packet-stream/src/inbound-parser.test.ts b/packages/pg-packet-stream/src/inbound-parser.test.ts index 098f41242..e8619bf83 100644 --- a/packages/pg-packet-stream/src/inbound-parser.test.ts +++ b/packages/pg-packet-stream/src/inbound-parser.test.ts @@ -1,8 +1,9 @@ import buffers from './testing/test-buffers' import BufferList from './testing/buffer-list' -import { PgPacketStream } from './' +import { parse } from './' import assert from 'assert' -import { Readable } from 'stream' +import { PassThrough } from 'stream' +import { BackendMessage } from './messages' var authOkBuffer = buffers.authenticationOk() var paramStatusBuffer = buffers.parameterStatus('client_encoding', 'UTF8') @@ -137,25 +138,14 @@ var expectedTwoRowMessage = { }] } -const concat = (stream: Readable): Promise => { - return new Promise((resolve) => { - const results: any[] = [] - stream.on('data', item => results.push(item)) - stream.on('end', () => resolve(results)) - }) -} - var testForMessage = function (buffer: Buffer, expectedMessage: any) { it('recieves and parses ' + expectedMessage.name, async () => { - const parser = new PgPacketStream(); - parser.write(buffer); - parser.end(); - const [lastMessage] = await concat(parser); + const messages = await parseBuffers([buffer]) + const [lastMessage] = messages; for (const key in expectedMessage) { - assert.deepEqual(lastMessage[key], expectedMessage[key]) + assert.deepEqual((lastMessage as any)[key], expectedMessage[key]) } - }) } @@ -197,6 +187,19 @@ var expectedNotificationResponseMessage = { payload: 'boom' } + + +const parseBuffers = async (buffers: Buffer[]): Promise => { + const stream = new PassThrough(); + for (const buffer of buffers) { + stream.write(buffer); + } + stream.end() + const msgs: BackendMessage[] = [] + await parse(stream, (msg) => msgs.push(msg)) + return msgs +} + describe('PgPacketStream', function () { testForMessage(authOkBuffer, expectedAuthenticationOkayMessage) testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage) @@ -391,18 +394,9 @@ describe('PgPacketStream', function () { describe('split buffer, single message parsing', function () { var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']) - const parse = async (buffers: Buffer[]): Promise => { - const parser = new PgPacketStream(); - for (const buffer of buffers) { - parser.write(buffer); - } - parser.end() - const [msg] = await concat(parser) - return msg; - } - it('parses when full buffer comes in', async function () { - const message = await parse([fullBuffer]); + const messages = await parseBuffers([fullBuffer]); + const message = messages[0] as any assert.equal(message.fields.length, 5) assert.equal(message.fields[0], null) assert.equal(message.fields[1], 'bang') @@ -416,7 +410,8 @@ describe('PgPacketStream', function () { var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) fullBuffer.copy(firstBuffer, 0, 0) fullBuffer.copy(secondBuffer, 0, firstBuffer.length) - const message = await parse([firstBuffer, secondBuffer]); + const messages = await parseBuffers([fullBuffer]); + const message = messages[0] as any assert.equal(message.fields.length, 5) assert.equal(message.fields[0], null) assert.equal(message.fields[1], 'bang') @@ -447,15 +442,6 @@ describe('PgPacketStream', function () { dataRowBuffer.copy(fullBuffer, 0, 0) readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0) - const parse = (buffers: Buffer[]): Promise => { - const parser = new PgPacketStream(); - for (const buffer of buffers) { - parser.write(buffer); - } - parser.end() - return concat(parser) - } - var verifyMessages = function (messages: any[]) { assert.strictEqual(messages.length, 2) assert.deepEqual(messages[0], { @@ -473,7 +459,7 @@ describe('PgPacketStream', function () { } // sanity check it('recieves both messages when packet is not split', async function () { - const messages = await parse([fullBuffer]) + const messages = await parseBuffers([fullBuffer]) verifyMessages(messages) }) @@ -482,7 +468,7 @@ describe('PgPacketStream', function () { var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) fullBuffer.copy(firstBuffer, 0, 0) fullBuffer.copy(secondBuffer, 0, firstBuffer.length) - const messages = await parse([firstBuffer, secondBuffer]) + const messages = await parseBuffers([firstBuffer, secondBuffer]) verifyMessages(messages) } diff --git a/packages/pg-packet-stream/src/index.ts b/packages/pg-packet-stream/src/index.ts index 2bd2da69c..3ebe5e847 100644 --- a/packages/pg-packet-stream/src/index.ts +++ b/packages/pg-packet-stream/src/index.ts @@ -1,5 +1,5 @@ -import { Transform, TransformCallback, TransformOptions } from 'stream'; -import { Mode, bindComplete, parseComplete, closeComplete, noData, portalSuspended, copyDone, replicationStart, emptyQuery, ReadyForQueryMessage, CommandCompleteMessage, CopyDataMessage, CopyResponse, NotificationResponseMessage, RowDescriptionMessage, Field, DataRowMessage, ParameterStatusMessage, BackendKeyDataMessage, DatabaseError, BackendMessage, MessageName, AuthenticationMD5Password } from './messages'; +import { TransformOptions } from 'stream'; +import { Mode, bindComplete, parseComplete, closeComplete, noData, portalSuspended, copyDone, replicationStart, emptyQuery, ReadyForQueryMessage, CommandCompleteMessage, CopyDataMessage, CopyResponse, NotificationResponseMessage, RowDescriptionMessage, Field, DataRowMessage, ParameterStatusMessage, BackendKeyDataMessage, DatabaseError, BackendMessage, MessageName, AuthenticationMD5Password, NoticeMessage } from './messages'; import { BufferReader } from './BufferReader'; import assert from 'assert' @@ -46,23 +46,27 @@ const enum MessageCodes { CopyData = 0x64, // d } -export class PgPacketStream extends Transform { +type MessageCallback = (msg: BackendMessage) => void; + +export function parse(stream: NodeJS.ReadableStream, callback: MessageCallback): Promise { + const parser = new PgPacketParser() + stream.on('data', (buffer: Buffer) => parser.parse(buffer, callback)) + return new Promise((resolve) => stream.on('end', () => resolve())) +} + +class PgPacketParser { private remainingBuffer: Buffer = emptyBuffer; private reader = new BufferReader(); private mode: Mode; constructor(opts?: StreamOptions) { - super({ - ...opts, - readableObjectMode: true - }) if (opts?.mode === 'binary') { throw new Error('Binary mode not supported yet') } this.mode = opts?.mode || 'text'; } - public _transform(buffer: Buffer, encoding: string, callback: TransformCallback) { + public parse(buffer: Buffer, callback: MessageCallback) { let combinedBuffer = buffer; if (this.remainingBuffer.byteLength) { combinedBuffer = Buffer.allocUnsafe(this.remainingBuffer.byteLength + buffer.byteLength); @@ -81,7 +85,7 @@ export class PgPacketStream extends Transform { if (fullMessageLength + offset <= combinedBuffer.byteLength) { const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer); - this.push(message) + callback(message) offset += fullMessageLength; } else { break; @@ -94,7 +98,6 @@ export class PgPacketStream extends Transform { this.remainingBuffer = combinedBuffer.slice(offset) } - callback(null); } private handlePacket(offset: number, code: number, length: number, bytes: Buffer): BackendMessage { @@ -146,10 +149,6 @@ export class PgPacketStream extends Transform { } } - public _flush(callback: TransformCallback) { - this._transform(Buffer.alloc(0), 'utf-8', callback) - } - private parseReadyForQueryMessage(offset: number, length: number, bytes: Buffer) { this.reader.setBuffer(offset, bytes); const status = this.reader.string(1); @@ -304,8 +303,9 @@ export class PgPacketStream extends Transform { fieldType = this.reader.string(1) } - // the msg is an Error instance - var message = new DatabaseError(fields.M, length, name) + const messageValue = fields.M + + const message = name === MessageName.notice ? new NoticeMessage(length, messageValue) : new DatabaseError(messageValue, length, name) message.severity = fields.S message.code = fields.C diff --git a/packages/pg-packet-stream/src/messages.ts b/packages/pg-packet-stream/src/messages.ts index 160eb3ffb..222a24902 100644 --- a/packages/pg-packet-stream/src/messages.ts +++ b/packages/pg-packet-stream/src/messages.ts @@ -74,7 +74,27 @@ export const copyDone: BackendMessage = { length: 4, } -export class DatabaseError extends Error { +interface NoticeOrError { + message: string | undefined; + severity: string | undefined; + code: string | undefined; + detail: string | undefined; + hint: string | undefined; + position: string | undefined; + internalPosition: string | undefined; + internalQuery: string | undefined; + where: string | undefined; + schema: string | undefined; + table: string | undefined; + column: string | undefined; + dataType: string | undefined; + constraint: string | undefined; + file: string | undefined; + line: string | undefined; + routine: string | undefined; +} + +export class DatabaseError extends Error implements NoticeOrError { public severity: string | undefined; public code: string | undefined; public detail: string | undefined; @@ -167,3 +187,24 @@ export class DataRowMessage { this.fieldCount = fields.length; } } + +export class NoticeMessage implements BackendMessage, NoticeOrError { + constructor(public readonly length: number, public readonly message: string | undefined) {} + public readonly name = MessageName.notice; + public severity: string | undefined; + public code: string | undefined; + public detail: string | undefined; + public hint: string | undefined; + public position: string | undefined; + public internalPosition: string | undefined; + public internalQuery: string | undefined; + public where: string | undefined; + public schema: string | undefined; + public table: string | undefined; + public column: string | undefined; + public dataType: string | undefined; + public constraint: string | undefined; + public file: string | undefined; + public line: string | undefined; + public routine: string | undefined; +} diff --git a/packages/pg/bench.js b/packages/pg/bench.js index 3c12fa683..b5707db73 100644 --- a/packages/pg/bench.js +++ b/packages/pg/bench.js @@ -54,13 +54,14 @@ const run = async () => { queries = await bench(client, seq, seconds * 1000); console.log("sequence queries:", queries); console.log("qps", queries / seconds); - console.log("on my laptop best so far seen 1192 qps") + console.log("on my laptop best so far seen 1209 qps") console.log('') queries = await bench(client, insert, seconds * 1000); console.log("insert queries:", queries); console.log("qps", queries / seconds); - console.log("on my laptop best so far seen 5600 qps") + console.log("on my laptop best so far seen 5799 qps") + console.log() await client.end(); await client.end(); }; diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index 631ea3b0e..ecbb362c9 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -13,13 +13,13 @@ var util = require('util') var Writer = require('buffer-writer') // eslint-disable-next-line -var PacketStream = require('pg-packet-stream') +const { parse } = require('pg-packet-stream') var TEXT_MODE = 0 // TODO(bmc) support binary mode here // var BINARY_MODE = 1 -console.log('using faster connection') +console.log('***using faster connection***') var Connection = function (config) { EventEmitter.call(this) config = config || {} @@ -84,12 +84,13 @@ Connection.prototype.connect = function (port, host) { this.stream.once('data', function (buffer) { var responseCode = buffer.toString('utf8') switch (responseCode) { - case 'N': // Server does not support SSL connections - return self.emit('error', new Error('The server does not support SSL connections')) case 'S': // Server supports SSL connections, continue with a secure connection break - default: - // Any other response byte, including 'E' (ErrorResponse) indicating a server error + case 'N': // Server does not support SSL connections + self.stream.end() + return self.emit('error', new Error('The server does not support SSL connections')) + default: // Any other response byte, including 'E' (ErrorResponse) indicating a server error + self.stream.end() return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') @@ -108,19 +109,15 @@ Connection.prototype.connect = function (port, host) { } Connection.prototype.attachListeners = function (stream) { - var self = this - const mode = this._mode === TEXT_MODE ? 'text' : 'binary' - const packetStream = new PacketStream.PgPacketStream({ mode }) - this.stream.pipe(packetStream) - packetStream.on('data', (msg) => { + stream.on('end', () => { + this.emit('end') + }) + parse(stream, (msg) => { var eventName = msg.name === 'error' ? 'errorMessage' : msg.name - if (self._emitMessage) { - self.emit('message', msg) + if (this._emitMessage) { + this.emit('message', msg) } - self.emit(eventName, msg) - }) - stream.on('end', function () { - self.emit('end') + this.emit(eventName, msg) }) } @@ -331,6 +328,10 @@ Connection.prototype.end = function () { // 0x58 = 'X' this.writer.clear() this._ending = true + if (!this.stream.writable) { + this.stream.end() + return + } return this.stream.write(END_BUFFER, () => { this.stream.end() }) From 3ff91eaa3222657fd51ea463b8086d134a505404 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 9 Apr 2020 12:28:19 -0500 Subject: [PATCH 0610/1037] Decouple serializing messages w/ writing them to socket (#2155) * Move message writing to typescript lib * Write more tests, cleanup code to some extent * Rename package to something more representing its name * Remove unused code * Small tweaks based on microbenchmarks * Rename w/o underscore --- package.json | 2 +- .../package.json | 3 +- packages/pg-protocol/src/b.ts | 24 ++ .../src/buffer-reader.ts} | 4 +- packages/pg-protocol/src/buffer-writer.ts | 87 ++++++ .../src/inbound-parser.test.ts | 2 +- packages/pg-protocol/src/index.ts | 11 + .../src/messages.ts | 0 .../src/outbound-serializer.test.ts | 256 +++++++++++++++++ .../index.ts => pg-protocol/src/parser.ts} | 12 +- packages/pg-protocol/src/serializer.ts | 272 ++++++++++++++++++ .../src/testing/buffer-list.ts | 0 .../src/testing/test-buffers.ts | 0 .../src/types/chunky.d.ts | 0 .../tsconfig.json | 0 packages/pg/lib/connection-fast.js | 198 ++----------- packages/pg/package.json | 2 +- 17 files changed, 685 insertions(+), 188 deletions(-) rename packages/{pg-packet-stream => pg-protocol}/package.json (81%) create mode 100644 packages/pg-protocol/src/b.ts rename packages/{pg-packet-stream/src/BufferReader.ts => pg-protocol/src/buffer-reader.ts} (96%) create mode 100644 packages/pg-protocol/src/buffer-writer.ts rename packages/{pg-packet-stream => pg-protocol}/src/inbound-parser.test.ts (99%) create mode 100644 packages/pg-protocol/src/index.ts rename packages/{pg-packet-stream => pg-protocol}/src/messages.ts (100%) create mode 100644 packages/pg-protocol/src/outbound-serializer.test.ts rename packages/{pg-packet-stream/src/index.ts => pg-protocol/src/parser.ts} (96%) create mode 100644 packages/pg-protocol/src/serializer.ts rename packages/{pg-packet-stream => pg-protocol}/src/testing/buffer-list.ts (100%) rename packages/{pg-packet-stream => pg-protocol}/src/testing/test-buffers.ts (100%) rename packages/{pg-packet-stream => pg-protocol}/src/types/chunky.d.ts (100%) rename packages/{pg-packet-stream => pg-protocol}/tsconfig.json (100%) diff --git a/package.json b/package.json index 03e3827e1..160180777 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ ], "scripts": { "test": "yarn lerna exec yarn test", - "build": "yarn lerna exec --scope pg-packet-stream yarn build", + "build": "yarn lerna exec --scope pg-protocol yarn build", "pretest": "yarn build", "lint": "yarn lerna exec --parallel yarn lint" }, diff --git a/packages/pg-packet-stream/package.json b/packages/pg-protocol/package.json similarity index 81% rename from packages/pg-packet-stream/package.json rename to packages/pg-protocol/package.json index bf9c13e84..e3e5640cd 100644 --- a/packages/pg-packet-stream/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,7 @@ { - "name": "pg-packet-stream", + "name": "pg-protocol", "version": "1.1.0", + "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", "license": "MIT", diff --git a/packages/pg-protocol/src/b.ts b/packages/pg-protocol/src/b.ts new file mode 100644 index 000000000..267d211c4 --- /dev/null +++ b/packages/pg-protocol/src/b.ts @@ -0,0 +1,24 @@ +// file for microbenchmarking + +import { Writer } from './buffer-writer' +import { serialize } from './index' + +const LOOPS = 1000 +let count = 0 +let start = Date.now() +const writer = new Writer() + +const run = () => { + if (count > LOOPS) { + console.log(Date.now() - start) + return; + } + count++ + for(let i = 0; i < LOOPS; i++) { + serialize.describe({ type: 'P'}) + serialize.describe({ type: 'S'}) + } + setImmediate(run) +} + +run() diff --git a/packages/pg-packet-stream/src/BufferReader.ts b/packages/pg-protocol/src/buffer-reader.ts similarity index 96% rename from packages/pg-packet-stream/src/BufferReader.ts rename to packages/pg-protocol/src/buffer-reader.ts index 9729d919f..68dc89cae 100644 --- a/packages/pg-packet-stream/src/BufferReader.ts +++ b/packages/pg-protocol/src/buffer-reader.ts @@ -2,8 +2,10 @@ const emptyBuffer = Buffer.allocUnsafe(0); export class BufferReader { private buffer: Buffer = emptyBuffer; - // TODO(bmc): support non-utf8 encoding + + // TODO(bmc): support non-utf8 encoding? private encoding: string = 'utf-8'; + constructor(private offset: number = 0) { } public setBuffer(offset: number, buffer: Buffer): void { diff --git a/packages/pg-protocol/src/buffer-writer.ts b/packages/pg-protocol/src/buffer-writer.ts new file mode 100644 index 000000000..2299070d1 --- /dev/null +++ b/packages/pg-protocol/src/buffer-writer.ts @@ -0,0 +1,87 @@ +//binary data writer tuned for encoding binary specific to the postgres binary protocol + +export class Writer { + private buffer: Buffer; + private offset: number = 5; + private headerPosition: number = 0; + constructor(private size = 256) { + this.buffer = Buffer.alloc(size) + } + + private ensure(size: number): void { + var remaining = this.buffer.length - this.offset; + if (remaining < size) { + var oldBuffer = this.buffer; + // exponential growth factor of around ~ 1.5 + // https://stackoverflow.com/questions/2269063/buffer-growth-strategy + var newSize = oldBuffer.length + (oldBuffer.length >> 1) + size; + this.buffer = Buffer.alloc(newSize); + oldBuffer.copy(this.buffer); + } + } + + public addInt32(num: number): Writer { + this.ensure(4); + this.buffer[this.offset++] = (num >>> 24 & 0xFF); + this.buffer[this.offset++] = (num >>> 16 & 0xFF); + this.buffer[this.offset++] = (num >>> 8 & 0xFF); + this.buffer[this.offset++] = (num >>> 0 & 0xFF); + return this; + } + + public addInt16(num: number): Writer { + this.ensure(2); + this.buffer[this.offset++] = (num >>> 8 & 0xFF); + this.buffer[this.offset++] = (num >>> 0 & 0xFF); + return this; + } + + + public addCString(string: string): Writer { + if (!string) { + this.ensure(1); + } else { + var len = Buffer.byteLength(string); + this.ensure(len + 1); // +1 for null terminator + this.buffer.write(string, this.offset, 'utf-8') + this.offset += len; + } + + this.buffer[this.offset++] = 0; // null terminator + return this; + } + + public addString(string: string = ""): Writer { + var len = Buffer.byteLength(string); + this.ensure(len); + this.buffer.write(string, this.offset); + this.offset += len; + return this; + } + + public add(otherBuffer: Buffer): Writer { + this.ensure(otherBuffer.length); + otherBuffer.copy(this.buffer, this.offset); + this.offset += otherBuffer.length; + return this; + } + + private join(code?: number): Buffer { + if (code) { + this.buffer[this.headerPosition] = code; + //length is everything in this packet minus the code + const length = this.offset - (this.headerPosition + 1) + this.buffer.writeInt32BE(length, this.headerPosition + 1) + } + return this.buffer.slice(code ? 0 : 5, this.offset); + } + + public flush(code?: number): Buffer { + var result = this.join(code); + this.offset = 5; + this.headerPosition = 0; + this.buffer = Buffer.allocUnsafe(this.size) + return result; + } +} + diff --git a/packages/pg-packet-stream/src/inbound-parser.test.ts b/packages/pg-protocol/src/inbound-parser.test.ts similarity index 99% rename from packages/pg-packet-stream/src/inbound-parser.test.ts rename to packages/pg-protocol/src/inbound-parser.test.ts index e8619bf83..461ab2628 100644 --- a/packages/pg-packet-stream/src/inbound-parser.test.ts +++ b/packages/pg-protocol/src/inbound-parser.test.ts @@ -1,6 +1,6 @@ import buffers from './testing/test-buffers' import BufferList from './testing/buffer-list' -import { parse } from './' +import { parse } from '.' import assert from 'assert' import { PassThrough } from 'stream' import { BackendMessage } from './messages' diff --git a/packages/pg-protocol/src/index.ts b/packages/pg-protocol/src/index.ts new file mode 100644 index 000000000..f4ade0173 --- /dev/null +++ b/packages/pg-protocol/src/index.ts @@ -0,0 +1,11 @@ +import { BackendMessage } from './messages'; +import { serialize } from './serializer'; +import { Parser, MessageCallback } from './parser' + +export function parse(stream: NodeJS.ReadableStream, callback: MessageCallback): Promise { + const parser = new Parser() + stream.on('data', (buffer: Buffer) => parser.parse(buffer, callback)) + return new Promise((resolve) => stream.on('end', () => resolve())) +} + +export { serialize }; diff --git a/packages/pg-packet-stream/src/messages.ts b/packages/pg-protocol/src/messages.ts similarity index 100% rename from packages/pg-packet-stream/src/messages.ts rename to packages/pg-protocol/src/messages.ts diff --git a/packages/pg-protocol/src/outbound-serializer.test.ts b/packages/pg-protocol/src/outbound-serializer.test.ts new file mode 100644 index 000000000..110b932ce --- /dev/null +++ b/packages/pg-protocol/src/outbound-serializer.test.ts @@ -0,0 +1,256 @@ +import assert from 'assert' +import { serialize } from './serializer' +import BufferList from './testing/buffer-list' + +describe('serializer', () => { + it('builds startup message', function () { + const actual = serialize.startup({ + user: 'brian', + database: 'bang' + }) + assert.deepEqual(actual, new BufferList() + .addInt16(3) + .addInt16(0) + .addCString('user') + .addCString('brian') + .addCString('database') + .addCString('bang') + .addCString('client_encoding') + .addCString("'utf-8'") + .addCString('').join(true)) + }) + + it('builds password message', function () { + const actual = serialize.password('!') + assert.deepEqual(actual, new BufferList().addCString('!').join(true, 'p')) + }) + + it('builds request ssl message', function () { + const actual = serialize.requestSsl() + const expected = new BufferList().addInt32(80877103).join(true) + assert.deepEqual(actual, expected); + }) + + it('builds SASLInitialResponseMessage message', function () { + const actual = serialize.sendSASLInitialResponseMessage('mech', 'data') + assert.deepEqual(actual, new BufferList().addCString('mech').addInt32(4).addString('data').join(true, 'p')) + }) + + + it('builds SCRAMClientFinalMessage message', function () { + const actual = serialize.sendSCRAMClientFinalMessage('data') + assert.deepEqual(actual, new BufferList().addString('data').join(true, 'p')) + }) + + + it('builds query message', function () { + var txt = 'select * from boom' + const actual = serialize.query(txt) + assert.deepEqual(actual, new BufferList().addCString(txt).join(true, 'Q')) + }) + + + describe('parse message', () => { + + it('builds parse message', function () { + const actual = serialize.parse({ text: '!' }) + var expected = new BufferList() + .addCString('') + .addCString('!') + .addInt16(0).join(true, 'P') + assert.deepEqual(actual, expected) + }) + + it('builds parse message with named query', function () { + const actual = serialize.parse({ + name: 'boom', + text: 'select * from boom', + types: [] + }) + var expected = new BufferList() + .addCString('boom') + .addCString('select * from boom') + .addInt16(0).join(true, 'P') + assert.deepEqual(actual, expected) + }) + + it('with multiple parameters', function () { + const actual = serialize.parse({ + name: 'force', + text: 'select * from bang where name = $1', + types: [1, 2, 3, 4] + }) + var expected = new BufferList() + .addCString('force') + .addCString('select * from bang where name = $1') + .addInt16(4) + .addInt32(1) + .addInt32(2) + .addInt32(3) + .addInt32(4).join(true, 'P') + assert.deepEqual(actual, expected) + }) + + }) + + + describe('bind messages', function () { + it('with no values', function () { + const actual = serialize.bind() + + var expectedBuffer = new BufferList() + .addCString('') + .addCString('') + .addInt16(0) + .addInt16(0) + .addInt16(0) + .join(true, 'B') + assert.deepEqual(actual, expectedBuffer) + }) + + it('with named statement, portal, and values', function () { + const actual = serialize.bind({ + portal: 'bang', + statement: 'woo', + values: ['1', 'hi', null, 'zing'] + }) + var expectedBuffer = new BufferList() + .addCString('bang') // portal name + .addCString('woo') // statement name + .addInt16(0) + .addInt16(4) + .addInt32(1) + .add(Buffer.from('1')) + .addInt32(2) + .add(Buffer.from('hi')) + .addInt32(-1) + .addInt32(4) + .add(Buffer.from('zing')) + .addInt16(0) + .join(true, 'B') + assert.deepEqual(actual, expectedBuffer) + }) + }) + + it('with named statement, portal, and buffer value', function () { + const actual = serialize.bind({ + portal: 'bang', + statement: 'woo', + values: ['1', 'hi', null, Buffer.from('zing', 'utf8')] + }) + var expectedBuffer = new BufferList() + .addCString('bang') // portal name + .addCString('woo') // statement name + .addInt16(4)// value count + .addInt16(0)// string + .addInt16(0)// string + .addInt16(0)// string + .addInt16(1)// binary + .addInt16(4) + .addInt32(1) + .add(Buffer.from('1')) + .addInt32(2) + .add(Buffer.from('hi')) + .addInt32(-1) + .addInt32(4) + .add(Buffer.from('zing', 'utf-8')) + .addInt16(0) + .join(true, 'B') + assert.deepEqual(actual, expectedBuffer) + }) + + describe('builds execute message', function () { + it('for unamed portal with no row limit', function () { + const actual = serialize.execute() + var expectedBuffer = new BufferList() + .addCString('') + .addInt32(0) + .join(true, 'E') + assert.deepEqual(actual, expectedBuffer) + }) + + it('for named portal with row limit', function () { + const actual = serialize.execute({ + portal: 'my favorite portal', + rows: 100 + }) + var expectedBuffer = new BufferList() + .addCString('my favorite portal') + .addInt32(100) + .join(true, 'E') + assert.deepEqual(actual, expectedBuffer) + }) + }) + + it('builds flush command', function () { + const actual = serialize.flush() + var expected = new BufferList().join(true, 'H') + assert.deepEqual(actual, expected) + }) + + it('builds sync command', function () { + const actual = serialize.sync() + var expected = new BufferList().join(true, 'S') + assert.deepEqual(actual, expected) + }) + + it('builds end command', function () { + const actual = serialize.end() + var expected = Buffer.from([0x58, 0, 0, 0, 4]) + assert.deepEqual(actual, expected) + }) + + describe('builds describe command', function () { + it('describe statement', function () { + const actual = serialize.describe({ type: 'S', name: 'bang' }) + var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D') + assert.deepEqual(actual, expected) + }) + + it('describe unnamed portal', function () { + const actual = serialize.describe({ type: 'P' }) + var expected = new BufferList().addChar('P').addCString('').join(true, 'D') + assert.deepEqual(actual, expected) + }) + }) + + describe('builds close command', function () { + it('describe statement', function () { + const actual = serialize.close({ type: 'S', name: 'bang' }) + var expected = new BufferList().addChar('S').addCString('bang').join(true, 'C') + assert.deepEqual(actual, expected) + }) + + it('describe unnamed portal', function () { + const actual = serialize.close({ type: 'P' }) + var expected = new BufferList().addChar('P').addCString('').join(true, 'C') + assert.deepEqual(actual, expected) + }) + }) + + describe('copy messages', function () { + it('builds copyFromChunk', () => { + const actual = serialize.copyData(Buffer.from([1, 2, 3])) + const expected = new BufferList().add(Buffer.from([1, 2,3 ])).join(true, 'd') + assert.deepEqual(actual, expected) + }) + + it('builds copy fail', () => { + const actual = serialize.copyFail('err!') + const expected = new BufferList().addCString('err!').join(true, 'f') + assert.deepEqual(actual, expected) + }) + + it('builds copy done', () => { + const actual = serialize.copyDone() + const expected = new BufferList().join(true, 'c') + assert.deepEqual(actual, expected) + }) + }) + + it('builds cancel message', () => { + const actual = serialize.cancel(3, 4) + const expected = new BufferList().addInt16(1234).addInt16(5678).addInt32(3).addInt32(4).join(true) + assert.deepEqual(actual, expected) + }) +}) diff --git a/packages/pg-packet-stream/src/index.ts b/packages/pg-protocol/src/parser.ts similarity index 96% rename from packages/pg-packet-stream/src/index.ts rename to packages/pg-protocol/src/parser.ts index 3ebe5e847..69a9c28b2 100644 --- a/packages/pg-packet-stream/src/index.ts +++ b/packages/pg-protocol/src/parser.ts @@ -1,6 +1,6 @@ import { TransformOptions } from 'stream'; import { Mode, bindComplete, parseComplete, closeComplete, noData, portalSuspended, copyDone, replicationStart, emptyQuery, ReadyForQueryMessage, CommandCompleteMessage, CopyDataMessage, CopyResponse, NotificationResponseMessage, RowDescriptionMessage, Field, DataRowMessage, ParameterStatusMessage, BackendKeyDataMessage, DatabaseError, BackendMessage, MessageName, AuthenticationMD5Password, NoticeMessage } from './messages'; -import { BufferReader } from './BufferReader'; +import { BufferReader } from './buffer-reader'; import assert from 'assert' // every message is prefixed with a single bye @@ -46,15 +46,9 @@ const enum MessageCodes { CopyData = 0x64, // d } -type MessageCallback = (msg: BackendMessage) => void; +export type MessageCallback = (msg: BackendMessage) => void; -export function parse(stream: NodeJS.ReadableStream, callback: MessageCallback): Promise { - const parser = new PgPacketParser() - stream.on('data', (buffer: Buffer) => parser.parse(buffer, callback)) - return new Promise((resolve) => stream.on('end', () => resolve())) -} - -class PgPacketParser { +export class Parser { private remainingBuffer: Buffer = emptyBuffer; private reader = new BufferReader(); private mode: Mode; diff --git a/packages/pg-protocol/src/serializer.ts b/packages/pg-protocol/src/serializer.ts new file mode 100644 index 000000000..71ac3c878 --- /dev/null +++ b/packages/pg-protocol/src/serializer.ts @@ -0,0 +1,272 @@ +import { Writer } from './buffer-writer' + +const enum code { + startup = 0x70, + query = 0x51, + parse = 0x50, + bind = 0x42, + execute = 0x45, + flush = 0x48, + sync = 0x53, + end = 0x58, + close = 0x43, + describe = 0x44, + copyFromChunk = 0x64, + copyDone = 0x63, + copyFail = 0x66 +} + +const writer = new Writer() + +const startup = (opts: Record): Buffer => { + // protocol version + writer.addInt16(3).addInt16(0) + for (const key of Object.keys(opts)) { + writer.addCString(key).addCString(opts[key]) + } + + writer.addCString('client_encoding').addCString("'utf-8'") + + var bodyBuffer = writer.addCString('').flush() + // this message is sent without a code + + var length = bodyBuffer.length + 4 + + return new Writer() + .addInt32(length) + .add(bodyBuffer) + .flush() +} + +const requestSsl = (): Buffer => { + const response = Buffer.allocUnsafe(8) + response.writeInt32BE(8, 0); + response.writeInt32BE(80877103, 4) + return response +} + +const password = (password: string): Buffer => { + return writer.addCString(password).flush(code.startup) +} + +const sendSASLInitialResponseMessage = function (mechanism: string, initialResponse: string): Buffer { + // 0x70 = 'p' + writer + .addCString(mechanism) + .addInt32(Buffer.byteLength(initialResponse)) + .addString(initialResponse) + + return writer.flush(code.startup) +} + +const sendSCRAMClientFinalMessage = function (additionalData: string): Buffer { + return writer.addString(additionalData).flush(code.startup) +} + +const query = (text: string): Buffer => { + return writer.addCString(text).flush(code.query) +} + +type ParseOpts = { + name?: string; + types?: number[]; + text: string; +} + +const emptyArray: any[] = [] + +const parse = (query: ParseOpts): Buffer => { + // expect something like this: + // { name: 'queryName', + // text: 'select * from blah', + // types: ['int8', 'bool'] } + + // normalize missing query names to allow for null + const name = query.name || '' + if (name.length > 63) { + /* eslint-disable no-console */ + console.error('Warning! Postgres only supports 63 characters for query names.') + console.error('You supplied %s (%s)', name, name.length) + console.error('This can cause conflicts and silent errors executing queries') + /* eslint-enable no-console */ + } + + const types = query.types || emptyArray + + var len = types.length + + var buffer = writer + .addCString(name) // name of query + .addCString(query.text) // actual query text + .addInt16(len) + + for (var i = 0; i < len; i++) { + buffer.addInt32(types[i]) + } + + return writer.flush(code.parse) +} + +type BindOpts = { + portal?: string; + binary?: boolean; + statement?: string; + values?: any[]; +} + +const bind = (config: BindOpts = {}): Buffer => { + // normalize config + const portal = config.portal || '' + const statement = config.statement || '' + const binary = config.binary || false + var values = config.values || emptyArray + var len = values.length + + var useBinary = false + // TODO(bmc): all the loops in here aren't nice, we can do better + for (var j = 0; j < len; j++) { + useBinary = useBinary || values[j] instanceof Buffer + } + + var buffer = writer + .addCString(portal) + .addCString(statement) + if (!useBinary) { + buffer.addInt16(0) + } else { + buffer.addInt16(len) + for (j = 0; j < len; j++) { + buffer.addInt16(values[j] instanceof Buffer ? 1 : 0) + } + } + buffer.addInt16(len) + for (var i = 0; i < len; i++) { + var val = values[i] + if (val === null || typeof val === 'undefined') { + buffer.addInt32(-1) + } else if (val instanceof Buffer) { + buffer.addInt32(val.length) + buffer.add(val) + } else { + buffer.addInt32(Buffer.byteLength(val)) + buffer.addString(val) + } + } + + if (binary) { + buffer.addInt16(1) // format codes to use binary + buffer.addInt16(1) + } else { + buffer.addInt16(0) // format codes to use text + } + return writer.flush(code.bind) +} + +type ExecOpts = { + portal?: string; + rows?: number; +} + +const emptyExecute = Buffer.from([code.execute, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00]) + +const execute = (config?: ExecOpts): Buffer => { + // this is the happy path for most queries + if (!config || !config.portal && !config.rows) { + return emptyExecute; + } + + const portal = config.portal || '' + const rows = config.rows || 0 + + const portalLength = Buffer.byteLength(portal) + const len = 4 + portalLength + 1 + 4 + // one extra bit for code + const buff = Buffer.allocUnsafe(1 + len) + buff[0] = code.execute + buff.writeInt32BE(len, 1) + buff.write(portal, 5, 'utf-8') + buff[portalLength + 5] = 0; // null terminate portal cString + buff.writeUInt32BE(rows, buff.length - 4) + return buff; +} + +const cancel = (processID: number, secretKey: number): Buffer => { + const buffer = Buffer.allocUnsafe(16) + buffer.writeInt32BE(16, 0) + buffer.writeInt16BE(1234, 4) + buffer.writeInt16BE(5678, 6) + buffer.writeInt32BE(processID, 8) + buffer.writeInt32BE(secretKey, 12) + return buffer; +} + +type PortalOpts = { + type: 'S' | 'P', + name?: string; +} + +const cstringMessage = (code: code, string: string): Buffer => { + const stringLen = Buffer.byteLength(string) + const len = 4 + stringLen + 1 + // one extra bit for code + const buffer = Buffer.allocUnsafe(1 + len) + buffer[0] = code + buffer.writeInt32BE(len, 1) + buffer.write(string, 5, 'utf-8') + buffer[len] = 0 // null terminate cString + return buffer +} + +const emptyDescribePortal = writer.addCString('P').flush(code.describe) +const emptyDescribeStatement = writer.addCString('S').flush(code.describe) + +const describe = (msg: PortalOpts): Buffer => { + return msg.name ? + cstringMessage(code.describe,`${msg.type}${msg.name || ''}`) : + msg.type === 'P' ? + emptyDescribePortal : + emptyDescribeStatement; +} + +const close = (msg: PortalOpts): Buffer => { + const text = `${msg.type}${msg.name || ''}` + return cstringMessage(code.close, text) +} + +const copyData = (chunk: Buffer): Buffer => { + return writer.add(chunk).flush(code.copyFromChunk) +} + +const copyFail = (message: string): Buffer => { + return cstringMessage(code.copyFail, message); +} + +const codeOnlyBuffer = (code: code): Buffer => Buffer.from([code, 0x00, 0x00, 0x00, 0x04]) + +const flushBuffer = codeOnlyBuffer(code.flush) +const syncBuffer = codeOnlyBuffer(code.sync) +const endBuffer = codeOnlyBuffer(code.end) +const copyDoneBuffer = codeOnlyBuffer(code.copyDone) + +const serialize = { + startup, + password, + requestSsl, + sendSASLInitialResponseMessage, + sendSCRAMClientFinalMessage, + query, + parse, + bind, + execute, + describe, + close, + flush: () => flushBuffer, + sync: () => syncBuffer, + end: () => endBuffer, + copyData, + copyDone: () => copyDoneBuffer, + copyFail, + cancel +} + +export { serialize } diff --git a/packages/pg-packet-stream/src/testing/buffer-list.ts b/packages/pg-protocol/src/testing/buffer-list.ts similarity index 100% rename from packages/pg-packet-stream/src/testing/buffer-list.ts rename to packages/pg-protocol/src/testing/buffer-list.ts diff --git a/packages/pg-packet-stream/src/testing/test-buffers.ts b/packages/pg-protocol/src/testing/test-buffers.ts similarity index 100% rename from packages/pg-packet-stream/src/testing/test-buffers.ts rename to packages/pg-protocol/src/testing/test-buffers.ts diff --git a/packages/pg-packet-stream/src/types/chunky.d.ts b/packages/pg-protocol/src/types/chunky.d.ts similarity index 100% rename from packages/pg-packet-stream/src/types/chunky.d.ts rename to packages/pg-protocol/src/types/chunky.d.ts diff --git a/packages/pg-packet-stream/tsconfig.json b/packages/pg-protocol/tsconfig.json similarity index 100% rename from packages/pg-packet-stream/tsconfig.json rename to packages/pg-protocol/tsconfig.json diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index ecbb362c9..71ef63ba6 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -11,11 +11,8 @@ var net = require('net') var EventEmitter = require('events').EventEmitter var util = require('util') -var Writer = require('buffer-writer') // eslint-disable-next-line -const { parse } = require('pg-packet-stream') - -var TEXT_MODE = 0 +const { parse, serialize } = require('../../pg-protocol/dist') // TODO(bmc) support binary mode here // var BINARY_MODE = 1 @@ -28,15 +25,9 @@ var Connection = function (config) { this._keepAlive = config.keepAlive this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis this.lastBuffer = false - this.lastOffset = 0 - this.buffer = null - this.offset = null - this.encoding = config.encoding || 'utf8' this.parsedStatements = {} - this.writer = new Writer() this.ssl = config.ssl || false this._ending = false - this._mode = TEXT_MODE this._emitMessage = false var self = this this.on('newListener', function (eventName) { @@ -122,244 +113,103 @@ Connection.prototype.attachListeners = function (stream) { } Connection.prototype.requestSsl = function () { - var bodyBuffer = this.writer - .addInt16(0x04d2) - .addInt16(0x162f) - .flush() - - var length = bodyBuffer.length + 4 - - var buffer = new Writer() - .addInt32(length) - .add(bodyBuffer) - .join() - this.stream.write(buffer) + this.stream.write(serialize.requestSsl()) } Connection.prototype.startup = function (config) { - var writer = this.writer.addInt16(3).addInt16(0) - - Object.keys(config).forEach(function (key) { - var val = config[key] - writer.addCString(key).addCString(val) - }) - - writer.addCString('client_encoding').addCString("'utf-8'") - - var bodyBuffer = writer.addCString('').flush() - // this message is sent without a code - - var length = bodyBuffer.length + 4 - - var buffer = new Writer() - .addInt32(length) - .add(bodyBuffer) - .join() - this.stream.write(buffer) + this.stream.write(serialize.startup(config)) } Connection.prototype.cancel = function (processID, secretKey) { - var bodyBuffer = this.writer - .addInt16(1234) - .addInt16(5678) - .addInt32(processID) - .addInt32(secretKey) - .flush() - - var length = bodyBuffer.length + 4 - - var buffer = new Writer() - .addInt32(length) - .add(bodyBuffer) - .join() - this.stream.write(buffer) + this._send(serialize.cancel(processID, secretKey)) } Connection.prototype.password = function (password) { - // 0x70 = 'p' - this._send(0x70, this.writer.addCString(password)) + this._send(serialize.password(password)) } Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) { - // 0x70 = 'p' - this.writer - .addCString(mechanism) - .addInt32(Buffer.byteLength(initialResponse)) - .addString(initialResponse) - - this._send(0x70) + this._send(serialize.sendSASLInitialResponseMessage(mechanism, initialResponse)) } Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) { - // 0x70 = 'p' - this.writer.addString(additionalData) - - this._send(0x70) + this._send(serialize.sendSCRAMClientFinalMessage(additionalData)) } -Connection.prototype._send = function (code, more) { +Connection.prototype._send = function (buffer) { if (!this.stream.writable) { return false } - return this.stream.write(this.writer.flush(code)) + return this.stream.write(buffer) } Connection.prototype.query = function (text) { - // 0x51 = Q - this.stream.write(this.writer.addCString(text).flush(0x51)) + this._send(serialize.query(text)) } // send parse message Connection.prototype.parse = function (query) { - // expect something like this: - // { name: 'queryName', - // text: 'select * from blah', - // types: ['int8', 'bool'] } - - // normalize missing query names to allow for null - query.name = query.name || '' - if (query.name.length > 63) { - /* eslint-disable no-console */ - console.error('Warning! Postgres only supports 63 characters for query names.') - console.error('You supplied %s (%s)', query.name, query.name.length) - console.error('This can cause conflicts and silent errors executing queries') - /* eslint-enable no-console */ - } - // normalize null type array - query.types = query.types || [] - var len = query.types.length - var buffer = this.writer - .addCString(query.name) // name of query - .addCString(query.text) // actual query text - .addInt16(len) - for (var i = 0; i < len; i++) { - buffer.addInt32(query.types[i]) - } - - var code = 0x50 - this._send(code) - this.flush() + this._send(serialize.parse(query)) } // send bind message // "more" === true to buffer the message until flush() is called Connection.prototype.bind = function (config) { - // normalize config - config = config || {} - config.portal = config.portal || '' - config.statement = config.statement || '' - config.binary = config.binary || false - var values = config.values || [] - var len = values.length - var useBinary = false - for (var j = 0; j < len; j++) { - useBinary |= values[j] instanceof Buffer - } - var buffer = this.writer.addCString(config.portal).addCString(config.statement) - if (!useBinary) { - buffer.addInt16(0) - } else { - buffer.addInt16(len) - for (j = 0; j < len; j++) { - buffer.addInt16(values[j] instanceof Buffer) - } - } - buffer.addInt16(len) - for (var i = 0; i < len; i++) { - var val = values[i] - if (val === null || typeof val === 'undefined') { - buffer.addInt32(-1) - } else if (val instanceof Buffer) { - buffer.addInt32(val.length) - buffer.add(val) - } else { - buffer.addInt32(Buffer.byteLength(val)) - buffer.addString(val) - } - } - - if (config.binary) { - buffer.addInt16(1) // format codes to use binary - buffer.addInt16(1) - } else { - buffer.addInt16(0) // format codes to use text - } - // 0x42 = 'B' - this._send(0x42) - this.flush() + this._send(serialize.bind(config)) } // send execute message // "more" === true to buffer the message until flush() is called Connection.prototype.execute = function (config) { - config = config || {} - config.portal = config.portal || '' - config.rows = config.rows || '' - this.writer.addCString(config.portal).addInt32(config.rows) - - // 0x45 = 'E' - this._send(0x45) - this.flush() + this._send(serialize.execute(config)) } -var emptyBuffer = Buffer.alloc(0) - -const flushBuffer = Buffer.from([0x48, 0x00, 0x00, 0x00, 0x04]) +const flushBuffer = serialize.flush() Connection.prototype.flush = function () { if (this.stream.writable) { this.stream.write(flushBuffer) } } -const syncBuffer = Buffer.from([0x53, 0x00, 0x00, 0x00, 0x04]) +const syncBuffer = serialize.sync() Connection.prototype.sync = function () { this._ending = true - // clear out any pending data in the writer - this.writer.clear() - if (this.stream.writable) { - this.stream.write(syncBuffer) - this.stream.write(flushBuffer) - } + this._send(syncBuffer) + this._send(flushBuffer) } -const END_BUFFER = Buffer.from([0x58, 0x00, 0x00, 0x00, 0x04]) +const endBuffer = serialize.end() Connection.prototype.end = function () { // 0x58 = 'X' - this.writer.clear() this._ending = true if (!this.stream.writable) { this.stream.end() return } - return this.stream.write(END_BUFFER, () => { + return this.stream.write(endBuffer, () => { this.stream.end() }) } Connection.prototype.close = function (msg) { - this.writer.addCString(msg.type + (msg.name || '')) - this._send(0x43) + this._send(serialize.close(msg)) } Connection.prototype.describe = function (msg) { - this.writer.addCString(msg.type + (msg.name || '')) - this._send(0x44) - this.flush() + this._send(serialize.describe(msg)) } Connection.prototype.sendCopyFromChunk = function (chunk) { - this.stream.write(this.writer.add(chunk).flush(0x64)) + this._send(serialize.copyData(chunk)) } Connection.prototype.endCopyFrom = function () { - this.stream.write(this.writer.add(emptyBuffer).flush(0x63)) + this._send(serialize.copyDone()) } Connection.prototype.sendCopyFail = function (msg) { - // this.stream.write(this.writer.add(emptyBuffer).flush(0x66)); - this.writer.addCString(msg) - this._send(0x66) + this._send(serialize.copyFail(msg)) } module.exports = Connection diff --git a/packages/pg/package.json b/packages/pg/package.json index edd24337b..b0bd735f5 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -22,7 +22,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "0.1.3", - "pg-packet-stream": "^1.1.0", + "pg-protocol": "^1.1.0", "pg-pool": "^3.0.0", "pg-types": "^2.1.0", "pgpass": "1.x", From 0a90e018cde96268563c2678aa8739b7f9f6552a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 9 Apr 2020 13:22:14 -0500 Subject: [PATCH 0611/1037] Publish - pg-cursor@2.1.8 - pg-protocol@1.2.0 - pg-query-stream@3.0.5 - pg@8.0.1 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 9694f9745..433d7f859 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.1.7", + "version": "2.1.8", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -21,7 +21,7 @@ "eslint-config-prettier": "^6.4.0", "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "^8.0.0", + "pg": "^8.0.1", "prettier": "^1.18.2" }, "prettier": { diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index e3e5640cd..62b5961d0 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.1.0", + "version": "1.2.0", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 6c35db0c1..9690079ae 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.0.4", + "version": "3.0.5", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -27,12 +27,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^6.2.2", - "pg": "^8.0.0", + "pg": "^8.0.1", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.1.7" + "pg-cursor": "^2.1.8" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index b0bd735f5..0e9eb96b2 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.0.0", + "version": "8.0.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -22,8 +22,8 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "0.1.3", - "pg-protocol": "^1.1.0", "pg-pool": "^3.0.0", + "pg-protocol": "^1.2.0", "pg-types": "^2.1.0", "pgpass": "1.x", "semver": "4.3.2" From de81f71417c440222be86e7fe0bef803da2264bb Mon Sep 17 00:00:00 2001 From: Chris Chew Date: Thu, 9 Apr 2020 14:08:11 -0500 Subject: [PATCH 0612/1037] Added maxUses config option to Pool; Dev setup instructions in main README --- README.md | 8 +++ packages/pg-pool/README.md | 26 ++++++++++ packages/pg-pool/index.js | 8 ++- packages/pg-pool/test/max-uses.js | 85 +++++++++++++++++++++++++++++++ 4 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 packages/pg-pool/test/max-uses.js diff --git a/README.md b/README.md index d22ac0c61..d963edc20 100644 --- a/README.md +++ b/README.md @@ -77,6 +77,14 @@ I will __happily__ accept your pull request if it: If your change involves breaking backwards compatibility please please point that out in the pull request & we can discuss & plan when and how to release it and what type of documentation or communication it will require. +### Setting up for local development + +1. Clone the repo +2. From your workspace root run `yarn` and then `yarn lerna bootstrap` +3. Ensure you have a PostgreSQL instance running with SSL enabled and an empty database for tests +4. Ensure you have the proper environment variables configured for connecting to the instance +5. Run `yarn test` to run all the tests + ## Troubleshooting and FAQ The causes and solutions to common errors can be found among the [Frequently Asked Questions (FAQ)](https://github.com/brianc/node-postgres/wiki/FAQ) diff --git a/packages/pg-pool/README.md b/packages/pg-pool/README.md index b77b65d86..f1c81ae52 100644 --- a/packages/pg-pool/README.md +++ b/packages/pg-pool/README.md @@ -34,6 +34,7 @@ var pool2 = new Pool({ max: 20, // set pool max size to 20 idleTimeoutMillis: 1000, // close idle clients after 1 second connectionTimeoutMillis: 1000, // return an error after 1 second if connection could not be established + maxUses: 7500, // close (and replace) a connection after it has been used 7500 times (see below for discussion) }) //you can supply a custom client constructor @@ -330,6 +331,31 @@ var bluebirdPool = new Pool({ __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." +## maxUses and read-replica autoscaling (e.g. AWS Aurora) + +The maxUses config option can help an application instance rebalance load against a replica set that has been auto-scaled after the connection pool is already full of healthy connections. + +The mechanism here is that a connection is considered "expended" after it has been acquired and released `maxUses` number of times. Depending on the load on your system, this means there will be an approximate time in which any given connection will live, thus creating a window for rebalancing. + +Imagine a scenario where you have 10 app instances providing an API running against a replica cluster of 3 that are accessed via a round-robin DNS entry. Each instance runs a connection pool size of 20. With an ambient load of 50 requests per second, the connection pool will likely fill up in a few minutes with healthy connections. + +If you have weekly bursts of traffic which peak at 1,000 requests per second, you might want to grow your replicas to 10 during this period. Without setting `maxUses`, the new replicas will not be adopted by the app servers without an intervention -- namely, restarting each in turn in order to build up new connection pools that are balanced against all the replicas. Adding additional app server instances will help to some extent because they will adopt all the replicas in an even way, but the initial app servers will continue to focus additional load on the original replicas. + +This is where the `maxUses` configuration option comes into play. Setting `maxUses` to 7500 will ensure that over a period of 30 minutes or so the new replicas will be adopted as the pre-existing connections are closed and replaced with new ones, thus creating a window for eventual balance. + +You'll want to test based on your own scenarios, but one way to make a first guess at `maxUses` is to identify an acceptable window for rebalancing and then solve for the value: + +``` +maxUses = rebalanceWindowSeconds * totalRequestsPerSecond / numAppInstances / poolSize +``` + +In the example above, assuming we acquire and release 1 connection per request and we are aiming for a 30 minute rebalancing window: + +``` +maxUses = rebalanceWindowSeconds * totalRequestsPerSecond / numAppInstances / poolSize + 7200 = 1800 * 1000 / 10 / 25 +``` + ## tests To run tests clone the repo, `npm i` in the working dir, and then run `npm test` diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index e144bb83b..32a4736d7 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -77,6 +77,7 @@ class Pool extends EventEmitter { } this.options.max = this.options.max || this.options.poolSize || 10 + this.options.maxUses = this.options.maxUses || Infinity this.log = this.options.log || function () { } this.Client = this.options.Client || Client || require('pg').Client this.Promise = this.options.Promise || global.Promise @@ -296,8 +297,13 @@ class Pool extends EventEmitter { _release (client, idleListener, err) { client.on('error', idleListener) + client._poolUseCount = (client._poolUseCount || 0) + 1 + // TODO(bmc): expose a proper, public interface _queryable and _ending - if (err || this.ending || !client._queryable || client._ending) { + if (err || this.ending || !client._queryable || client._ending || client._poolUseCount >= this.options.maxUses) { + if (client._poolUseCount >= this.options.maxUses) { + this.log('remove expended client') + } this._remove(client) this._pulseQueue() return diff --git a/packages/pg-pool/test/max-uses.js b/packages/pg-pool/test/max-uses.js new file mode 100644 index 000000000..2abede31e --- /dev/null +++ b/packages/pg-pool/test/max-uses.js @@ -0,0 +1,85 @@ +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('maxUses', () => { + it('can create a single client and use it once', co.wrap(function * () { + const pool = new Pool({ maxUses: 2 }) + 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('getting a connection a second time returns the same connection and releasing it also closes it', co.wrap(function * () { + const pool = new Pool({ maxUses: 2 }) + expect(pool.waitingCount).to.equal(0) + const client = yield pool.connect() + client.release() + const client2 = yield pool.connect() + expect(client).to.equal(client2) + expect(client2._ending).to.equal(false) + client2.release() + expect(client2._ending).to.equal(true) + return yield pool.end() + })) + + it('getting a connection a third time returns a new connection', co.wrap(function * () { + const pool = new Pool({ maxUses: 2 }) + expect(pool.waitingCount).to.equal(0) + const client = yield pool.connect() + client.release() + const client2 = yield pool.connect() + expect(client).to.equal(client2) + client2.release() + const client3 = yield pool.connect() + expect(client3).not.to.equal(client2) + client3.release() + return yield pool.end() + })) + + it('getting a connection from a pending request gets a fresh client when the released candidate is expended', co.wrap(function * () { + const pool = new Pool({ max: 1, maxUses: 2 }) + expect(pool.waitingCount).to.equal(0) + const client1 = yield pool.connect() + pool.connect() + .then(client2 => { + expect(client2).to.equal(client1) + expect(pool.waitingCount).to.equal(1) + // Releasing the client this time should also expend it since maxUses is 2, causing client3 to be a fresh client + client2.release() + }) + const client3Promise = pool.connect() + .then(client3 => { + // client3 should be a fresh client since client2's release caused the first client to be expended + expect(pool.waitingCount).to.equal(0) + expect(client3).not.to.equal(client1) + return client3.release() + }) + // There should be two pending requests since we have 3 connect requests but a max size of 1 + expect(pool.waitingCount).to.equal(2) + // Releasing the client should not yet expend it since maxUses is 2 + client1.release() + yield client3Promise + return yield pool.end() + })) + + it('logs when removing an expended client', co.wrap(function * () { + const messages = [] + const log = function (msg) { + messages.push(msg) + } + const pool = new Pool({ maxUses: 1, log }) + const client = yield pool.connect() + client.release() + expect(messages).to.contain('remove expended client') + return yield pool.end() + })) +}) From ae5dae4fa49f14267d0ad473f06f2c819d95a1e5 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 9 Apr 2020 14:58:48 -0500 Subject: [PATCH 0613/1037] Make several small speed tweaks for binary reading & writing (#2158) --- packages/pg-protocol/src/b.ts | 8 ++++++-- packages/pg-protocol/src/buffer-reader.ts | 22 +++++++++++++++------- packages/pg-protocol/src/parser.ts | 11 ++++------- packages/pg/bench.js | 2 +- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/packages/pg-protocol/src/b.ts b/packages/pg-protocol/src/b.ts index 267d211c4..dbf9f52ef 100644 --- a/packages/pg-protocol/src/b.ts +++ b/packages/pg-protocol/src/b.ts @@ -2,12 +2,16 @@ import { Writer } from './buffer-writer' import { serialize } from './index' +import { BufferReader } from './buffer-reader' const LOOPS = 1000 let count = 0 let start = Date.now() const writer = new Writer() +const reader = new BufferReader() +const buffer = Buffer.from([33, 33, 33, 33, 33, 33, 33, 0]) + const run = () => { if (count > LOOPS) { console.log(Date.now() - start) @@ -15,8 +19,8 @@ const run = () => { } count++ for(let i = 0; i < LOOPS; i++) { - serialize.describe({ type: 'P'}) - serialize.describe({ type: 'S'}) + reader.setBuffer(0, buffer) + reader.cstring() } setImmediate(run) } diff --git a/packages/pg-protocol/src/buffer-reader.ts b/packages/pg-protocol/src/buffer-reader.ts index 68dc89cae..cb7d4e3bd 100644 --- a/packages/pg-protocol/src/buffer-reader.ts +++ b/packages/pg-protocol/src/buffer-reader.ts @@ -8,36 +8,44 @@ export class BufferReader { constructor(private offset: number = 0) { } + public setBuffer(offset: number, buffer: Buffer): void { this.offset = offset; this.buffer = buffer; } - public int16() { + + public int16(): number { const result = this.buffer.readInt16BE(this.offset); this.offset += 2; return result; } - public byte() { + + public byte(): number { const result = this.buffer[this.offset]; this.offset++; return result; } - public int32() { + + public int32(): number { const result = this.buffer.readInt32BE(this.offset); this.offset += 4; return result; } + public string(length: number): string { const result = this.buffer.toString(this.encoding, this.offset, this.offset + length); this.offset += length; return result; } + public cstring(): string { - var start = this.offset; - var end = this.buffer.indexOf(0, start); - this.offset = end + 1; - return this.buffer.toString(this.encoding, start, end); + const start = this.offset; + let end = start + while(this.buffer[end++] !== 0) { }; + this.offset = end; + return this.buffer.toString(this.encoding, start, end - 1); } + public bytes(length: number): Buffer { const result = this.buffer.slice(this.offset, this.offset + length); this.offset += length; diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 69a9c28b2..14573e624 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -214,11 +214,8 @@ export class Parser { const fields: any[] = new Array(fieldCount); for (let i = 0; i < fieldCount; i++) { const len = this.reader.int32(); - if (len === -1) { - fields[i] = null - } else if (this.mode === 'text') { - fields[i] = this.reader.string(len) - } + // a -1 for length means the value of the field is null + fields[i] = len === -1 ? null : this.reader.string(len) } return new DataRowMessage(length, fields); } @@ -290,8 +287,8 @@ export class Parser { private parseErrorMessage(offset: number, length: number, bytes: Buffer, name: MessageName) { this.reader.setBuffer(offset, bytes); - var fields: Record = {} - var fieldType = this.reader.string(1) + const fields: Record = {} + let fieldType = this.reader.string(1) while (fieldType !== '\0') { fields[fieldType] = this.reader.cstring() fieldType = this.reader.string(1) diff --git a/packages/pg/bench.js b/packages/pg/bench.js index b5707db73..4fde9170f 100644 --- a/packages/pg/bench.js +++ b/packages/pg/bench.js @@ -54,7 +54,7 @@ const run = async () => { queries = await bench(client, seq, seconds * 1000); console.log("sequence queries:", queries); console.log("qps", queries / seconds); - console.log("on my laptop best so far seen 1209 qps") + console.log("on my laptop best so far seen 1309 qps") console.log('') queries = await bench(client, insert, seconds * 1000); From da03b3f9050c85a7722413a03c199cc3bdbcf5bf Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 9 Apr 2020 15:17:54 -0500 Subject: [PATCH 0614/1037] Publish - pg-cursor@2.1.9 - pg-pool@3.1.0 - pg-protocol@1.2.1 - pg-query-stream@3.0.6 - pg@8.0.2 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 433d7f859..dc5e02e1a 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.1.8", + "version": "2.1.9", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -21,7 +21,7 @@ "eslint-config-prettier": "^6.4.0", "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "^8.0.1", + "pg": "^8.0.2", "prettier": "^1.18.2" }, "prettier": { diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 788a49292..4eb998ed1 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.0.0", + "version": "3.1.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 62b5961d0..476941dd4 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.2.0", + "version": "1.2.1", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 9690079ae..7f8f2f806 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.0.5", + "version": "3.0.6", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -27,12 +27,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^6.2.2", - "pg": "^8.0.1", + "pg": "^8.0.2", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.1.8" + "pg-cursor": "^2.1.9" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 0e9eb96b2..91e78d33f 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.0.1", + "version": "8.0.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -22,8 +22,8 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "0.1.3", - "pg-pool": "^3.0.0", - "pg-protocol": "^1.2.0", + "pg-pool": "^3.1.0", + "pg-protocol": "^1.2.1", "pg-types": "^2.1.0", "pgpass": "1.x", "semver": "4.3.2" From 41c899c5a20766519ebaf7b0e6548569a60b94b4 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 9 Apr 2020 15:19:53 -0500 Subject: [PATCH 0615/1037] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41eaca70e..ab356e0f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### pg-pool@3.1.0 + +- Add [maxUses](https://github.com/brianc/node-postgres/pull/2157) config option. + ### pg@8.0.0 #### note: for detailed release notes please [check here](https://node-postgres.com/announcements#2020-02-25) From a8471aa54b8bedd652170452653b74f9cfc041f6 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 10 Apr 2020 10:29:13 -0500 Subject: [PATCH 0616/1037] Set up prettier in workspace dir --- .eslintrc | 25 ++---- .prettierrc.json | 6 ++ package.json | 11 ++- packages/pg-cursor/package.json | 12 +-- yarn.lock | 151 +++++++++++++++++++++++++++++--- 5 files changed, 161 insertions(+), 44 deletions(-) create mode 100644 .prettierrc.json diff --git a/.eslintrc b/.eslintrc index e4ff2e0f0..511bbc79a 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,14 +1,17 @@ { "plugins": [ - "node" + "prettier" ], "extends": [ - "standard", - "eslint:recommended", - "plugin:node/recommended" + "plugin:prettier/recommended" ], "ignorePatterns": [ - "**/*.ts" + "**/*.ts", + "node_modules", + "packages/pg", + "packages/pg-protocol", + "packages/pg-pool", + "packages/pg-query-stream" ], "parserOptions": { "ecmaVersion": 2017, @@ -18,17 +21,5 @@ "node": true, "es6": true, "mocha": true - }, - "rules": { - "space-before-function-paren": "off", - "node/no-unsupported-features/es-syntax": "off", - "node/no-unpublished-require": [ - "error", - { - "allowModules": [ - "pg" - ] - } - ] } } diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 000000000..7e83b67a6 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "semi": true, + "printWidth": 120, + "trailingComma": "es5", + "singleQuote": true +} diff --git a/package.json b/package.json index 160180777..0e2841fd3 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,12 @@ "lint": "yarn lerna exec --parallel yarn lint" }, "devDependencies": { - "lerna": "^3.19.0" - }, - "dependencies": {} + "@typescript-eslint/eslint-plugin": "^2.27.0", + "eslint": "^6.8.0", + "eslint-config-prettier": "^6.10.1", + "eslint-plugin-node": "^11.1.0", + "eslint-plugin-prettier": "^3.1.2", + "lerna": "^3.19.0", + "prettier": "^2.0.4" + } } diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index dc5e02e1a..04f4d77eb 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -17,17 +17,7 @@ "author": "Brian M. Carlson", "license": "MIT", "devDependencies": { - "eslint": "^6.5.1", - "eslint-config-prettier": "^6.4.0", - "eslint-plugin-prettier": "^3.1.1", "mocha": "^6.2.2", - "pg": "^8.0.2", - "prettier": "^1.18.2" - }, - "prettier": { - "semi": false, - "printWidth": 120, - "trailingComma": "none", - "singleQuote": true + "pg": "^8.0.2" } } diff --git a/yarn.lock b/yarn.lock index 43c90a76a..812bf9158 100644 --- a/yarn.lock +++ b/yarn.lock @@ -850,6 +850,11 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/json-schema@^7.0.3": + version "7.0.4" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" + integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -865,6 +870,39 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.21.tgz#aa44a6363291c7037111c47e4661ad210aded23f" integrity sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA== +"@typescript-eslint/eslint-plugin@^2.27.0": + version "2.27.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.27.0.tgz#e479cdc4c9cf46f96b4c287755733311b0d0ba4b" + integrity sha512-/my+vVHRN7zYgcp0n4z5A6HAK7bvKGBiswaM5zIlOQczsxj/aiD7RcgD+dvVFuwFaGh5+kM7XA6Q6PN0bvb1tw== + dependencies: + "@typescript-eslint/experimental-utils" "2.27.0" + functional-red-black-tree "^1.0.1" + regexpp "^3.0.0" + tsutils "^3.17.1" + +"@typescript-eslint/experimental-utils@2.27.0": + version "2.27.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.27.0.tgz#801a952c10b58e486c9a0b36cf21e2aab1e9e01a" + integrity sha512-vOsYzjwJlY6E0NJRXPTeCGqjv5OHgRU1kzxHKWJVPjDYGbPgLudBXjIlc+OD1hDBZ4l1DLbOc5VjofKahsu9Jw== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "2.27.0" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/typescript-estree@2.27.0": + version "2.27.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.27.0.tgz#a288e54605412da8b81f1660b56c8b2e42966ce8" + integrity sha512-t2miCCJIb/FU8yArjAvxllxbTiyNqaXJag7UOpB5DVoM3+xnjeOngtqlJkLRnMtzaRcJhe3CIR9RmL40omubhg== + dependencies: + debug "^4.1.1" + eslint-visitor-keys "^1.1.0" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^6.3.0" + tsutils "^3.17.1" + "@zkochan/cmd-shim@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz#2ab8ed81f5bb5452a85f25758eb9b8681982fd2e" @@ -1772,7 +1810,7 @@ debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: dependencies: ms "2.0.0" -debug@^4.0.1: +debug@^4.0.1, debug@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== @@ -2036,10 +2074,10 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -eslint-config-prettier@^6.4.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.7.0.tgz#9a876952e12df2b284adbd3440994bf1f39dfbb9" - integrity sha512-FamQVKM3jjUVwhG4hEMnbtsq7xOIDm+SY5iBPfR8gKsJoAB2IQnNF+bk1+8Fy44Nq7PPJaLvkRxILYdJWoguKQ== +eslint-config-prettier@^6.10.1: + version "6.10.1" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.10.1.tgz#129ef9ec575d5ddc0e269667bf09defcd898642a" + integrity sha512-svTy6zh1ecQojvpbJSgH3aei/Rt7C6i090l5f2WQ4aB05lYHeZIR1qL4wZyyILTbtmnbHP5Yn8MrsOJMGa8RkQ== dependencies: get-stdin "^6.0.0" @@ -2072,6 +2110,14 @@ eslint-plugin-es@^1.4.1: eslint-utils "^1.4.2" regexpp "^2.0.1" +eslint-plugin-es@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.0.tgz#98cb1bc8ab0aa807977855e11ad9d1c9422d014b" + integrity sha512-6/Jb/J/ZvSebydwbBJO1R9E5ky7YeElfK56Veh7e4QGFHCXoIXGH9HhVz+ibJLM3XJ1XjP+T7rKBLUa/Y7eIng== + dependencies: + eslint-utils "^2.0.0" + regexpp "^3.0.0" + eslint-plugin-import@^2.18.1: version "2.19.1" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.19.1.tgz#5654e10b7839d064dd0d46cd1b88ec2133a11448" @@ -2090,6 +2136,18 @@ eslint-plugin-import@^2.18.1: read-pkg-up "^2.0.0" resolve "^1.12.0" +eslint-plugin-node@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" + integrity sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g== + dependencies: + eslint-plugin-es "^3.0.0" + eslint-utils "^2.0.0" + ignore "^5.1.1" + minimatch "^3.0.4" + resolve "^1.10.1" + semver "^6.1.0" + eslint-plugin-node@^9.1.0: version "9.2.0" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-9.2.0.tgz#b1911f111002d366c5954a6d96d3cd5bf2a3036a" @@ -2102,7 +2160,7 @@ eslint-plugin-node@^9.1.0: resolve "^1.10.1" semver "^6.1.0" -eslint-plugin-prettier@^3.1.1: +eslint-plugin-prettier@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz#432e5a667666ab84ce72f945c72f77d996a5c9ba" integrity sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA== @@ -2139,12 +2197,19 @@ eslint-utils@^1.4.2, eslint-utils@^1.4.3: dependencies: eslint-visitor-keys "^1.1.0" +eslint-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" + integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA== + dependencies: + eslint-visitor-keys "^1.1.0" + eslint-visitor-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== -eslint@^6.0.1, eslint@^6.5.1: +eslint@^6.0.1: version "6.7.2" resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.2.tgz#c17707ca4ad7b2d8af986a33feba71e18a9fecd1" integrity sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng== @@ -2187,6 +2252,49 @@ eslint@^6.0.1, eslint@^6.5.1: text-table "^0.2.0" v8-compile-cache "^2.0.3" +eslint@^6.8.0: + version "6.8.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" + integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.10.0" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^5.0.0" + eslint-utils "^1.4.3" + eslint-visitor-keys "^1.1.0" + espree "^6.1.2" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^7.0.0" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.14" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.3" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^6.1.2" + strip-ansi "^5.2.0" + strip-json-comments "^3.0.1" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + espree@^6.1.2: version "6.1.2" resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" @@ -2684,7 +2792,7 @@ glob@7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: +glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -4509,10 +4617,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^1.18.2: - version "1.19.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" - integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== +prettier@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.4.tgz#2d1bae173e355996ee355ec9830a7a1ee05457ef" + integrity sha512-SVJIQ51spzFDvh4fIbCLvciiDMCrRhlN3mbZvv/+ycjvmF5E73bKdGfU8QDLNmjYJf+lsGnDBC4UUnvTe5OO0w== process-nextick-args@~2.0.0: version "2.0.1" @@ -4763,6 +4871,11 @@ regexpp@^2.0.1: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== +regexpp@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== + render@0.1: version "0.1.4" resolved "https://registry.yarnpkg.com/render/-/render-0.1.4.tgz#cfb33a34e26068591d418469e23d8cc5ce1ceff5" @@ -4945,7 +5058,7 @@ semver@4.3.2: resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= -semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.2.0: +semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -5554,11 +5667,23 @@ ts-node@^8.5.4: source-map-support "^0.5.6" yn "^3.0.0" +tslib@^1.8.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" + integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== + tslib@^1.9.0: version "1.10.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tsutils@^3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" + integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== + dependencies: + tslib "^1.8.1" + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" From 3002d5cbddb8ed52ba27ce1481c5f9f48221fa91 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 10 Apr 2020 10:29:54 -0500 Subject: [PATCH 0617/1037] Auto-fix pg-cursor --- packages/pg-cursor/index.js | 214 ++++++------ packages/pg-cursor/test/close.js | 74 ++--- packages/pg-cursor/test/error-handling.js | 160 ++++----- packages/pg-cursor/test/index.js | 342 ++++++++++---------- packages/pg-cursor/test/no-data-handling.js | 60 ++-- packages/pg-cursor/test/pool.js | 132 ++++---- packages/pg-cursor/test/query-config.js | 58 ++-- packages/pg-cursor/test/transactions.js | 68 ++-- 8 files changed, 554 insertions(+), 554 deletions(-) diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index 727fe9081..7c041322a 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -1,218 +1,218 @@ -'use strict' -const Result = require('pg/lib/result.js') -const prepare = require('pg/lib/utils.js').prepareValue -const EventEmitter = require('events').EventEmitter -const util = require('util') +'use strict'; +const Result = require('pg/lib/result.js'); +const prepare = require('pg/lib/utils.js').prepareValue; +const EventEmitter = require('events').EventEmitter; +const util = require('util'); -let nextUniqueID = 1 // concept borrowed from org.postgresql.core.v3.QueryExecutorImpl +let nextUniqueID = 1; // concept borrowed from org.postgresql.core.v3.QueryExecutorImpl function Cursor(text, values, config) { - EventEmitter.call(this) - - this._conf = config || {} - this.text = text - this.values = values ? values.map(prepare) : null - this.connection = null - this._queue = [] - this.state = 'initialized' - this._result = new Result(this._conf.rowMode, this._conf.types) - this._cb = null - this._rows = null - this._portal = null - this._ifNoData = this._ifNoData.bind(this) - this._rowDescription = this._rowDescription.bind(this) + EventEmitter.call(this); + + this._conf = config || {}; + this.text = text; + this.values = values ? values.map(prepare) : null; + this.connection = null; + this._queue = []; + this.state = 'initialized'; + this._result = new Result(this._conf.rowMode, this._conf.types); + this._cb = null; + this._rows = null; + this._portal = null; + this._ifNoData = this._ifNoData.bind(this); + this._rowDescription = this._rowDescription.bind(this); } -util.inherits(Cursor, EventEmitter) +util.inherits(Cursor, EventEmitter); Cursor.prototype._ifNoData = function () { - this.state = 'idle' - this._shiftQueue() -} + this.state = 'idle'; + this._shiftQueue(); +}; Cursor.prototype._rowDescription = function () { if (this.connection) { - this.connection.removeListener('noData', this._ifNoData) + this.connection.removeListener('noData', this._ifNoData); } -} +}; Cursor.prototype.submit = function (connection) { - this.connection = connection - this._portal = 'C_' + nextUniqueID++ + this.connection = connection; + this._portal = 'C_' + nextUniqueID++; - const con = connection + const con = connection; con.parse( { - text: this.text + text: this.text, }, true - ) + ); con.bind( { portal: this._portal, - values: this.values + values: this.values, }, true - ) + ); con.describe( { type: 'P', - name: this._portal // AWS Redshift requires a portal name + name: this._portal, // AWS Redshift requires a portal name }, true - ) + ); - con.flush() + con.flush(); if (this._conf.types) { - this._result._getTypeParser = this._conf.types.getTypeParser + this._result._getTypeParser = this._conf.types.getTypeParser; } - con.once('noData', this._ifNoData) - con.once('rowDescription', this._rowDescription) -} + con.once('noData', this._ifNoData); + con.once('rowDescription', this._rowDescription); +}; Cursor.prototype._shiftQueue = function () { if (this._queue.length) { - this._getRows.apply(this, this._queue.shift()) + this._getRows.apply(this, this._queue.shift()); } -} +}; Cursor.prototype._closePortal = function () { // because we opened a named portal to stream results // we need to close the same named portal. Leaving a named portal // open can lock tables for modification if inside a transaction. // see https://github.com/brianc/node-pg-cursor/issues/56 - this.connection.close({ type: 'P', name: this._portal }) - this.connection.sync() -} + this.connection.close({ type: 'P', name: this._portal }); + this.connection.sync(); +}; Cursor.prototype.handleRowDescription = function (msg) { - this._result.addFields(msg.fields) - this.state = 'idle' - this._shiftQueue() -} + this._result.addFields(msg.fields); + this.state = 'idle'; + this._shiftQueue(); +}; Cursor.prototype.handleDataRow = function (msg) { - const row = this._result.parseRow(msg.fields) - this.emit('row', row, this._result) - this._rows.push(row) -} + const row = this._result.parseRow(msg.fields); + this.emit('row', row, this._result); + this._rows.push(row); +}; Cursor.prototype._sendRows = function () { - this.state = 'idle' + this.state = 'idle'; setImmediate(() => { - const cb = this._cb + const cb = this._cb; // remove callback before calling it // because likely a new one will be added // within the call to this callback - this._cb = null + this._cb = null; if (cb) { - this._result.rows = this._rows - cb(null, this._rows, this._result) + this._result.rows = this._rows; + cb(null, this._rows, this._result); } - this._rows = [] - }) -} + this._rows = []; + }); +}; Cursor.prototype.handleCommandComplete = function (msg) { - this._result.addCommandComplete(msg) - this._closePortal() -} + this._result.addCommandComplete(msg); + this._closePortal(); +}; Cursor.prototype.handlePortalSuspended = function () { - this._sendRows() -} + this._sendRows(); +}; Cursor.prototype.handleReadyForQuery = function () { - this._sendRows() - this.state = 'done' - this.emit('end', this._result) -} + this._sendRows(); + this.state = 'done'; + this.emit('end', this._result); +}; Cursor.prototype.handleEmptyQuery = function () { - this.connection.sync() -} + this.connection.sync(); +}; Cursor.prototype.handleError = function (msg) { - this.connection.removeListener('noData', this._ifNoData) - this.connection.removeListener('rowDescription', this._rowDescription) - this.state = 'error' - this._error = msg + this.connection.removeListener('noData', this._ifNoData); + this.connection.removeListener('rowDescription', this._rowDescription); + this.state = 'error'; + this._error = msg; // satisfy any waiting callback if (this._cb) { - this._cb(msg) + this._cb(msg); } // dispatch error to all waiting callbacks for (let i = 0; i < this._queue.length; i++) { - this._queue.pop()[1](msg) + this._queue.pop()[1](msg); } if (this.listenerCount('error') > 0) { // only dispatch error events if we have a listener - this.emit('error', msg) + this.emit('error', msg); } // call sync to keep this connection from hanging - this.connection.sync() -} + this.connection.sync(); +}; Cursor.prototype._getRows = function (rows, cb) { - this.state = 'busy' - this._cb = cb - this._rows = [] + this.state = 'busy'; + this._cb = cb; + this._rows = []; const msg = { portal: this._portal, - rows: rows - } - this.connection.execute(msg, true) - this.connection.flush() -} + rows: rows, + }; + this.connection.execute(msg, true); + this.connection.flush(); +}; // users really shouldn't be calling 'end' here and terminating a connection to postgres // via the low level connection.end api Cursor.prototype.end = util.deprecate(function (cb) { if (this.state !== 'initialized') { - this.connection.sync() + this.connection.sync(); } - this.connection.once('end', cb) - this.connection.end() -}, 'Cursor.end is deprecated. Call end on the client itself to end a connection to the database.') + this.connection.once('end', cb); + this.connection.end(); +}, 'Cursor.end is deprecated. Call end on the client itself to end a connection to the database.'); Cursor.prototype.close = function (cb) { if (!this.connection || this.state === 'done') { if (cb) { - return setImmediate(cb) + return setImmediate(cb); } else { - return + return; } } - this._closePortal() - this.state = 'done' + this._closePortal(); + this.state = 'done'; if (cb) { this.connection.once('readyForQuery', function () { - cb() - }) + cb(); + }); } -} +}; Cursor.prototype.read = function (rows, cb) { if (this.state === 'idle') { - return this._getRows(rows, cb) + return this._getRows(rows, cb); } if (this.state === 'busy' || this.state === 'initialized') { - return this._queue.push([rows, cb]) + return this._queue.push([rows, cb]); } if (this.state === 'error') { - return setImmediate(() => cb(this._error)) + return setImmediate(() => cb(this._error)); } if (this.state === 'done') { - return setImmediate(() => cb(null, [])) + return setImmediate(() => cb(null, [])); } else { - throw new Error('Unknown state: ' + this.state) + throw new Error('Unknown state: ' + this.state); } -} +}; -module.exports = Cursor +module.exports = Cursor; diff --git a/packages/pg-cursor/test/close.js b/packages/pg-cursor/test/close.js index e63512abd..ec545265f 100644 --- a/packages/pg-cursor/test/close.js +++ b/packages/pg-cursor/test/close.js @@ -1,54 +1,54 @@ -const assert = require('assert') -const Cursor = require('../') -const pg = require('pg') +const assert = require('assert'); +const Cursor = require('../'); +const pg = require('pg'); -const text = 'SELECT generate_series as num FROM generate_series(0, 50)' +const text = 'SELECT generate_series as num FROM generate_series(0, 50)'; describe('close', function () { beforeEach(function (done) { - const client = (this.client = new pg.Client()) - client.connect(done) - }) + const client = (this.client = new pg.Client()); + client.connect(done); + }); this.afterEach(function (done) { - this.client.end(done) - }) + this.client.end(done); + }); it('can close a finished cursor without a callback', function (done) { - const cursor = new Cursor(text) - this.client.query(cursor) - this.client.query('SELECT NOW()', done) + const cursor = new Cursor(text); + this.client.query(cursor); + this.client.query('SELECT NOW()', done); cursor.read(100, function (err) { - assert.ifError(err) - cursor.close() - }) - }) + assert.ifError(err); + cursor.close(); + }); + }); it('closes cursor early', function (done) { - const cursor = new Cursor(text) - this.client.query(cursor) - this.client.query('SELECT NOW()', done) + const cursor = new Cursor(text); + this.client.query(cursor); + this.client.query('SELECT NOW()', done); cursor.read(25, function (err) { - assert.ifError(err) - cursor.close() - }) - }) + assert.ifError(err); + cursor.close(); + }); + }); it('works with callback style', function (done) { - const cursor = new Cursor(text) - const client = this.client - client.query(cursor) + const cursor = new Cursor(text); + const client = this.client; + client.query(cursor); cursor.read(25, function (err, rows) { - assert.ifError(err) - assert.strictEqual(rows.length, 25) + assert.ifError(err); + assert.strictEqual(rows.length, 25); cursor.close(function (err) { - assert.ifError(err) - client.query('SELECT NOW()', done) - }) - }) - }) + assert.ifError(err); + client.query('SELECT NOW()', done); + }); + }); + }); it('is a no-op to "close" the cursor before submitting it', function (done) { - const cursor = new Cursor(text) - cursor.close(done) - }) -}) + const cursor = new Cursor(text); + cursor.close(done); + }); +}); diff --git a/packages/pg-cursor/test/error-handling.js b/packages/pg-cursor/test/error-handling.js index 43d34581f..235dbed38 100644 --- a/packages/pg-cursor/test/error-handling.js +++ b/packages/pg-cursor/test/error-handling.js @@ -1,86 +1,86 @@ -'use strict' -const assert = require('assert') -const Cursor = require('../') -const pg = require('pg') +'use strict'; +const assert = require('assert'); +const Cursor = require('../'); +const pg = require('pg'); -const text = 'SELECT generate_series as num FROM generate_series(0, 4)' +const text = 'SELECT generate_series as num FROM generate_series(0, 4)'; -describe('error handling', function() { - it('can continue after error', function(done) { - const client = new pg.Client() - client.connect() - const cursor = client.query(new Cursor('asdfdffsdf')) - cursor.read(1, function(err) { - assert(err) - client.query('SELECT NOW()', function(err) { - assert.ifError(err) - client.end() - done() - }) - }) - }) -}) +describe('error handling', function () { + it('can continue after error', function (done) { + const client = new pg.Client(); + client.connect(); + const cursor = client.query(new Cursor('asdfdffsdf')); + cursor.read(1, function (err) { + assert(err); + client.query('SELECT NOW()', function (err) { + assert.ifError(err); + client.end(); + done(); + }); + }); + }); +}); describe('read callback does not fire sync', () => { - it('does not fire error callback sync', done => { - const client = new pg.Client() - client.connect() - const cursor = client.query(new Cursor('asdfdffsdf')) - let after = false - cursor.read(1, function(err) { - assert(err, 'error should be returned') - assert.strictEqual(after, true, 'should not call read sync') - after = false - cursor.read(1, function(err) { - assert(err, 'error should be returned') - assert.strictEqual(after, true, 'should not call read sync') - client.end() - done() - }) - after = true - }) - after = true - }) + it('does not fire error callback sync', (done) => { + const client = new pg.Client(); + client.connect(); + const cursor = client.query(new Cursor('asdfdffsdf')); + let after = false; + cursor.read(1, function (err) { + assert(err, 'error should be returned'); + assert.strictEqual(after, true, 'should not call read sync'); + after = false; + cursor.read(1, function (err) { + assert(err, 'error should be returned'); + assert.strictEqual(after, true, 'should not call read sync'); + client.end(); + done(); + }); + after = true; + }); + after = true; + }); - it('does not fire result sync after finished', done => { - const client = new pg.Client() - client.connect() - const cursor = client.query(new Cursor('SELECT NOW()')) - let after = false - cursor.read(1, function(err) { - assert(!err) - assert.strictEqual(after, true, 'should not call read sync') - cursor.read(1, function(err) { - assert(!err) - after = false - cursor.read(1, function(err) { - assert(!err) - assert.strictEqual(after, true, 'should not call read sync') - client.end() - done() - }) - after = true - }) - }) - after = true - }) -}) + it('does not fire result sync after finished', (done) => { + const client = new pg.Client(); + client.connect(); + const cursor = client.query(new Cursor('SELECT NOW()')); + let after = false; + cursor.read(1, function (err) { + assert(!err); + assert.strictEqual(after, true, 'should not call read sync'); + cursor.read(1, function (err) { + assert(!err); + after = false; + cursor.read(1, function (err) { + assert(!err); + assert.strictEqual(after, true, 'should not call read sync'); + client.end(); + done(); + }); + after = true; + }); + }); + after = true; + }); +}); -describe('proper cleanup', function() { - it('can issue multiple cursors on one client', function(done) { - const client = new pg.Client() - client.connect() - const cursor1 = client.query(new Cursor(text)) - cursor1.read(8, function(err, rows) { - assert.ifError(err) - assert.strictEqual(rows.length, 5) - const cursor2 = client.query(new Cursor(text)) - cursor2.read(8, function(err, rows) { - assert.ifError(err) - assert.strictEqual(rows.length, 5) - client.end() - done() - }) - }) - }) -}) +describe('proper cleanup', function () { + it('can issue multiple cursors on one client', function (done) { + const client = new pg.Client(); + client.connect(); + const cursor1 = client.query(new Cursor(text)); + cursor1.read(8, function (err, rows) { + assert.ifError(err); + assert.strictEqual(rows.length, 5); + const cursor2 = client.query(new Cursor(text)); + cursor2.read(8, function (err, rows) { + assert.ifError(err); + assert.strictEqual(rows.length, 5); + client.end(); + done(); + }); + }); + }); +}); diff --git a/packages/pg-cursor/test/index.js b/packages/pg-cursor/test/index.js index fe210096e..4193bfab6 100644 --- a/packages/pg-cursor/test/index.js +++ b/packages/pg-cursor/test/index.js @@ -1,181 +1,181 @@ -const assert = require('assert') -const Cursor = require('../') -const pg = require('pg') - -const text = 'SELECT generate_series as num FROM generate_series(0, 5)' - -describe('cursor', function() { - beforeEach(function(done) { - const client = (this.client = new pg.Client()) - client.connect(done) - - this.pgCursor = function(text, values) { - return client.query(new Cursor(text, values || [])) - } - }) - - afterEach(function() { - this.client.end() - }) - - it('fetch 6 when asking for 10', function(done) { - const cursor = this.pgCursor(text) - cursor.read(10, function(err, res) { - assert.ifError(err) - assert.strictEqual(res.length, 6) - done() - }) - }) - - it('end before reading to end', function(done) { - const cursor = this.pgCursor(text) - cursor.read(3, function(err, res) { - assert.ifError(err) - assert.strictEqual(res.length, 3) - done() - }) - }) - - it('callback with error', function(done) { - const cursor = this.pgCursor('select asdfasdf') - cursor.read(1, function(err) { - assert(err) - done() - }) - }) - - it('read a partial chunk of data', function(done) { - const cursor = this.pgCursor(text) - cursor.read(2, function(err, res) { - assert.ifError(err) - assert.strictEqual(res.length, 2) - cursor.read(3, function(err, res) { - assert(!err) - assert.strictEqual(res.length, 3) - cursor.read(1, function(err, res) { - assert(!err) - assert.strictEqual(res.length, 1) - cursor.read(1, function(err, res) { - assert(!err) - assert.ifError(err) - assert.strictEqual(res.length, 0) - done() - }) - }) - }) - }) - }) - - it('read return length 0 past the end', function(done) { - const cursor = this.pgCursor(text) - cursor.read(2, function(err) { - assert(!err) - cursor.read(100, function(err, res) { - assert(!err) - assert.strictEqual(res.length, 4) - cursor.read(100, function(err, res) { - assert(!err) - assert.strictEqual(res.length, 0) - done() - }) - }) - }) - }) - - it('read huge result', function(done) { - this.timeout(10000) - const text = 'SELECT generate_series as num FROM generate_series(0, 100000)' - const values = [] - const cursor = this.pgCursor(text, values) - let count = 0 - const read = function() { - cursor.read(100, function(err, rows) { - if (err) return done(err) +const assert = require('assert'); +const Cursor = require('../'); +const pg = require('pg'); + +const text = 'SELECT generate_series as num FROM generate_series(0, 5)'; + +describe('cursor', function () { + beforeEach(function (done) { + const client = (this.client = new pg.Client()); + client.connect(done); + + this.pgCursor = function (text, values) { + return client.query(new Cursor(text, values || [])); + }; + }); + + afterEach(function () { + this.client.end(); + }); + + it('fetch 6 when asking for 10', function (done) { + const cursor = this.pgCursor(text); + cursor.read(10, function (err, res) { + assert.ifError(err); + assert.strictEqual(res.length, 6); + done(); + }); + }); + + it('end before reading to end', function (done) { + const cursor = this.pgCursor(text); + cursor.read(3, function (err, res) { + assert.ifError(err); + assert.strictEqual(res.length, 3); + done(); + }); + }); + + it('callback with error', function (done) { + const cursor = this.pgCursor('select asdfasdf'); + cursor.read(1, function (err) { + assert(err); + done(); + }); + }); + + it('read a partial chunk of data', function (done) { + const cursor = this.pgCursor(text); + cursor.read(2, function (err, res) { + assert.ifError(err); + assert.strictEqual(res.length, 2); + cursor.read(3, function (err, res) { + assert(!err); + assert.strictEqual(res.length, 3); + cursor.read(1, function (err, res) { + assert(!err); + assert.strictEqual(res.length, 1); + cursor.read(1, function (err, res) { + assert(!err); + assert.ifError(err); + assert.strictEqual(res.length, 0); + done(); + }); + }); + }); + }); + }); + + it('read return length 0 past the end', function (done) { + const cursor = this.pgCursor(text); + cursor.read(2, function (err) { + assert(!err); + cursor.read(100, function (err, res) { + assert(!err); + assert.strictEqual(res.length, 4); + cursor.read(100, function (err, res) { + assert(!err); + assert.strictEqual(res.length, 0); + done(); + }); + }); + }); + }); + + it('read huge result', function (done) { + this.timeout(10000); + const text = 'SELECT generate_series as num FROM generate_series(0, 100000)'; + const values = []; + const cursor = this.pgCursor(text, values); + let count = 0; + const read = function () { + cursor.read(100, function (err, rows) { + if (err) return done(err); if (!rows.length) { - assert.strictEqual(count, 100001) - return done() + assert.strictEqual(count, 100001); + return done(); } - count += rows.length + count += rows.length; if (count % 10000 === 0) { // console.log(count) } - setImmediate(read) - }) - } - read() - }) - - it('normalizes parameter values', function(done) { - const text = 'SELECT $1::json me' - const values = [{ name: 'brian' }] - const cursor = this.pgCursor(text, values) - cursor.read(1, function(err, rows) { - if (err) return done(err) - assert.strictEqual(rows[0].me.name, 'brian') - cursor.read(1, function(err, rows) { - assert(!err) - assert.strictEqual(rows.length, 0) - done() - }) - }) - }) - - it('returns result along with rows', function(done) { - const cursor = this.pgCursor(text) - cursor.read(1, function(err, rows, result) { - assert.ifError(err) - assert.strictEqual(rows.length, 1) - assert.strictEqual(rows, result.rows) + setImmediate(read); + }); + }; + read(); + }); + + it('normalizes parameter values', function (done) { + const text = 'SELECT $1::json me'; + const values = [{ name: 'brian' }]; + const cursor = this.pgCursor(text, values); + cursor.read(1, function (err, rows) { + if (err) return done(err); + assert.strictEqual(rows[0].me.name, 'brian'); + cursor.read(1, function (err, rows) { + assert(!err); + assert.strictEqual(rows.length, 0); + done(); + }); + }); + }); + + it('returns result along with rows', function (done) { + const cursor = this.pgCursor(text); + cursor.read(1, function (err, rows, result) { + assert.ifError(err); + assert.strictEqual(rows.length, 1); + assert.strictEqual(rows, result.rows); assert.deepStrictEqual( - result.fields.map(f => f.name), + result.fields.map((f) => f.name), ['num'] - ) - done() - }) - }) - - it('emits row events', function(done) { - const cursor = this.pgCursor(text) - cursor.read(10) - cursor.on('row', (row, result) => result.addRow(row)) - cursor.on('end', result => { - assert.strictEqual(result.rows.length, 6) - done() - }) - }) - - it('emits row events when cursor is closed manually', function(done) { - const cursor = this.pgCursor(text) - cursor.on('row', (row, result) => result.addRow(row)) - cursor.on('end', result => { - assert.strictEqual(result.rows.length, 3) - done() - }) - - cursor.read(3, () => cursor.close()) - }) - - it('emits error events', function(done) { - const cursor = this.pgCursor('select asdfasdf') - cursor.on('error', function(err) { - assert(err) - done() - }) - }) - - it('returns rowCount on insert', function(done) { - const pgCursor = this.pgCursor + ); + done(); + }); + }); + + it('emits row events', function (done) { + const cursor = this.pgCursor(text); + cursor.read(10); + cursor.on('row', (row, result) => result.addRow(row)); + cursor.on('end', (result) => { + assert.strictEqual(result.rows.length, 6); + done(); + }); + }); + + it('emits row events when cursor is closed manually', function (done) { + const cursor = this.pgCursor(text); + cursor.on('row', (row, result) => result.addRow(row)); + cursor.on('end', (result) => { + assert.strictEqual(result.rows.length, 3); + done(); + }); + + cursor.read(3, () => cursor.close()); + }); + + it('emits error events', function (done) { + const cursor = this.pgCursor('select asdfasdf'); + cursor.on('error', function (err) { + assert(err); + done(); + }); + }); + + it('returns rowCount on insert', function (done) { + const pgCursor = this.pgCursor; this.client .query('CREATE TEMPORARY TABLE pg_cursor_test (foo VARCHAR(1), bar VARCHAR(1))') - .then(function() { - const cursor = pgCursor('insert into pg_cursor_test values($1, $2)', ['a', 'b']) - cursor.read(1, function(err, rows, result) { - assert.ifError(err) - assert.strictEqual(rows.length, 0) - assert.strictEqual(result.rowCount, 1) - done() - }) + .then(function () { + const cursor = pgCursor('insert into pg_cursor_test values($1, $2)', ['a', 'b']); + cursor.read(1, function (err, rows, result) { + assert.ifError(err); + assert.strictEqual(rows.length, 0); + assert.strictEqual(result.rowCount, 1); + done(); + }); }) - .catch(done) - }) -}) + .catch(done); + }); +}); diff --git a/packages/pg-cursor/test/no-data-handling.js b/packages/pg-cursor/test/no-data-handling.js index 755658746..a25f83328 100644 --- a/packages/pg-cursor/test/no-data-handling.js +++ b/packages/pg-cursor/test/no-data-handling.js @@ -1,34 +1,34 @@ -const assert = require('assert') -const pg = require('pg') -const Cursor = require('../') +const assert = require('assert'); +const pg = require('pg'); +const Cursor = require('../'); -describe('queries with no data', function() { - beforeEach(function(done) { - const client = (this.client = new pg.Client()) - client.connect(done) - }) +describe('queries with no data', function () { + beforeEach(function (done) { + const client = (this.client = new pg.Client()); + client.connect(done); + }); - afterEach(function() { - this.client.end() - }) + afterEach(function () { + this.client.end(); + }); - it('handles queries that return no data', function(done) { - const cursor = new Cursor('CREATE TEMPORARY TABLE whatwhat (thing int)') - this.client.query(cursor) - cursor.read(100, function(err, rows) { - assert.ifError(err) - assert.strictEqual(rows.length, 0) - done() - }) - }) + it('handles queries that return no data', function (done) { + const cursor = new Cursor('CREATE TEMPORARY TABLE whatwhat (thing int)'); + this.client.query(cursor); + cursor.read(100, function (err, rows) { + assert.ifError(err); + assert.strictEqual(rows.length, 0); + done(); + }); + }); - it('handles empty query', function(done) { - let cursor = new Cursor('-- this is a comment') - cursor = this.client.query(cursor) - cursor.read(100, function(err, rows) { - assert.ifError(err) - assert.strictEqual(rows.length, 0) - done() - }) - }) -}) + it('handles empty query', function (done) { + let cursor = new Cursor('-- this is a comment'); + cursor = this.client.query(cursor); + cursor.read(100, function (err, rows) { + assert.ifError(err); + assert.strictEqual(rows.length, 0); + done(); + }); + }); +}); diff --git a/packages/pg-cursor/test/pool.js b/packages/pg-cursor/test/pool.js index 9af79276c..74ad19919 100644 --- a/packages/pg-cursor/test/pool.js +++ b/packages/pg-cursor/test/pool.js @@ -1,107 +1,107 @@ -'use strict' -const assert = require('assert') -const Cursor = require('../') -const pg = require('pg') +'use strict'; +const assert = require('assert'); +const Cursor = require('../'); +const pg = require('pg'); -const text = 'SELECT generate_series as num FROM generate_series(0, 50)' +const text = 'SELECT generate_series as num FROM generate_series(0, 50)'; -function poolQueryPromise (pool, readRowCount) { +function poolQueryPromise(pool, readRowCount) { return new Promise((resolve, reject) => { pool.connect((err, client, done) => { if (err) { - done(err) - return reject(err) + done(err); + return reject(err); } - const cursor = client.query(new Cursor(text)) - cursor.read(readRowCount, err => { + const cursor = client.query(new Cursor(text)); + cursor.read(readRowCount, (err) => { if (err) { - done(err) - return reject(err) + done(err); + return reject(err); } - cursor.close(err => { + cursor.close((err) => { if (err) { - done(err) - return reject(err) + done(err); + return reject(err); } - done() - resolve() - }) - }) - }) - }) + done(); + resolve(); + }); + }); + }); + }); } describe('pool', function () { beforeEach(function () { - this.pool = new pg.Pool({ max: 1 }) - }) + this.pool = new pg.Pool({ max: 1 }); + }); afterEach(function () { - this.pool.end() - }) + this.pool.end(); + }); it('closes cursor early, single pool query', function (done) { poolQueryPromise(this.pool, 25) .then(() => done()) - .catch(err => { - assert.ifError(err) - done() - }) - }) + .catch((err) => { + assert.ifError(err); + done(); + }); + }); it('closes cursor early, saturated pool', function (done) { - const promises = [] + const promises = []; for (let i = 0; i < 10; i++) { - promises.push(poolQueryPromise(this.pool, 25)) + promises.push(poolQueryPromise(this.pool, 25)); } Promise.all(promises) .then(() => done()) - .catch(err => { - assert.ifError(err) - done() - }) - }) + .catch((err) => { + assert.ifError(err); + done(); + }); + }); it('closes exhausted cursor, single pool query', function (done) { poolQueryPromise(this.pool, 100) .then(() => done()) - .catch(err => { - assert.ifError(err) - done() - }) - }) + .catch((err) => { + assert.ifError(err); + done(); + }); + }); it('closes exhausted cursor, saturated pool', function (done) { - const promises = [] + const promises = []; for (let i = 0; i < 10; i++) { - promises.push(poolQueryPromise(this.pool, 100)) + promises.push(poolQueryPromise(this.pool, 100)); } Promise.all(promises) .then(() => done()) - .catch(err => { - assert.ifError(err) - done() - }) - }) + .catch((err) => { + assert.ifError(err); + done(); + }); + }); it('can close multiple times on a pool', async function () { - const pool = new pg.Pool({ max: 1 }) + const pool = new pg.Pool({ max: 1 }); const run = async () => { - const cursor = new Cursor(text) - const client = await pool.connect() - client.query(cursor) - await new Promise(resolve => { + const cursor = new Cursor(text); + const client = await pool.connect(); + client.query(cursor); + await new Promise((resolve) => { cursor.read(25, function (err) { - assert.ifError(err) + assert.ifError(err); cursor.close(function (err) { - assert.ifError(err) - client.release() - resolve() - }) - }) - }) - } - await Promise.all([run(), run(), run()]) - await pool.end() - }) -}) + assert.ifError(err); + client.release(); + resolve(); + }); + }); + }); + }; + await Promise.all([run(), run(), run()]); + await pool.end(); + }); +}); diff --git a/packages/pg-cursor/test/query-config.js b/packages/pg-cursor/test/query-config.js index 42692b90b..b97cbbc26 100644 --- a/packages/pg-cursor/test/query-config.js +++ b/packages/pg-cursor/test/query-config.js @@ -1,35 +1,35 @@ -'use strict' -const assert = require('assert') -const Cursor = require('../') -const pg = require('pg') +'use strict'; +const assert = require('assert'); +const Cursor = require('../'); +const pg = require('pg'); describe('query config passed to result', () => { - it('passes rowMode to result', done => { - const client = new pg.Client() - client.connect() - const text = 'SELECT generate_series as num FROM generate_series(0, 5)' - const cursor = client.query(new Cursor(text, null, { rowMode: 'array' })) + it('passes rowMode to result', (done) => { + const client = new pg.Client(); + client.connect(); + const text = 'SELECT generate_series as num FROM generate_series(0, 5)'; + const cursor = client.query(new Cursor(text, null, { rowMode: 'array' })); cursor.read(10, (err, rows) => { - assert(!err) - assert.deepStrictEqual(rows, [[0], [1], [2], [3], [4], [5]]) - client.end() - done() - }) - }) + assert(!err); + assert.deepStrictEqual(rows, [[0], [1], [2], [3], [4], [5]]); + client.end(); + done(); + }); + }); - it('passes types to result', done => { - const client = new pg.Client() - client.connect() - const text = 'SELECT generate_series as num FROM generate_series(0, 2)' + it('passes types to result', (done) => { + const client = new pg.Client(); + client.connect(); + const text = 'SELECT generate_series as num FROM generate_series(0, 2)'; const types = { - getTypeParser: () => () => 'foo' - } - const cursor = client.query(new Cursor(text, null, { types })) + getTypeParser: () => () => 'foo', + }; + const cursor = client.query(new Cursor(text, null, { types })); cursor.read(10, (err, rows) => { - assert(!err) - assert.deepStrictEqual(rows, [{ num: 'foo' }, { num: 'foo' }, { num: 'foo' }]) - client.end() - done() - }) - }) -}) + assert(!err); + assert.deepStrictEqual(rows, [{ num: 'foo' }, { num: 'foo' }, { num: 'foo' }]); + client.end(); + done(); + }); + }); +}); diff --git a/packages/pg-cursor/test/transactions.js b/packages/pg-cursor/test/transactions.js index a0ee5e6f9..08a605d9b 100644 --- a/packages/pg-cursor/test/transactions.js +++ b/packages/pg-cursor/test/transactions.js @@ -1,43 +1,43 @@ -const assert = require('assert') -const Cursor = require('../') -const pg = require('pg') +const assert = require('assert'); +const Cursor = require('../'); +const pg = require('pg'); describe('transactions', () => { it('can execute multiple statements in a transaction', async () => { - const client = new pg.Client() - await client.connect() - await client.query('begin') - await client.query('CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)') - const cursor = client.query(new Cursor('SELECT * FROM foobar')) + const client = new pg.Client(); + await client.connect(); + await client.query('begin'); + await client.query('CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)'); + const cursor = client.query(new Cursor('SELECT * FROM foobar')); const rows = await new Promise((resolve, reject) => { - cursor.read(10, (err, rows) => (err ? reject(err) : resolve(rows))) - }) - assert.strictEqual(rows.length, 0) - await client.query('ALTER TABLE foobar ADD COLUMN name TEXT') - await client.end() - }) + cursor.read(10, (err, rows) => (err ? reject(err) : resolve(rows))); + }); + assert.strictEqual(rows.length, 0); + await client.query('ALTER TABLE foobar ADD COLUMN name TEXT'); + await client.end(); + }); it('can execute multiple statements in a transaction if ending cursor early', async () => { - const client = new pg.Client() - await client.connect() - await client.query('begin') - await client.query('CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)') - const cursor = client.query(new Cursor('SELECT * FROM foobar')) - await new Promise(resolve => cursor.close(resolve)) - await client.query('ALTER TABLE foobar ADD COLUMN name TEXT') - await client.end() - }) + const client = new pg.Client(); + await client.connect(); + await client.query('begin'); + await client.query('CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)'); + const cursor = client.query(new Cursor('SELECT * FROM foobar')); + await new Promise((resolve) => cursor.close(resolve)); + await client.query('ALTER TABLE foobar ADD COLUMN name TEXT'); + await client.end(); + }); it('can execute multiple statements in a transaction if no data', async () => { - const client = new pg.Client() - await client.connect() - await client.query('begin') + const client = new pg.Client(); + await client.connect(); + await client.query('begin'); // create a cursor that has no data response - const createText = 'CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)' - const cursor = client.query(new Cursor(createText)) - const err = await new Promise(resolve => cursor.read(100, resolve)) - assert.ifError(err) - await client.query('ALTER TABLE foobar ADD COLUMN name TEXT') - await client.end() - }) -}) + const createText = 'CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)'; + const cursor = client.query(new Cursor(createText)); + const err = await new Promise((resolve) => cursor.read(100, resolve)); + assert.ifError(err); + await client.query('ALTER TABLE foobar ADD COLUMN name TEXT'); + await client.end(); + }); +}); From cb928ded2aaae3083ddc426f5edaa6bbbb53cdee Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 10 Apr 2020 10:34:34 -0500 Subject: [PATCH 0618/1037] Prettier pg-query-stream --- .eslintrc | 3 +- packages/pg-query-stream/index.js | 38 ++--- .../pg-query-stream/test/async-iterator.js | 2 +- packages/pg-query-stream/test/close.js | 161 +++++++++--------- packages/pg-query-stream/test/concat.js | 42 +++-- packages/pg-query-stream/test/config.js | 28 +-- packages/pg-query-stream/test/empty-query.js | 34 ++-- packages/pg-query-stream/test/error.js | 34 ++-- packages/pg-query-stream/test/fast-reader.js | 40 ++--- packages/pg-query-stream/test/helper.js | 20 +-- packages/pg-query-stream/test/instant.js | 24 +-- packages/pg-query-stream/test/issue-3.js | 50 +++--- .../pg-query-stream/test/passing-options.js | 62 +++---- packages/pg-query-stream/test/pauses.js | 33 ++-- packages/pg-query-stream/test/slow-reader.js | 39 +++-- .../test/stream-tester-timestamp.js | 37 ++-- .../pg-query-stream/test/stream-tester.js | 19 +-- 17 files changed, 343 insertions(+), 323 deletions(-) diff --git a/.eslintrc b/.eslintrc index 511bbc79a..968b93e52 100644 --- a/.eslintrc +++ b/.eslintrc @@ -10,8 +10,7 @@ "node_modules", "packages/pg", "packages/pg-protocol", - "packages/pg-pool", - "packages/pg-query-stream" + "packages/pg-pool" ], "parserOptions": { "ecmaVersion": 2017, diff --git a/packages/pg-query-stream/index.js b/packages/pg-query-stream/index.js index 20c56b387..01903cc3c 100644 --- a/packages/pg-query-stream/index.js +++ b/packages/pg-query-stream/index.js @@ -1,31 +1,31 @@ -const { Readable } = require('stream') -const Cursor = require('pg-cursor') +const { Readable } = require('stream'); +const Cursor = require('pg-cursor'); class PgQueryStream extends Readable { constructor(text, values, config = {}) { const { batchSize, highWaterMark = 100 } = config; // https://nodejs.org/api/stream.html#stream_new_stream_readable_options - super({ objectMode: true, emitClose: true, autoDestroy: true, highWaterMark: batchSize || highWaterMark }) - this.cursor = new Cursor(text, values, config) + super({ objectMode: true, emitClose: true, autoDestroy: true, highWaterMark: batchSize || highWaterMark }); + this.cursor = new Cursor(text, values, config); // delegate Submittable callbacks to cursor - this.handleRowDescription = this.cursor.handleRowDescription.bind(this.cursor) - this.handleDataRow = this.cursor.handleDataRow.bind(this.cursor) - this.handlePortalSuspended = this.cursor.handlePortalSuspended.bind(this.cursor) - this.handleCommandComplete = this.cursor.handleCommandComplete.bind(this.cursor) - this.handleReadyForQuery = this.cursor.handleReadyForQuery.bind(this.cursor) - this.handleError = this.cursor.handleError.bind(this.cursor) - this.handleEmptyQuery = this.cursor.handleEmptyQuery.bind(this.cursor) + this.handleRowDescription = this.cursor.handleRowDescription.bind(this.cursor); + this.handleDataRow = this.cursor.handleDataRow.bind(this.cursor); + this.handlePortalSuspended = this.cursor.handlePortalSuspended.bind(this.cursor); + this.handleCommandComplete = this.cursor.handleCommandComplete.bind(this.cursor); + this.handleReadyForQuery = this.cursor.handleReadyForQuery.bind(this.cursor); + this.handleError = this.cursor.handleError.bind(this.cursor); + this.handleEmptyQuery = this.cursor.handleEmptyQuery.bind(this.cursor); } submit(connection) { - this.cursor.submit(connection) + this.cursor.submit(connection); } _destroy(_err, cb) { this.cursor.close((err) => { - cb(err || _err) - }) + cb(err || _err); + }); } // https://nodejs.org/api/stream.html#stream_readable_read_size_1 @@ -33,13 +33,13 @@ class PgQueryStream extends Readable { this.cursor.read(size, (err, rows, result) => { if (err) { // https://nodejs.org/api/stream.html#stream_errors_while_reading - this.destroy(err) + this.destroy(err); } else { - for (const row of rows) this.push(row) - if (rows.length < size) this.push(null) + for (const row of rows) this.push(row); + if (rows.length < size) this.push(null); } - }) + }); } } -module.exports = PgQueryStream +module.exports = PgQueryStream; diff --git a/packages/pg-query-stream/test/async-iterator.js b/packages/pg-query-stream/test/async-iterator.js index 19718fe3b..63acb99b3 100644 --- a/packages/pg-query-stream/test/async-iterator.js +++ b/packages/pg-query-stream/test/async-iterator.js @@ -1,4 +1,4 @@ // only newer versions of node support async iterator if (!process.version.startsWith('v8')) { - require('./async-iterator.es6') + require('./async-iterator.es6'); } diff --git a/packages/pg-query-stream/test/close.js b/packages/pg-query-stream/test/close.js index d7e44b675..d1d38f747 100644 --- a/packages/pg-query-stream/test/close.js +++ b/packages/pg-query-stream/test/close.js @@ -1,88 +1,91 @@ -var assert = require('assert') -var concat = require('concat-stream') +var assert = require('assert'); +var concat = require('concat-stream'); -var QueryStream = require('../') -var helper = require('./helper') +var QueryStream = require('../'); +var helper = require('./helper'); if (process.version.startsWith('v8.')) { - return console.error('warning! node versions less than 10lts no longer supported & stream closing semantics may not behave properly'); -} + console.error('warning! node less than 10lts stream closing semantics may not behave properly'); +} else { + helper('close', function (client) { + it('emits close', function (done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], { batchSize: 2, highWaterMark: 2 }); + var query = client.query(stream); + query.pipe(concat(function () {})); + query.on('close', done); + }); + }); -helper('close', function (client) { - it('emits close', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], { batchSize: 2, highWaterMark: 2 }) - var query = client.query(stream) - query.pipe(concat(function () { })) - query.on('close', done) - }) -}) + helper('early close', function (client) { + it('can be closed early', function (done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [20000], { + batchSize: 2, + highWaterMark: 2, + }); + var query = client.query(stream); + var readCount = 0; + query.on('readable', function () { + readCount++; + query.read(); + }); + query.once('readable', function () { + query.destroy(); + }); + query.on('close', function () { + assert(readCount < 10, 'should not have read more than 10 rows'); + done(); + }); + }); -helper('early close', function (client) { - it('can be closed early', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [20000], { batchSize: 2, highWaterMark: 2 }) - var query = client.query(stream) - var readCount = 0 - query.on('readable', function () { - readCount++ - query.read() - }) - query.once('readable', function () { - query.destroy() - }) - query.on('close', function () { - assert(readCount < 10, 'should not have read more than 10 rows') - done() - }) - }) + it('can destroy stream while reading', function (done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)'); + client.query(stream); + stream.on('data', () => done(new Error('stream should not have returned rows'))); + setTimeout(() => { + stream.destroy(); + stream.on('close', done); + }, 100); + }); - it('can destroy stream while reading', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') - client.query(stream) - stream.on('data', () => done(new Error('stream should not have returned rows'))) - setTimeout(() => { - stream.destroy() - stream.on('close', done) - }, 100) - }) + it('emits an error when calling destroy with an error', function (done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)'); + client.query(stream); + stream.on('data', () => done(new Error('stream should not have returned rows'))); + setTimeout(() => { + stream.destroy(new Error('intentional error')); + stream.on('error', (err) => { + // make sure there's an error + assert(err); + assert.strictEqual(err.message, 'intentional error'); + done(); + }); + }, 100); + }); - it('emits an error when calling destroy with an error', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') - client.query(stream) - stream.on('data', () => done(new Error('stream should not have returned rows'))) - setTimeout(() => { - stream.destroy(new Error('intentional error')) - stream.on('error', (err) => { - // make sure there's an error - assert(err); - assert.strictEqual(err.message, 'intentional error'); - done(); - }) - }, 100) - }) + it('can destroy stream while reading an error', function (done) { + var stream = new QueryStream('SELECT * from pg_sleep(1), basdfasdf;'); + client.query(stream); + stream.on('data', () => done(new Error('stream should not have returned rows'))); + stream.once('error', () => { + stream.destroy(); + // wait a bit to let any other errors shake through + setTimeout(done, 100); + }); + }); - it('can destroy stream while reading an error', function (done) { - var stream = new QueryStream('SELECT * from pg_sleep(1), basdfasdf;') - client.query(stream) - stream.on('data', () => done(new Error('stream should not have returned rows'))) - stream.once('error', () => { - stream.destroy() - // wait a bit to let any other errors shake through - setTimeout(done, 100) - }) - }) + it('does not crash when destroying the stream immediately after calling read', function (done) { + var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);'); + client.query(stream); + stream.on('data', () => done(new Error('stream should not have returned rows'))); + stream.destroy(); + stream.on('close', done); + }); - it('does not crash when destroying the stream immediately after calling read', function (done) { - var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') - client.query(stream) - stream.on('data', () => done(new Error('stream should not have returned rows'))) - stream.destroy() - stream.on('close', done) - }) - - it('does not crash when destroying the stream before its submitted', function (done) { - var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') - stream.on('data', () => done(new Error('stream should not have returned rows'))) - stream.destroy() - stream.on('close', done) - }) -}) + it('does not crash when destroying the stream before its submitted', function (done) { + var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);'); + stream.on('data', () => done(new Error('stream should not have returned rows'))); + stream.destroy(); + stream.on('close', done); + }); + }); +} diff --git a/packages/pg-query-stream/test/concat.js b/packages/pg-query-stream/test/concat.js index 78a633be2..bf479d328 100644 --- a/packages/pg-query-stream/test/concat.js +++ b/packages/pg-query-stream/test/concat.js @@ -1,22 +1,28 @@ -var assert = require('assert') -var concat = require('concat-stream') -var through = require('through') -var helper = require('./helper') +var assert = require('assert'); +var concat = require('concat-stream'); +var through = require('through'); +var helper = require('./helper'); -var QueryStream = require('../') +var QueryStream = require('../'); helper('concat', function (client) { it('concats correctly', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) - var query = client.query(stream) - query.pipe(through(function (row) { - this.push(row.num) - })).pipe(concat(function (result) { - var total = result.reduce(function (prev, cur) { - return prev + cur - }) - assert.equal(total, 20100) - })) - stream.on('end', done) - }) -}) + var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []); + var query = client.query(stream); + query + .pipe( + through(function (row) { + this.push(row.num); + }) + ) + .pipe( + concat(function (result) { + var total = result.reduce(function (prev, cur) { + return prev + cur; + }); + assert.equal(total, 20100); + }) + ); + stream.on('end', done); + }); +}); diff --git a/packages/pg-query-stream/test/config.js b/packages/pg-query-stream/test/config.js index 1634f6174..859f7064b 100644 --- a/packages/pg-query-stream/test/config.js +++ b/packages/pg-query-stream/test/config.js @@ -1,26 +1,26 @@ -var assert = require('assert') -var QueryStream = require('../') +var assert = require('assert'); +var QueryStream = require('../'); describe('stream config options', () => { // this is mostly for backwards compatability. it('sets readable.highWaterMark based on batch size', () => { var stream = new QueryStream('SELECT NOW()', [], { - batchSize: 88 - }) - assert.equal(stream._readableState.highWaterMark, 88) - }) + batchSize: 88, + }); + assert.equal(stream._readableState.highWaterMark, 88); + }); it('sets readable.highWaterMark based on highWaterMark config', () => { var stream = new QueryStream('SELECT NOW()', [], { - highWaterMark: 88 - }) + highWaterMark: 88, + }); - assert.equal(stream._readableState.highWaterMark, 88) - }) + assert.equal(stream._readableState.highWaterMark, 88); + }); it('defaults to 100 for highWaterMark', () => { - var stream = new QueryStream('SELECT NOW()', []) + var stream = new QueryStream('SELECT NOW()', []); - assert.equal(stream._readableState.highWaterMark, 100) - }) -}) + assert.equal(stream._readableState.highWaterMark, 100); + }); +}); diff --git a/packages/pg-query-stream/test/empty-query.js b/packages/pg-query-stream/test/empty-query.js index 756031747..8e45f6823 100644 --- a/packages/pg-query-stream/test/empty-query.js +++ b/packages/pg-query-stream/test/empty-query.js @@ -1,20 +1,22 @@ -const assert = require('assert') -const helper = require('./helper') -const QueryStream = require('../') +const assert = require('assert'); +const helper = require('./helper'); +const QueryStream = require('../'); helper('empty-query', function (client) { - it('handles empty query', function(done) { - const stream = new QueryStream('-- this is a comment', []) - const query = client.query(stream) - query.on('end', function () { - // nothing should happen for empty query - done(); - }).on('data', function () { - // noop to kick off reading - }) - }) + it('handles empty query', function (done) { + const stream = new QueryStream('-- this is a comment', []); + const query = client.query(stream); + query + .on('end', function () { + // nothing should happen for empty query + done(); + }) + .on('data', function () { + // noop to kick off reading + }); + }); it('continues to function after stream', function (done) { - client.query('SELECT NOW()', done) - }) -}) \ No newline at end of file + client.query('SELECT NOW()', done); + }); +}); diff --git a/packages/pg-query-stream/test/error.js b/packages/pg-query-stream/test/error.js index 1e6030d5d..848915dc2 100644 --- a/packages/pg-query-stream/test/error.js +++ b/packages/pg-query-stream/test/error.js @@ -1,22 +1,24 @@ -var assert = require('assert') -var helper = require('./helper') +var assert = require('assert'); +var helper = require('./helper'); -var QueryStream = require('../') +var QueryStream = require('../'); helper('error', function (client) { it('receives error on stream', function (done) { - var stream = new QueryStream('SELECT * FROM asdf num', []) - var query = client.query(stream) - query.on('error', function (err) { - assert(err) - assert.equal(err.code, '42P01') - done() - }).on('data', function () { - // noop to kick of reading - }) - }) + var stream = new QueryStream('SELECT * FROM asdf num', []); + var query = client.query(stream); + query + .on('error', function (err) { + assert(err); + assert.equal(err.code, '42P01'); + done(); + }) + .on('data', function () { + // noop to kick of reading + }); + }); it('continues to function after stream', function (done) { - client.query('SELECT NOW()', done) - }) -}) + client.query('SELECT NOW()', done); + }); +}); diff --git a/packages/pg-query-stream/test/fast-reader.js b/packages/pg-query-stream/test/fast-reader.js index 4c6f31f95..54e47c3b2 100644 --- a/packages/pg-query-stream/test/fast-reader.js +++ b/packages/pg-query-stream/test/fast-reader.js @@ -1,35 +1,35 @@ -var assert = require('assert') -var helper = require('./helper') -var QueryStream = require('../') +var assert = require('assert'); +var helper = require('./helper'); +var QueryStream = require('../'); helper('fast reader', function (client) { it('works', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) - var query = client.query(stream) - var result = [] + var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []); + var query = client.query(stream); + var result = []; stream.on('readable', function () { - var res = stream.read() + var res = stream.read(); while (res) { if (result.length !== 201) { - assert(res, 'should not return null on evented reader') + assert(res, 'should not return null on evented reader'); } else { // a readable stream will emit a null datum when it finishes being readable // https://nodejs.org/api/stream.html#stream_event_readable - assert.equal(res, null) + assert.equal(res, null); } if (res) { - result.push(res.num) + result.push(res.num); } - res = stream.read() + res = stream.read(); } - }) + }); stream.on('end', function () { var total = result.reduce(function (prev, cur) { - return prev + cur - }) - assert.equal(total, 20100) - done() - }) - assert.strictEqual(query.read(2), null) - }) -}) + return prev + cur; + }); + assert.equal(total, 20100); + done(); + }); + assert.strictEqual(query.read(2), null); + }); +}); diff --git a/packages/pg-query-stream/test/helper.js b/packages/pg-query-stream/test/helper.js index ad21d6ea2..87bf32377 100644 --- a/packages/pg-query-stream/test/helper.js +++ b/packages/pg-query-stream/test/helper.js @@ -1,17 +1,17 @@ -var pg = require('pg') +var pg = require('pg'); module.exports = function (name, cb) { describe(name, function () { - var client = new pg.Client() + var client = new pg.Client(); before(function (done) { - client.connect(done) - }) + client.connect(done); + }); - cb(client) + cb(client); after(function (done) { - client.end() - client.on('end', done) - }) - }) -} + client.end(); + client.on('end', done); + }); + }); +}; diff --git a/packages/pg-query-stream/test/instant.js b/packages/pg-query-stream/test/instant.js index 49ab0b07d..984e90038 100644 --- a/packages/pg-query-stream/test/instant.js +++ b/packages/pg-query-stream/test/instant.js @@ -1,15 +1,17 @@ -var assert = require('assert') -var concat = require('concat-stream') +var assert = require('assert'); +var concat = require('concat-stream'); -var QueryStream = require('../') +var QueryStream = require('../'); require('./helper')('instant', function (client) { it('instant', function (done) { - var query = new QueryStream('SELECT pg_sleep(1)', []) - var stream = client.query(query) - stream.pipe(concat(function (res) { - assert.equal(res.length, 1) - done() - })) - }) -}) + var query = new QueryStream('SELECT pg_sleep(1)', []); + var stream = client.query(query); + stream.pipe( + concat(function (res) { + assert.equal(res.length, 1); + done(); + }) + ); + }); +}); diff --git a/packages/pg-query-stream/test/issue-3.js b/packages/pg-query-stream/test/issue-3.js index 7b467a3b3..608f9f715 100644 --- a/packages/pg-query-stream/test/issue-3.js +++ b/packages/pg-query-stream/test/issue-3.js @@ -1,32 +1,32 @@ -var pg = require('pg') -var QueryStream = require('../') +var pg = require('pg'); +var QueryStream = require('../'); describe('end semantics race condition', function () { before(function (done) { - var client = new pg.Client() - client.connect() - client.on('drain', client.end.bind(client)) - client.on('end', done) - client.query('create table IF NOT EXISTS p(id serial primary key)') - client.query('create table IF NOT EXISTS c(id int primary key references p)') - }) + var client = new pg.Client(); + client.connect(); + client.on('drain', client.end.bind(client)); + client.on('end', done); + client.query('create table IF NOT EXISTS p(id serial primary key)'); + client.query('create table IF NOT EXISTS c(id int primary key references p)'); + }); it('works', function (done) { - var client1 = new pg.Client() - client1.connect() - var client2 = new pg.Client() - client2.connect() + var client1 = new pg.Client(); + client1.connect(); + var client2 = new pg.Client(); + client2.connect(); - var qr = new QueryStream('INSERT INTO p DEFAULT VALUES RETURNING id') - client1.query(qr) - var id = null + var qr = new QueryStream('INSERT INTO p DEFAULT VALUES RETURNING id'); + client1.query(qr); + var id = null; qr.on('data', function (row) { - id = row.id - }) + id = row.id; + }); qr.on('end', function () { client2.query('INSERT INTO c(id) VALUES ($1)', [id], function (err, rows) { - client1.end() - client2.end() - done(err) - }) - }) - }) -}) + client1.end(); + client2.end(); + done(err); + }); + }); + }); +}); diff --git a/packages/pg-query-stream/test/passing-options.js b/packages/pg-query-stream/test/passing-options.js index e2ddd1857..bed59272b 100644 --- a/packages/pg-query-stream/test/passing-options.js +++ b/packages/pg-query-stream/test/passing-options.js @@ -1,38 +1,38 @@ -var assert = require('assert') -var helper = require('./helper') -var QueryStream = require('../') +var assert = require('assert'); +var helper = require('./helper'); +var QueryStream = require('../'); -helper('passing options', function(client) { - it('passes row mode array', function(done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { rowMode: 'array' }) - var query = client.query(stream) - var result = [] - query.on('data', datum => { - result.push(datum) - }) +helper('passing options', function (client) { + it('passes row mode array', function (done) { + var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { rowMode: 'array' }); + var query = client.query(stream); + var result = []; + query.on('data', (datum) => { + result.push(datum); + }); query.on('end', () => { - const expected = new Array(11).fill(0).map((_, i) => [i]) - assert.deepEqual(result, expected) - done() - }) - }) + const expected = new Array(11).fill(0).map((_, i) => [i]); + assert.deepEqual(result, expected); + done(); + }); + }); - it('passes custom types', function(done) { + it('passes custom types', function (done) { const types = { - getTypeParser: () => string => string, - } - var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { types }) - var query = client.query(stream) - var result = [] - query.on('data', datum => { - result.push(datum) - }) + getTypeParser: () => (string) => string, + }; + var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { types }); + var query = client.query(stream); + var result = []; + query.on('data', (datum) => { + result.push(datum); + }); query.on('end', () => { const expected = new Array(11).fill(0).map((_, i) => ({ num: i.toString(), - })) - assert.deepEqual(result, expected) - done() - }) - }) -}) + })); + assert.deepEqual(result, expected); + done(); + }); + }); +}); diff --git a/packages/pg-query-stream/test/pauses.js b/packages/pg-query-stream/test/pauses.js index 8d9beb02c..83f290a60 100644 --- a/packages/pg-query-stream/test/pauses.js +++ b/packages/pg-query-stream/test/pauses.js @@ -1,18 +1,23 @@ -var concat = require('concat-stream') -var tester = require('stream-tester') -var JSONStream = require('JSONStream') +var concat = require('concat-stream'); +var tester = require('stream-tester'); +var JSONStream = require('JSONStream'); -var QueryStream = require('../') +var QueryStream = require('../'); require('./helper')('pauses', function (client) { it('pauses', function (done) { - this.timeout(5000) - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], {batchSize: 2, highWaterMark: 2}) - var query = client.query(stream) - var pauser = tester.createPauseStream(0.1, 100) - query.pipe(JSONStream.stringify()).pipe(pauser).pipe(concat(function (json) { - JSON.parse(json) - done() - })) - }) -}) + this.timeout(5000); + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], { batchSize: 2, highWaterMark: 2 }); + var query = client.query(stream); + var pauser = tester.createPauseStream(0.1, 100); + query + .pipe(JSONStream.stringify()) + .pipe(pauser) + .pipe( + concat(function (json) { + JSON.parse(json); + done(); + }) + ); + }); +}); diff --git a/packages/pg-query-stream/test/slow-reader.js b/packages/pg-query-stream/test/slow-reader.js index 4c0070a35..b5524b8f1 100644 --- a/packages/pg-query-stream/test/slow-reader.js +++ b/packages/pg-query-stream/test/slow-reader.js @@ -1,26 +1,31 @@ -var helper = require('./helper') -var QueryStream = require('../') -var concat = require('concat-stream') +var helper = require('./helper'); +var QueryStream = require('../'); +var concat = require('concat-stream'); -var Transform = require('stream').Transform +var Transform = require('stream').Transform; -var mapper = new Transform({ objectMode: true }) +var mapper = new Transform({ objectMode: true }); mapper._transform = function (obj, enc, cb) { - this.push(obj) - setTimeout(cb, 5) -} + this.push(obj); + setTimeout(cb, 5); +}; helper('slow reader', function (client) { it('works', function (done) { - this.timeout(50000) - var stream = new QueryStream('SELECT * FROM generate_series(0, 201) num', [], { highWaterMark: 100, batchSize: 50 }) + this.timeout(50000); + var stream = new QueryStream('SELECT * FROM generate_series(0, 201) num', [], { + highWaterMark: 100, + batchSize: 50, + }); stream.on('end', function () { // console.log('stream end') - }) - client.query(stream) - stream.pipe(mapper).pipe(concat(function (res) { - done() - })) - }) -}) + }); + client.query(stream); + stream.pipe(mapper).pipe( + concat(function (res) { + done(); + }) + ); + }); +}); diff --git a/packages/pg-query-stream/test/stream-tester-timestamp.js b/packages/pg-query-stream/test/stream-tester-timestamp.js index 7a31b4ecc..ef2182c1d 100644 --- a/packages/pg-query-stream/test/stream-tester-timestamp.js +++ b/packages/pg-query-stream/test/stream-tester-timestamp.js @@ -1,26 +1,25 @@ -var QueryStream = require('../') -var spec = require('stream-spec') -var assert = require('assert') +var QueryStream = require('../'); +var spec = require('stream-spec'); +var assert = require('assert'); require('./helper')('stream tester timestamp', function (client) { it('should not warn about max listeners', function (done) { - var sql = 'SELECT * FROM generate_series(\'1983-12-30 00:00\'::timestamp, \'2013-12-30 00:00\', \'1 years\')' - var stream = new QueryStream(sql, []) - var ended = false - var query = client.query(stream) - query.on('end', function () { ended = true }) - spec(query) - .readable() - .pausable({ strict: true }) - .validateOnExit() + var sql = "SELECT * FROM generate_series('1983-12-30 00:00'::timestamp, '2013-12-30 00:00', '1 years')"; + var stream = new QueryStream(sql, []); + var ended = false; + var query = client.query(stream); + query.on('end', function () { + ended = true; + }); + spec(query).readable().pausable({ strict: true }).validateOnExit(); var checkListeners = function () { - assert(stream.listeners('end').length < 10) + assert(stream.listeners('end').length < 10); if (!ended) { - setImmediate(checkListeners) + setImmediate(checkListeners); } else { - done() + done(); } - } - checkListeners() - }) -}) + }; + checkListeners(); + }); +}); diff --git a/packages/pg-query-stream/test/stream-tester.js b/packages/pg-query-stream/test/stream-tester.js index 826565813..0769d7189 100644 --- a/packages/pg-query-stream/test/stream-tester.js +++ b/packages/pg-query-stream/test/stream-tester.js @@ -1,15 +1,12 @@ -var spec = require('stream-spec') +var spec = require('stream-spec'); -var QueryStream = require('../') +var QueryStream = require('../'); require('./helper')('stream tester', function (client) { it('passes stream spec', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) - var query = client.query(stream) - spec(query) - .readable() - .pausable({strict: true}) - .validateOnExit() - stream.on('end', done) - }) -}) + var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []); + var query = client.query(stream); + spec(query).readable().pausable({ strict: true }).validateOnExit(); + stream.on('end', done); + }); +}); From 6adbcabf50d63ce13cebd5579123bcbe90927703 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 10 Apr 2020 10:43:54 -0500 Subject: [PATCH 0619/1037] lint pg-protcol --- .eslintrc | 7 +- package.json | 3 +- packages/pg-protocol/src/b.ts | 36 +- packages/pg-protocol/src/buffer-reader.ts | 7 +- packages/pg-protocol/src/buffer-writer.ts | 26 +- .../pg-protocol/src/inbound-parser.test.ts | 565 +++++++++--------- packages/pg-protocol/src/index.ts | 8 +- packages/pg-protocol/src/messages.ts | 74 ++- .../src/outbound-serializer.test.ts | 277 ++++----- packages/pg-protocol/src/parser.ts | 170 +++--- packages/pg-protocol/src/serializer.ts | 232 ++++--- .../pg-protocol/src/testing/buffer-list.ts | 74 ++- .../pg-protocol/src/testing/test-buffers.ts | 123 ++-- packages/pg-protocol/src/types/chunky.d.ts | 2 +- packages/pg/Makefile | 8 +- yarn.lock | 15 + 16 files changed, 818 insertions(+), 809 deletions(-) diff --git a/.eslintrc b/.eslintrc index 968b93e52..2840a3646 100644 --- a/.eslintrc +++ b/.eslintrc @@ -2,14 +2,15 @@ "plugins": [ "prettier" ], + "parser": "@typescript-eslint/parser", "extends": [ - "plugin:prettier/recommended" + "plugin:prettier/recommended", + "prettier/@typescript-eslint" ], "ignorePatterns": [ - "**/*.ts", "node_modules", "packages/pg", - "packages/pg-protocol", + "packages/pg-protocol/dist/**/*", "packages/pg-pool" ], "parserOptions": { diff --git a/package.json b/package.json index 0e2841fd3..83867563a 100644 --- a/package.json +++ b/package.json @@ -13,10 +13,11 @@ "test": "yarn lerna exec yarn test", "build": "yarn lerna exec --scope pg-protocol yarn build", "pretest": "yarn build", - "lint": "yarn lerna exec --parallel yarn lint" + "lint": "eslint '*/**/*.{js,ts,tsx}'" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^2.27.0", + "@typescript-eslint/parser": "^2.27.0", "eslint": "^6.8.0", "eslint-config-prettier": "^6.10.1", "eslint-plugin-node": "^11.1.0", diff --git a/packages/pg-protocol/src/b.ts b/packages/pg-protocol/src/b.ts index dbf9f52ef..27a24c6a5 100644 --- a/packages/pg-protocol/src/b.ts +++ b/packages/pg-protocol/src/b.ts @@ -1,28 +1,28 @@ -// file for microbenchmarking +// file for microbenchmarking -import { Writer } from './buffer-writer' -import { serialize } from './index' -import { BufferReader } from './buffer-reader' +import { Writer } from './buffer-writer'; +import { serialize } from './index'; +import { BufferReader } from './buffer-reader'; -const LOOPS = 1000 -let count = 0 -let start = Date.now() -const writer = new Writer() +const LOOPS = 1000; +let count = 0; +let start = Date.now(); +const writer = new Writer(); -const reader = new BufferReader() -const buffer = Buffer.from([33, 33, 33, 33, 33, 33, 33, 0]) +const reader = new BufferReader(); +const buffer = Buffer.from([33, 33, 33, 33, 33, 33, 33, 0]); const run = () => { if (count > LOOPS) { - console.log(Date.now() - start) + console.log(Date.now() - start); return; } - count++ - for(let i = 0; i < LOOPS; i++) { - reader.setBuffer(0, buffer) - reader.cstring() + count++; + for (let i = 0; i < LOOPS; i++) { + reader.setBuffer(0, buffer); + reader.cstring(); } - setImmediate(run) -} + setImmediate(run); +}; -run() +run(); diff --git a/packages/pg-protocol/src/buffer-reader.ts b/packages/pg-protocol/src/buffer-reader.ts index cb7d4e3bd..62ea85240 100644 --- a/packages/pg-protocol/src/buffer-reader.ts +++ b/packages/pg-protocol/src/buffer-reader.ts @@ -6,8 +6,7 @@ export class BufferReader { // TODO(bmc): support non-utf8 encoding? private encoding: string = 'utf-8'; - constructor(private offset: number = 0) { - } + constructor(private offset: number = 0) {} public setBuffer(offset: number, buffer: Buffer): void { this.offset = offset; @@ -40,8 +39,8 @@ export class BufferReader { public cstring(): string { const start = this.offset; - let end = start - while(this.buffer[end++] !== 0) { }; + let end = start; + while (this.buffer[end++] !== 0) {} this.offset = end; return this.buffer.toString(this.encoding, start, end - 1); } diff --git a/packages/pg-protocol/src/buffer-writer.ts b/packages/pg-protocol/src/buffer-writer.ts index 2299070d1..58efb3b25 100644 --- a/packages/pg-protocol/src/buffer-writer.ts +++ b/packages/pg-protocol/src/buffer-writer.ts @@ -5,7 +5,7 @@ export class Writer { private offset: number = 5; private headerPosition: number = 0; constructor(private size = 256) { - this.buffer = Buffer.alloc(size) + this.buffer = Buffer.alloc(size); } private ensure(size: number): void { @@ -22,28 +22,27 @@ export class Writer { public addInt32(num: number): Writer { this.ensure(4); - this.buffer[this.offset++] = (num >>> 24 & 0xFF); - this.buffer[this.offset++] = (num >>> 16 & 0xFF); - this.buffer[this.offset++] = (num >>> 8 & 0xFF); - this.buffer[this.offset++] = (num >>> 0 & 0xFF); + this.buffer[this.offset++] = (num >>> 24) & 0xff; + this.buffer[this.offset++] = (num >>> 16) & 0xff; + this.buffer[this.offset++] = (num >>> 8) & 0xff; + this.buffer[this.offset++] = (num >>> 0) & 0xff; return this; } public addInt16(num: number): Writer { this.ensure(2); - this.buffer[this.offset++] = (num >>> 8 & 0xFF); - this.buffer[this.offset++] = (num >>> 0 & 0xFF); + this.buffer[this.offset++] = (num >>> 8) & 0xff; + this.buffer[this.offset++] = (num >>> 0) & 0xff; return this; } - public addCString(string: string): Writer { if (!string) { this.ensure(1); } else { var len = Buffer.byteLength(string); this.ensure(len + 1); // +1 for null terminator - this.buffer.write(string, this.offset, 'utf-8') + this.buffer.write(string, this.offset, 'utf-8'); this.offset += len; } @@ -51,7 +50,7 @@ export class Writer { return this; } - public addString(string: string = ""): Writer { + public addString(string: string = ''): Writer { var len = Buffer.byteLength(string); this.ensure(len); this.buffer.write(string, this.offset); @@ -70,8 +69,8 @@ export class Writer { if (code) { this.buffer[this.headerPosition] = code; //length is everything in this packet minus the code - const length = this.offset - (this.headerPosition + 1) - this.buffer.writeInt32BE(length, this.headerPosition + 1) + const length = this.offset - (this.headerPosition + 1); + this.buffer.writeInt32BE(length, this.headerPosition + 1); } return this.buffer.slice(code ? 0 : 5, this.offset); } @@ -80,8 +79,7 @@ export class Writer { var result = this.join(code); this.offset = 5; this.headerPosition = 0; - this.buffer = Buffer.allocUnsafe(this.size) + this.buffer = Buffer.allocUnsafe(this.size); return result; } } - diff --git a/packages/pg-protocol/src/inbound-parser.test.ts b/packages/pg-protocol/src/inbound-parser.test.ts index 461ab2628..f50e95bed 100644 --- a/packages/pg-protocol/src/inbound-parser.test.ts +++ b/packages/pg-protocol/src/inbound-parser.test.ts @@ -1,28 +1,29 @@ -import buffers from './testing/test-buffers' -import BufferList from './testing/buffer-list' -import { parse } from '.' -import assert from 'assert' -import { PassThrough } from 'stream' -import { BackendMessage } from './messages' - -var authOkBuffer = buffers.authenticationOk() -var paramStatusBuffer = buffers.parameterStatus('client_encoding', 'UTF8') -var readyForQueryBuffer = buffers.readyForQuery() -var backendKeyDataBuffer = buffers.backendKeyData(1, 2) -var commandCompleteBuffer = buffers.commandComplete('SELECT 3') -var parseCompleteBuffer = buffers.parseComplete() -var bindCompleteBuffer = buffers.bindComplete() -var portalSuspendedBuffer = buffers.portalSuspended() +import buffers from './testing/test-buffers'; +import BufferList from './testing/buffer-list'; +import { parse } from '.'; +import assert from 'assert'; +import { PassThrough } from 'stream'; +import { BackendMessage } from './messages'; + +var authOkBuffer = buffers.authenticationOk(); +var paramStatusBuffer = buffers.parameterStatus('client_encoding', 'UTF8'); +var readyForQueryBuffer = buffers.readyForQuery(); +var backendKeyDataBuffer = buffers.backendKeyData(1, 2); +var commandCompleteBuffer = buffers.commandComplete('SELECT 3'); +var parseCompleteBuffer = buffers.parseComplete(); +var bindCompleteBuffer = buffers.bindComplete(); +var portalSuspendedBuffer = buffers.portalSuspended(); var addRow = function (bufferList: BufferList, name: string, offset: number) { - return bufferList.addCString(name) // field name + return bufferList + .addCString(name) // field name .addInt32(offset++) // table id .addInt16(offset++) // attribute of column number .addInt32(offset++) // objectId of field's data type .addInt16(offset++) // datatype size .addInt32(offset++) // type modifier - .addInt16(0) // format code, 0 => text -} + .addInt16(0); // format code, 0 => text +}; var row1 = { name: 'id', @@ -31,274 +32,291 @@ var row1 = { dataTypeID: 3, dataTypeSize: 4, typeModifier: 5, - formatCode: 0 -} -var oneRowDescBuff = buffers.rowDescription([row1]) -row1.name = 'bang' - -var twoRowBuf = buffers.rowDescription([row1, { - name: 'whoah', - tableID: 10, - attributeNumber: 11, - dataTypeID: 12, - dataTypeSize: 13, - typeModifier: 14, - formatCode: 0 -}]) - -var emptyRowFieldBuf = new BufferList() - .addInt16(0) - .join(true, 'D') - -var emptyRowFieldBuf = buffers.dataRow([]) + formatCode: 0, +}; +var oneRowDescBuff = buffers.rowDescription([row1]); +row1.name = 'bang'; + +var twoRowBuf = buffers.rowDescription([ + row1, + { + name: 'whoah', + tableID: 10, + attributeNumber: 11, + dataTypeID: 12, + dataTypeSize: 13, + typeModifier: 14, + formatCode: 0, + }, +]); + +var emptyRowFieldBuf = new BufferList().addInt16(0).join(true, 'D'); + +var emptyRowFieldBuf = buffers.dataRow([]); var oneFieldBuf = new BufferList() .addInt16(1) // number of fields .addInt32(5) // length of bytes of fields .addCString('test') - .join(true, 'D') + .join(true, 'D'); -var oneFieldBuf = buffers.dataRow(['test']) +var oneFieldBuf = buffers.dataRow(['test']); var expectedAuthenticationOkayMessage = { name: 'authenticationOk', - length: 8 -} + length: 8, +}; var expectedParameterStatusMessage = { name: 'parameterStatus', parameterName: 'client_encoding', parameterValue: 'UTF8', - length: 25 -} + length: 25, +}; var expectedBackendKeyDataMessage = { name: 'backendKeyData', processID: 1, - secretKey: 2 -} + secretKey: 2, +}; var expectedReadyForQueryMessage = { name: 'readyForQuery', length: 5, - status: 'I' -} + status: 'I', +}; var expectedCommandCompleteMessage = { name: 'commandComplete', length: 13, - text: 'SELECT 3' -} + text: 'SELECT 3', +}; var emptyRowDescriptionBuffer = new BufferList() .addInt16(0) // number of fields - .join(true, 'T') + .join(true, 'T'); var expectedEmptyRowDescriptionMessage = { name: 'rowDescription', length: 6, fieldCount: 0, fields: [], -} +}; var expectedOneRowMessage = { name: 'rowDescription', length: 27, fieldCount: 1, - fields: [{ - name: 'id', - tableID: 1, - columnID: 2, - dataTypeID: 3, - dataTypeSize: 4, - dataTypeModifier: 5, - format: 'text' - }] -} + fields: [ + { + name: 'id', + tableID: 1, + columnID: 2, + dataTypeID: 3, + dataTypeSize: 4, + dataTypeModifier: 5, + format: 'text', + }, + ], +}; var expectedTwoRowMessage = { name: 'rowDescription', length: 53, fieldCount: 2, - fields: [{ - name: 'bang', - tableID: 1, - columnID: 2, - dataTypeID: 3, - dataTypeSize: 4, - dataTypeModifier: 5, - format: 'text' - }, - { - name: 'whoah', - tableID: 10, - columnID: 11, - dataTypeID: 12, - dataTypeSize: 13, - dataTypeModifier: 14, - format: 'text' - }] -} + fields: [ + { + name: 'bang', + tableID: 1, + columnID: 2, + dataTypeID: 3, + dataTypeSize: 4, + dataTypeModifier: 5, + format: 'text', + }, + { + name: 'whoah', + tableID: 10, + columnID: 11, + dataTypeID: 12, + dataTypeSize: 13, + dataTypeModifier: 14, + format: 'text', + }, + ], +}; var testForMessage = function (buffer: Buffer, expectedMessage: any) { it('recieves and parses ' + expectedMessage.name, async () => { - const messages = await parseBuffers([buffer]) + const messages = await parseBuffers([buffer]); const [lastMessage] = messages; for (const key in expectedMessage) { - assert.deepEqual((lastMessage as any)[key], expectedMessage[key]) + assert.deepEqual((lastMessage as any)[key], expectedMessage[key]); } - }) -} + }); +}; -var plainPasswordBuffer = buffers.authenticationCleartextPassword() -var md5PasswordBuffer = buffers.authenticationMD5Password() -var SASLBuffer = buffers.authenticationSASL() -var SASLContinueBuffer = buffers.authenticationSASLContinue() -var SASLFinalBuffer = buffers.authenticationSASLFinal() +var plainPasswordBuffer = buffers.authenticationCleartextPassword(); +var md5PasswordBuffer = buffers.authenticationMD5Password(); +var SASLBuffer = buffers.authenticationSASL(); +var SASLContinueBuffer = buffers.authenticationSASLContinue(); +var SASLFinalBuffer = buffers.authenticationSASLFinal(); var expectedPlainPasswordMessage = { - name: 'authenticationCleartextPassword' -} + name: 'authenticationCleartextPassword', +}; var expectedMD5PasswordMessage = { name: 'authenticationMD5Password', - salt: Buffer.from([1, 2, 3, 4]) -} + salt: Buffer.from([1, 2, 3, 4]), +}; var expectedSASLMessage = { name: 'authenticationSASL', - mechanisms: ['SCRAM-SHA-256'] -} + mechanisms: ['SCRAM-SHA-256'], +}; var expectedSASLContinueMessage = { name: 'authenticationSASLContinue', data: 'data', -} +}; var expectedSASLFinalMessage = { name: 'authenticationSASLFinal', data: 'data', -} +}; -var notificationResponseBuffer = buffers.notification(4, 'hi', 'boom') +var notificationResponseBuffer = buffers.notification(4, 'hi', 'boom'); var expectedNotificationResponseMessage = { name: 'notification', processId: 4, channel: 'hi', - payload: 'boom' -} - - + payload: 'boom', +}; const parseBuffers = async (buffers: Buffer[]): Promise => { const stream = new PassThrough(); for (const buffer of buffers) { stream.write(buffer); } - stream.end() - const msgs: BackendMessage[] = [] - await parse(stream, (msg) => msgs.push(msg)) - return msgs -} + stream.end(); + const msgs: BackendMessage[] = []; + await parse(stream, (msg) => msgs.push(msg)); + return msgs; +}; describe('PgPacketStream', function () { - testForMessage(authOkBuffer, expectedAuthenticationOkayMessage) - testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage) - testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage) - testForMessage(SASLBuffer, expectedSASLMessage) - testForMessage(SASLContinueBuffer, expectedSASLContinueMessage) - testForMessage(SASLFinalBuffer, expectedSASLFinalMessage) - - testForMessage(paramStatusBuffer, expectedParameterStatusMessage) - testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage) - testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage) - testForMessage(commandCompleteBuffer, expectedCommandCompleteMessage) - testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage) + testForMessage(authOkBuffer, expectedAuthenticationOkayMessage); + testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage); + testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage); + testForMessage(SASLBuffer, expectedSASLMessage); + testForMessage(SASLContinueBuffer, expectedSASLContinueMessage); + testForMessage(SASLFinalBuffer, expectedSASLFinalMessage); + + testForMessage(paramStatusBuffer, expectedParameterStatusMessage); + testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage); + testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage); + testForMessage(commandCompleteBuffer, expectedCommandCompleteMessage); + testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage); testForMessage(buffers.emptyQuery(), { name: 'emptyQuery', length: 4, - }) + }); testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), { - name: 'noData' - }) + name: 'noData', + }); describe('rowDescription messages', function () { - testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage) - testForMessage(oneRowDescBuff, expectedOneRowMessage) - testForMessage(twoRowBuf, expectedTwoRowMessage) - }) + testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage); + testForMessage(oneRowDescBuff, expectedOneRowMessage); + testForMessage(twoRowBuf, expectedTwoRowMessage); + }); describe('parsing rows', function () { describe('parsing empty row', function () { testForMessage(emptyRowFieldBuf, { name: 'dataRow', - fieldCount: 0 - }) - }) + fieldCount: 0, + }); + }); describe('parsing data row with fields', function () { testForMessage(oneFieldBuf, { name: 'dataRow', fieldCount: 1, - fields: ['test'] - }) - }) - }) + fields: ['test'], + }); + }); + }); describe('notice message', function () { // this uses the same logic as error message - var buff = buffers.notice([{ type: 'C', value: 'code' }]) + var buff = buffers.notice([{ type: 'C', value: 'code' }]); testForMessage(buff, { name: 'notice', - code: 'code' - }) - }) + code: 'code', + }); + }); testForMessage(buffers.error([]), { - name: 'error' - }) + name: 'error', + }); describe('with all the fields', function () { - var buffer = buffers.error([{ - type: 'S', - value: 'ERROR' - }, { - type: 'C', - value: 'code' - }, { - type: 'M', - value: 'message' - }, { - type: 'D', - value: 'details' - }, { - type: 'H', - value: 'hint' - }, { - type: 'P', - value: '100' - }, { - type: 'p', - value: '101' - }, { - type: 'q', - value: 'query' - }, { - type: 'W', - value: 'where' - }, { - type: 'F', - value: 'file' - }, { - type: 'L', - value: 'line' - }, { - type: 'R', - value: 'routine' - }, { - type: 'Z', // ignored - value: 'alsdkf' - }]) + var buffer = buffers.error([ + { + type: 'S', + value: 'ERROR', + }, + { + type: 'C', + value: 'code', + }, + { + type: 'M', + value: 'message', + }, + { + type: 'D', + value: 'details', + }, + { + type: 'H', + value: 'hint', + }, + { + type: 'P', + value: '100', + }, + { + type: 'p', + value: '101', + }, + { + type: 'q', + value: 'query', + }, + { + type: 'W', + value: 'where', + }, + { + type: 'F', + value: 'file', + }, + { + type: 'L', + value: 'line', + }, + { + type: 'R', + value: 'routine', + }, + { + type: 'Z', // ignored + value: 'alsdkf', + }, + ]); testForMessage(buffer, { name: 'error', @@ -313,184 +331,179 @@ describe('PgPacketStream', function () { where: 'where', file: 'file', line: 'line', - routine: 'routine' - }) - }) + routine: 'routine', + }); + }); testForMessage(parseCompleteBuffer, { - name: 'parseComplete' - }) + name: 'parseComplete', + }); testForMessage(bindCompleteBuffer, { - name: 'bindComplete' - }) + name: 'bindComplete', + }); testForMessage(bindCompleteBuffer, { - name: 'bindComplete' - }) + name: 'bindComplete', + }); testForMessage(buffers.closeComplete(), { - name: 'closeComplete' - }) + name: 'closeComplete', + }); describe('parses portal suspended message', function () { testForMessage(portalSuspendedBuffer, { - name: 'portalSuspended' - }) - }) + name: 'portalSuspended', + }); + }); describe('parses replication start message', function () { testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { name: 'replicationStart', - length: 4 - }) - }) + length: 4, + }); + }); describe('copy', () => { testForMessage(buffers.copyIn(0), { name: 'copyInResponse', length: 7, binary: false, - columnTypes: [] - }) + columnTypes: [], + }); testForMessage(buffers.copyIn(2), { name: 'copyInResponse', length: 11, binary: false, - columnTypes: [0, 1] - }) + columnTypes: [0, 1], + }); testForMessage(buffers.copyOut(0), { name: 'copyOutResponse', length: 7, binary: false, - columnTypes: [] - }) + columnTypes: [], + }); testForMessage(buffers.copyOut(3), { name: 'copyOutResponse', length: 13, binary: false, - columnTypes: [0, 1, 2] - }) + columnTypes: [0, 1, 2], + }); testForMessage(buffers.copyDone(), { name: 'copyDone', length: 4, - }) + }); testForMessage(buffers.copyData(Buffer.from([5, 6, 7])), { name: 'copyData', length: 7, - chunk: Buffer.from([5, 6, 7]) - }) - }) - + chunk: Buffer.from([5, 6, 7]), + }); + }); // since the data message on a stream can randomly divide the incomming // tcp packets anywhere, we need to make sure we can parse every single // split on a tcp message describe('split buffer, single message parsing', function () { - var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']) + var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']); it('parses when full buffer comes in', async function () { const messages = await parseBuffers([fullBuffer]); - const message = messages[0] as any - assert.equal(message.fields.length, 5) - assert.equal(message.fields[0], null) - assert.equal(message.fields[1], 'bang') - assert.equal(message.fields[2], 'zug zug') - assert.equal(message.fields[3], null) - assert.equal(message.fields[4], '!') - }) + const message = messages[0] as any; + assert.equal(message.fields.length, 5); + assert.equal(message.fields[0], null); + assert.equal(message.fields[1], 'bang'); + assert.equal(message.fields[2], 'zug zug'); + assert.equal(message.fields[3], null); + assert.equal(message.fields[4], '!'); + }); var testMessageRecievedAfterSpiltAt = async function (split: number) { - var firstBuffer = Buffer.alloc(fullBuffer.length - split) - var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) - fullBuffer.copy(firstBuffer, 0, 0) - fullBuffer.copy(secondBuffer, 0, firstBuffer.length) + var firstBuffer = Buffer.alloc(fullBuffer.length - split); + var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length); + fullBuffer.copy(firstBuffer, 0, 0); + fullBuffer.copy(secondBuffer, 0, firstBuffer.length); const messages = await parseBuffers([fullBuffer]); - const message = messages[0] as any - assert.equal(message.fields.length, 5) - assert.equal(message.fields[0], null) - assert.equal(message.fields[1], 'bang') - assert.equal(message.fields[2], 'zug zug') - assert.equal(message.fields[3], null) - assert.equal(message.fields[4], '!') - } + const message = messages[0] as any; + assert.equal(message.fields.length, 5); + assert.equal(message.fields[0], null); + assert.equal(message.fields[1], 'bang'); + assert.equal(message.fields[2], 'zug zug'); + assert.equal(message.fields[3], null); + assert.equal(message.fields[4], '!'); + }; it('parses when split in the middle', function () { - testMessageRecievedAfterSpiltAt(6) - }) + testMessageRecievedAfterSpiltAt(6); + }); it('parses when split at end', function () { - testMessageRecievedAfterSpiltAt(2) - }) + testMessageRecievedAfterSpiltAt(2); + }); it('parses when split at beginning', function () { - testMessageRecievedAfterSpiltAt(fullBuffer.length - 2) - testMessageRecievedAfterSpiltAt(fullBuffer.length - 1) - testMessageRecievedAfterSpiltAt(fullBuffer.length - 5) - }) - }) + testMessageRecievedAfterSpiltAt(fullBuffer.length - 2); + testMessageRecievedAfterSpiltAt(fullBuffer.length - 1); + testMessageRecievedAfterSpiltAt(fullBuffer.length - 5); + }); + }); describe('split buffer, multiple message parsing', function () { - var dataRowBuffer = buffers.dataRow(['!']) - var readyForQueryBuffer = buffers.readyForQuery() - var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length) - dataRowBuffer.copy(fullBuffer, 0, 0) - readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0) + var dataRowBuffer = buffers.dataRow(['!']); + var readyForQueryBuffer = buffers.readyForQuery(); + var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length); + dataRowBuffer.copy(fullBuffer, 0, 0); + readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0); var verifyMessages = function (messages: any[]) { - assert.strictEqual(messages.length, 2) + assert.strictEqual(messages.length, 2); assert.deepEqual(messages[0], { name: 'dataRow', fieldCount: 1, length: 11, - fields: ['!'] - }) - assert.equal(messages[0].fields[0], '!') + fields: ['!'], + }); + assert.equal(messages[0].fields[0], '!'); assert.deepEqual(messages[1], { name: 'readyForQuery', length: 5, - status: 'I' - }) - } + status: 'I', + }); + }; // sanity check it('recieves both messages when packet is not split', async function () { - const messages = await parseBuffers([fullBuffer]) - verifyMessages(messages) - }) + const messages = await parseBuffers([fullBuffer]); + verifyMessages(messages); + }); var splitAndVerifyTwoMessages = async function (split: number) { - var firstBuffer = Buffer.alloc(fullBuffer.length - split) - var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) - fullBuffer.copy(firstBuffer, 0, 0) - fullBuffer.copy(secondBuffer, 0, firstBuffer.length) - const messages = await parseBuffers([firstBuffer, secondBuffer]) - verifyMessages(messages) - } + var firstBuffer = Buffer.alloc(fullBuffer.length - split); + var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length); + fullBuffer.copy(firstBuffer, 0, 0); + fullBuffer.copy(secondBuffer, 0, firstBuffer.length); + const messages = await parseBuffers([firstBuffer, secondBuffer]); + verifyMessages(messages); + }; describe('recieves both messages when packet is split', function () { it('in the middle', function () { - return splitAndVerifyTwoMessages(11) - }) + return splitAndVerifyTwoMessages(11); + }); it('at the front', function () { return Promise.all([ splitAndVerifyTwoMessages(fullBuffer.length - 1), splitAndVerifyTwoMessages(fullBuffer.length - 4), - splitAndVerifyTwoMessages(fullBuffer.length - 6) - ]) - }) + splitAndVerifyTwoMessages(fullBuffer.length - 6), + ]); + }); it('at the end', function () { - return Promise.all([ - splitAndVerifyTwoMessages(8), - splitAndVerifyTwoMessages(1) - ]) - }) - }) - }) - -}) + return Promise.all([splitAndVerifyTwoMessages(8), splitAndVerifyTwoMessages(1)]); + }); + }); + }); +}); diff --git a/packages/pg-protocol/src/index.ts b/packages/pg-protocol/src/index.ts index f4ade0173..57580f6ec 100644 --- a/packages/pg-protocol/src/index.ts +++ b/packages/pg-protocol/src/index.ts @@ -1,11 +1,11 @@ import { BackendMessage } from './messages'; import { serialize } from './serializer'; -import { Parser, MessageCallback } from './parser' +import { Parser, MessageCallback } from './parser'; export function parse(stream: NodeJS.ReadableStream, callback: MessageCallback): Promise { - const parser = new Parser() - stream.on('data', (buffer: Buffer) => parser.parse(buffer, callback)) - return new Promise((resolve) => stream.on('end', () => resolve())) + const parser = new Parser(); + stream.on('data', (buffer: Buffer) => parser.parse(buffer, callback)); + return new Promise((resolve) => stream.on('end', () => resolve())); } export { serialize }; diff --git a/packages/pg-protocol/src/messages.ts b/packages/pg-protocol/src/messages.ts index 222a24902..20d17f1d1 100644 --- a/packages/pg-protocol/src/messages.ts +++ b/packages/pg-protocol/src/messages.ts @@ -42,37 +42,37 @@ export const parseComplete: BackendMessage = { export const bindComplete: BackendMessage = { name: MessageName.bindComplete, length: 5, -} +}; export const closeComplete: BackendMessage = { name: MessageName.closeComplete, length: 5, -} +}; export const noData: BackendMessage = { name: MessageName.noData, - length: 5 -} + length: 5, +}; export const portalSuspended: BackendMessage = { name: MessageName.portalSuspended, length: 5, -} +}; export const replicationStart: BackendMessage = { name: MessageName.replicationStart, length: 4, -} +}; export const emptyQuery: BackendMessage = { name: MessageName.emptyQuery, length: 4, -} +}; export const copyDone: BackendMessage = { name: MessageName.copyDone, length: 4, -} +}; interface NoticeOrError { message: string | undefined; @@ -112,77 +112,89 @@ export class DatabaseError extends Error implements NoticeOrError { public line: string | undefined; public routine: string | undefined; constructor(message: string, public readonly length: number, public readonly name: MessageName) { - super(message) + super(message); } } export class CopyDataMessage { public readonly name = MessageName.copyData; - constructor(public readonly length: number, public readonly chunk: Buffer) { - - } + constructor(public readonly length: number, public readonly chunk: Buffer) {} } export class CopyResponse { public readonly columnTypes: number[]; - constructor(public readonly length: number, public readonly name: MessageName, public readonly binary: boolean, columnCount: number) { + constructor( + public readonly length: number, + public readonly name: MessageName, + public readonly binary: boolean, + columnCount: number + ) { this.columnTypes = new Array(columnCount); } } export class Field { - constructor(public readonly name: string, public readonly tableID: number, public readonly columnID: number, public readonly dataTypeID: number, public readonly dataTypeSize: number, public readonly dataTypeModifier: number, public readonly format: Mode) { - } + constructor( + public readonly name: string, + public readonly tableID: number, + public readonly columnID: number, + public readonly dataTypeID: number, + public readonly dataTypeSize: number, + public readonly dataTypeModifier: number, + public readonly format: Mode + ) {} } export class RowDescriptionMessage { public readonly name: MessageName = MessageName.rowDescription; public readonly fields: Field[]; constructor(public readonly length: number, public readonly fieldCount: number) { - this.fields = new Array(this.fieldCount) + this.fields = new Array(this.fieldCount); } } export class ParameterStatusMessage { public readonly name: MessageName = MessageName.parameterStatus; - constructor(public readonly length: number, public readonly parameterName: string, public readonly parameterValue: string) { - - } + constructor( + public readonly length: number, + public readonly parameterName: string, + public readonly parameterValue: string + ) {} } export class AuthenticationMD5Password implements BackendMessage { public readonly name: MessageName = MessageName.authenticationMD5Password; - constructor(public readonly length: number, public readonly salt: Buffer) { - } + constructor(public readonly length: number, public readonly salt: Buffer) {} } export class BackendKeyDataMessage { public readonly name: MessageName = MessageName.backendKeyData; - constructor(public readonly length: number, public readonly processID: number, public readonly secretKey: number) { - } + constructor(public readonly length: number, public readonly processID: number, public readonly secretKey: number) {} } export class NotificationResponseMessage { public readonly name: MessageName = MessageName.notification; - constructor(public readonly length: number, public readonly processId: number, public readonly channel: string, public readonly payload: string) { - } + constructor( + public readonly length: number, + public readonly processId: number, + public readonly channel: string, + public readonly payload: string + ) {} } export class ReadyForQueryMessage { public readonly name: MessageName = MessageName.readyForQuery; - constructor(public readonly length: number, public readonly status: string) { - } + constructor(public readonly length: number, public readonly status: string) {} } export class CommandCompleteMessage { - public readonly name: MessageName = MessageName.commandComplete - constructor(public readonly length: number, public readonly text: string) { - } + public readonly name: MessageName = MessageName.commandComplete; + constructor(public readonly length: number, public readonly text: string) {} } export class DataRowMessage { public readonly fieldCount: number; - public readonly name: MessageName = MessageName.dataRow + public readonly name: MessageName = MessageName.dataRow; constructor(public length: number, public fields: any[]) { this.fieldCount = fields.length; } diff --git a/packages/pg-protocol/src/outbound-serializer.test.ts b/packages/pg-protocol/src/outbound-serializer.test.ts index 110b932ce..c2ef22db7 100644 --- a/packages/pg-protocol/src/outbound-serializer.test.ts +++ b/packages/pg-protocol/src/outbound-serializer.test.ts @@ -1,85 +1,79 @@ -import assert from 'assert' -import { serialize } from './serializer' -import BufferList from './testing/buffer-list' +import assert from 'assert'; +import { serialize } from './serializer'; +import BufferList from './testing/buffer-list'; describe('serializer', () => { it('builds startup message', function () { const actual = serialize.startup({ user: 'brian', - database: 'bang' - }) - assert.deepEqual(actual, new BufferList() - .addInt16(3) - .addInt16(0) - .addCString('user') - .addCString('brian') - .addCString('database') - .addCString('bang') - .addCString('client_encoding') - .addCString("'utf-8'") - .addCString('').join(true)) - }) + database: 'bang', + }); + assert.deepEqual( + actual, + new BufferList() + .addInt16(3) + .addInt16(0) + .addCString('user') + .addCString('brian') + .addCString('database') + .addCString('bang') + .addCString('client_encoding') + .addCString("'utf-8'") + .addCString('') + .join(true) + ); + }); it('builds password message', function () { - const actual = serialize.password('!') - assert.deepEqual(actual, new BufferList().addCString('!').join(true, 'p')) - }) + const actual = serialize.password('!'); + assert.deepEqual(actual, new BufferList().addCString('!').join(true, 'p')); + }); it('builds request ssl message', function () { - const actual = serialize.requestSsl() - const expected = new BufferList().addInt32(80877103).join(true) + const actual = serialize.requestSsl(); + const expected = new BufferList().addInt32(80877103).join(true); assert.deepEqual(actual, expected); - }) + }); it('builds SASLInitialResponseMessage message', function () { - const actual = serialize.sendSASLInitialResponseMessage('mech', 'data') - assert.deepEqual(actual, new BufferList().addCString('mech').addInt32(4).addString('data').join(true, 'p')) - }) - + const actual = serialize.sendSASLInitialResponseMessage('mech', 'data'); + assert.deepEqual(actual, new BufferList().addCString('mech').addInt32(4).addString('data').join(true, 'p')); + }); it('builds SCRAMClientFinalMessage message', function () { - const actual = serialize.sendSCRAMClientFinalMessage('data') - assert.deepEqual(actual, new BufferList().addString('data').join(true, 'p')) - }) - + const actual = serialize.sendSCRAMClientFinalMessage('data'); + assert.deepEqual(actual, new BufferList().addString('data').join(true, 'p')); + }); it('builds query message', function () { - var txt = 'select * from boom' - const actual = serialize.query(txt) - assert.deepEqual(actual, new BufferList().addCString(txt).join(true, 'Q')) - }) - + var txt = 'select * from boom'; + const actual = serialize.query(txt); + assert.deepEqual(actual, new BufferList().addCString(txt).join(true, 'Q')); + }); describe('parse message', () => { - it('builds parse message', function () { - const actual = serialize.parse({ text: '!' }) - var expected = new BufferList() - .addCString('') - .addCString('!') - .addInt16(0).join(true, 'P') - assert.deepEqual(actual, expected) - }) + const actual = serialize.parse({ text: '!' }); + var expected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P'); + assert.deepEqual(actual, expected); + }); it('builds parse message with named query', function () { const actual = serialize.parse({ name: 'boom', text: 'select * from boom', - types: [] - }) - var expected = new BufferList() - .addCString('boom') - .addCString('select * from boom') - .addInt16(0).join(true, 'P') - assert.deepEqual(actual, expected) - }) + types: [], + }); + var expected = new BufferList().addCString('boom').addCString('select * from boom').addInt16(0).join(true, 'P'); + assert.deepEqual(actual, expected); + }); it('with multiple parameters', function () { const actual = serialize.parse({ name: 'force', text: 'select * from bang where name = $1', - types: [1, 2, 3, 4] - }) + types: [1, 2, 3, 4], + }); var expected = new BufferList() .addCString('force') .addCString('select * from bang where name = $1') @@ -87,16 +81,15 @@ describe('serializer', () => { .addInt32(1) .addInt32(2) .addInt32(3) - .addInt32(4).join(true, 'P') - assert.deepEqual(actual, expected) - }) - - }) - + .addInt32(4) + .join(true, 'P'); + assert.deepEqual(actual, expected); + }); + }); describe('bind messages', function () { it('with no values', function () { - const actual = serialize.bind() + const actual = serialize.bind(); var expectedBuffer = new BufferList() .addCString('') @@ -104,18 +97,18 @@ describe('serializer', () => { .addInt16(0) .addInt16(0) .addInt16(0) - .join(true, 'B') - assert.deepEqual(actual, expectedBuffer) - }) + .join(true, 'B'); + assert.deepEqual(actual, expectedBuffer); + }); it('with named statement, portal, and values', function () { const actual = serialize.bind({ portal: 'bang', statement: 'woo', - values: ['1', 'hi', null, 'zing'] - }) + values: ['1', 'hi', null, 'zing'], + }); var expectedBuffer = new BufferList() - .addCString('bang') // portal name + .addCString('bang') // portal name .addCString('woo') // statement name .addInt16(0) .addInt16(4) @@ -127,25 +120,25 @@ describe('serializer', () => { .addInt32(4) .add(Buffer.from('zing')) .addInt16(0) - .join(true, 'B') - assert.deepEqual(actual, expectedBuffer) - }) - }) + .join(true, 'B'); + assert.deepEqual(actual, expectedBuffer); + }); + }); it('with named statement, portal, and buffer value', function () { const actual = serialize.bind({ portal: 'bang', statement: 'woo', - values: ['1', 'hi', null, Buffer.from('zing', 'utf8')] - }) + values: ['1', 'hi', null, Buffer.from('zing', 'utf8')], + }); var expectedBuffer = new BufferList() - .addCString('bang') // portal name + .addCString('bang') // portal name .addCString('woo') // statement name - .addInt16(4)// value count - .addInt16(0)// string - .addInt16(0)// string - .addInt16(0)// string - .addInt16(1)// binary + .addInt16(4) // value count + .addInt16(0) // string + .addInt16(0) // string + .addInt16(0) // string + .addInt16(1) // binary .addInt16(4) .addInt32(1) .add(Buffer.from('1')) @@ -155,102 +148,96 @@ describe('serializer', () => { .addInt32(4) .add(Buffer.from('zing', 'utf-8')) .addInt16(0) - .join(true, 'B') - assert.deepEqual(actual, expectedBuffer) - }) + .join(true, 'B'); + assert.deepEqual(actual, expectedBuffer); + }); describe('builds execute message', function () { it('for unamed portal with no row limit', function () { - const actual = serialize.execute() - var expectedBuffer = new BufferList() - .addCString('') - .addInt32(0) - .join(true, 'E') - assert.deepEqual(actual, expectedBuffer) - }) + const actual = serialize.execute(); + var expectedBuffer = new BufferList().addCString('').addInt32(0).join(true, 'E'); + assert.deepEqual(actual, expectedBuffer); + }); it('for named portal with row limit', function () { const actual = serialize.execute({ portal: 'my favorite portal', - rows: 100 - }) - var expectedBuffer = new BufferList() - .addCString('my favorite portal') - .addInt32(100) - .join(true, 'E') - assert.deepEqual(actual, expectedBuffer) - }) - }) + rows: 100, + }); + var expectedBuffer = new BufferList().addCString('my favorite portal').addInt32(100).join(true, 'E'); + assert.deepEqual(actual, expectedBuffer); + }); + }); it('builds flush command', function () { - const actual = serialize.flush() - var expected = new BufferList().join(true, 'H') - assert.deepEqual(actual, expected) - }) + const actual = serialize.flush(); + var expected = new BufferList().join(true, 'H'); + assert.deepEqual(actual, expected); + }); it('builds sync command', function () { - const actual = serialize.sync() - var expected = new BufferList().join(true, 'S') - assert.deepEqual(actual, expected) - }) + const actual = serialize.sync(); + var expected = new BufferList().join(true, 'S'); + assert.deepEqual(actual, expected); + }); it('builds end command', function () { - const actual = serialize.end() - var expected = Buffer.from([0x58, 0, 0, 0, 4]) - assert.deepEqual(actual, expected) - }) + const actual = serialize.end(); + var expected = Buffer.from([0x58, 0, 0, 0, 4]); + assert.deepEqual(actual, expected); + }); describe('builds describe command', function () { it('describe statement', function () { - const actual = serialize.describe({ type: 'S', name: 'bang' }) - var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D') - assert.deepEqual(actual, expected) - }) + const actual = serialize.describe({ type: 'S', name: 'bang' }); + var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D'); + assert.deepEqual(actual, expected); + }); it('describe unnamed portal', function () { - const actual = serialize.describe({ type: 'P' }) - var expected = new BufferList().addChar('P').addCString('').join(true, 'D') - assert.deepEqual(actual, expected) - }) - }) + const actual = serialize.describe({ type: 'P' }); + var expected = new BufferList().addChar('P').addCString('').join(true, 'D'); + assert.deepEqual(actual, expected); + }); + }); describe('builds close command', function () { it('describe statement', function () { - const actual = serialize.close({ type: 'S', name: 'bang' }) - var expected = new BufferList().addChar('S').addCString('bang').join(true, 'C') - assert.deepEqual(actual, expected) - }) + const actual = serialize.close({ type: 'S', name: 'bang' }); + var expected = new BufferList().addChar('S').addCString('bang').join(true, 'C'); + assert.deepEqual(actual, expected); + }); it('describe unnamed portal', function () { - const actual = serialize.close({ type: 'P' }) - var expected = new BufferList().addChar('P').addCString('').join(true, 'C') - assert.deepEqual(actual, expected) - }) - }) + const actual = serialize.close({ type: 'P' }); + var expected = new BufferList().addChar('P').addCString('').join(true, 'C'); + assert.deepEqual(actual, expected); + }); + }); describe('copy messages', function () { it('builds copyFromChunk', () => { - const actual = serialize.copyData(Buffer.from([1, 2, 3])) - const expected = new BufferList().add(Buffer.from([1, 2,3 ])).join(true, 'd') - assert.deepEqual(actual, expected) - }) + const actual = serialize.copyData(Buffer.from([1, 2, 3])); + const expected = new BufferList().add(Buffer.from([1, 2, 3])).join(true, 'd'); + assert.deepEqual(actual, expected); + }); it('builds copy fail', () => { - const actual = serialize.copyFail('err!') - const expected = new BufferList().addCString('err!').join(true, 'f') - assert.deepEqual(actual, expected) - }) + const actual = serialize.copyFail('err!'); + const expected = new BufferList().addCString('err!').join(true, 'f'); + assert.deepEqual(actual, expected); + }); it('builds copy done', () => { - const actual = serialize.copyDone() - const expected = new BufferList().join(true, 'c') - assert.deepEqual(actual, expected) - }) - }) + const actual = serialize.copyDone(); + const expected = new BufferList().join(true, 'c'); + assert.deepEqual(actual, expected); + }); + }); it('builds cancel message', () => { - const actual = serialize.cancel(3, 4) - const expected = new BufferList().addInt16(1234).addInt16(5678).addInt32(3).addInt32(4).join(true) - assert.deepEqual(actual, expected) - }) -}) + const actual = serialize.cancel(3, 4); + const expected = new BufferList().addInt16(1234).addInt16(5678).addInt32(3).addInt32(4).join(true); + assert.deepEqual(actual, expected); + }); +}); diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 14573e624..58de45e1f 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -1,7 +1,32 @@ import { TransformOptions } from 'stream'; -import { Mode, bindComplete, parseComplete, closeComplete, noData, portalSuspended, copyDone, replicationStart, emptyQuery, ReadyForQueryMessage, CommandCompleteMessage, CopyDataMessage, CopyResponse, NotificationResponseMessage, RowDescriptionMessage, Field, DataRowMessage, ParameterStatusMessage, BackendKeyDataMessage, DatabaseError, BackendMessage, MessageName, AuthenticationMD5Password, NoticeMessage } from './messages'; +import { + Mode, + bindComplete, + parseComplete, + closeComplete, + noData, + portalSuspended, + copyDone, + replicationStart, + emptyQuery, + ReadyForQueryMessage, + CommandCompleteMessage, + CopyDataMessage, + CopyResponse, + NotificationResponseMessage, + RowDescriptionMessage, + Field, + DataRowMessage, + ParameterStatusMessage, + BackendKeyDataMessage, + DatabaseError, + BackendMessage, + MessageName, + AuthenticationMD5Password, + NoticeMessage, +} from './messages'; import { BufferReader } from './buffer-reader'; -import assert from 'assert' +import assert from 'assert'; // every message is prefixed with a single bye const CODE_LENGTH = 1; @@ -14,13 +39,13 @@ const HEADER_LENGTH = CODE_LENGTH + LEN_LENGTH; export type Packet = { code: number; packet: Buffer; -} +}; const emptyBuffer = Buffer.allocUnsafe(0); type StreamOptions = TransformOptions & { - mode: Mode -} + mode: Mode; +}; const enum MessageCodes { DataRow = 0x44, // D @@ -55,7 +80,7 @@ export class Parser { constructor(opts?: StreamOptions) { if (opts?.mode === 'binary') { - throw new Error('Binary mode not supported yet') + throw new Error('Binary mode not supported yet'); } this.mode = opts?.mode || 'text'; } @@ -64,11 +89,11 @@ export class Parser { let combinedBuffer = buffer; if (this.remainingBuffer.byteLength) { combinedBuffer = Buffer.allocUnsafe(this.remainingBuffer.byteLength + buffer.byteLength); - this.remainingBuffer.copy(combinedBuffer) - buffer.copy(combinedBuffer, this.remainingBuffer.byteLength) + this.remainingBuffer.copy(combinedBuffer); + buffer.copy(combinedBuffer, this.remainingBuffer.byteLength); } let offset = 0; - while ((offset + HEADER_LENGTH) <= combinedBuffer.byteLength) { + while (offset + HEADER_LENGTH <= combinedBuffer.byteLength) { // code is 1 byte long - it identifies the message type const code = combinedBuffer[offset]; @@ -79,7 +104,7 @@ export class Parser { if (fullMessageLength + offset <= combinedBuffer.byteLength) { const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer); - callback(message) + callback(message); offset += fullMessageLength; } else { break; @@ -89,9 +114,8 @@ export class Parser { if (offset === combinedBuffer.byteLength) { this.remainingBuffer = emptyBuffer; } else { - this.remainingBuffer = combinedBuffer.slice(offset) + this.remainingBuffer = combinedBuffer.slice(offset); } - } private handlePacket(offset: number, code: number, length: number, bytes: Buffer): BackendMessage { @@ -139,14 +163,14 @@ export class Parser { case MessageCodes.CopyData: return this.parseCopyData(offset, length, bytes); default: - assert.fail(`unknown message code: ${code.toString(16)}`) + assert.fail(`unknown message code: ${code.toString(16)}`); } } private parseReadyForQueryMessage(offset: number, length: number, bytes: Buffer) { this.reader.setBuffer(offset, bytes); const status = this.reader.string(1); - return new ReadyForQueryMessage(length, status) + return new ReadyForQueryMessage(length, status); } private parseCommandCompleteMessage(offset: number, length: number, bytes: Buffer) { @@ -161,17 +185,17 @@ export class Parser { } private parseCopyInMessage(offset: number, length: number, bytes: Buffer) { - return this.parseCopyMessage(offset, length, bytes, MessageName.copyInResponse) + return this.parseCopyMessage(offset, length, bytes, MessageName.copyInResponse); } private parseCopyOutMessage(offset: number, length: number, bytes: Buffer) { - return this.parseCopyMessage(offset, length, bytes, MessageName.copyOutResponse) + return this.parseCopyMessage(offset, length, bytes, MessageName.copyOutResponse); } private parseCopyMessage(offset: number, length: number, bytes: Buffer, messageName: MessageName) { this.reader.setBuffer(offset, bytes); const isBinary = this.reader.byte() !== 0; - const columnCount = this.reader.int16() + const columnCount = this.reader.int16(); const message = new CopyResponse(length, messageName, isBinary, columnCount); for (let i = 0; i < columnCount; i++) { message.columnTypes[i] = this.reader.int16(); @@ -189,23 +213,23 @@ export class Parser { private parseRowDescriptionMessage(offset: number, length: number, bytes: Buffer) { this.reader.setBuffer(offset, bytes); - const fieldCount = this.reader.int16() + const fieldCount = this.reader.int16(); const message = new RowDescriptionMessage(length, fieldCount); for (let i = 0; i < fieldCount; i++) { - message.fields[i] = this.parseField() + message.fields[i] = this.parseField(); } return message; } private parseField(): Field { - const name = this.reader.cstring() - const tableID = this.reader.int32() - const columnID = this.reader.int16() - const dataTypeID = this.reader.int32() - const dataTypeSize = this.reader.int16() - const dataTypeModifier = this.reader.int32() + const name = this.reader.cstring(); + const tableID = this.reader.int32(); + const columnID = this.reader.int16(); + const dataTypeID = this.reader.int32(); + const dataTypeSize = this.reader.int16(); + const dataTypeModifier = this.reader.int32(); const mode = this.reader.int16() === 0 ? 'text' : 'binary'; - return new Field(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, mode) + return new Field(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, mode); } private parseDataRowMessage(offset: number, length: number, bytes: Buffer) { @@ -215,7 +239,7 @@ export class Parser { for (let i = 0; i < fieldCount; i++) { const len = this.reader.int32(); // a -1 for length means the value of the field is null - fields[i] = len === -1 ? null : this.reader.string(len) + fields[i] = len === -1 ? null : this.reader.string(len); } return new DataRowMessage(length, fields); } @@ -223,21 +247,20 @@ export class Parser { private parseParameterStatusMessage(offset: number, length: number, bytes: Buffer) { this.reader.setBuffer(offset, bytes); const name = this.reader.cstring(); - const value = this.reader.cstring() - return new ParameterStatusMessage(length, name, value) + const value = this.reader.cstring(); + return new ParameterStatusMessage(length, name, value); } private parseBackendKeyData(offset: number, length: number, bytes: Buffer) { this.reader.setBuffer(offset, bytes); - const processID = this.reader.int32() - const secretKey = this.reader.int32() - return new BackendKeyDataMessage(length, processID, secretKey) + const processID = this.reader.int32(); + const secretKey = this.reader.int32(); + return new BackendKeyDataMessage(length, processID, secretKey); } - public parseAuthenticationResponse(offset: number, length: number, bytes: Buffer) { this.reader.setBuffer(offset, bytes); - const code = this.reader.int32() + const code = this.reader.int32(); // TODO(bmc): maybe better types here const message: BackendMessage & any = { name: MessageName.authenticationOk, @@ -249,71 +272,74 @@ export class Parser { break; case 3: // AuthenticationCleartextPassword if (message.length === 8) { - message.name = MessageName.authenticationCleartextPassword + message.name = MessageName.authenticationCleartextPassword; } - break + break; case 5: // AuthenticationMD5Password if (message.length === 12) { - message.name = MessageName.authenticationMD5Password + message.name = MessageName.authenticationMD5Password; const salt = this.reader.bytes(4); return new AuthenticationMD5Password(length, salt); } - break + break; case 10: // AuthenticationSASL - message.name = MessageName.authenticationSASL - message.mechanisms = [] + message.name = MessageName.authenticationSASL; + message.mechanisms = []; let mechanism: string; do { - mechanism = this.reader.cstring() + mechanism = this.reader.cstring(); if (mechanism) { - message.mechanisms.push(mechanism) + message.mechanisms.push(mechanism); } - } while (mechanism) + } while (mechanism); break; case 11: // AuthenticationSASLContinue - message.name = MessageName.authenticationSASLContinue - message.data = this.reader.string(length - 4) + message.name = MessageName.authenticationSASLContinue; + message.data = this.reader.string(length - 4); break; case 12: // AuthenticationSASLFinal - message.name = MessageName.authenticationSASLFinal - message.data = this.reader.string(length - 4) + message.name = MessageName.authenticationSASLFinal; + message.data = this.reader.string(length - 4); break; default: - throw new Error('Unknown authenticationOk message type ' + code) + throw new Error('Unknown authenticationOk message type ' + code); } return message; } private parseErrorMessage(offset: number, length: number, bytes: Buffer, name: MessageName) { this.reader.setBuffer(offset, bytes); - const fields: Record = {} - let fieldType = this.reader.string(1) + const fields: Record = {}; + let fieldType = this.reader.string(1); while (fieldType !== '\0') { - fields[fieldType] = this.reader.cstring() - fieldType = this.reader.string(1) + fields[fieldType] = this.reader.cstring(); + fieldType = this.reader.string(1); } - const messageValue = fields.M - - const message = name === MessageName.notice ? new NoticeMessage(length, messageValue) : new DatabaseError(messageValue, length, name) - - message.severity = fields.S - message.code = fields.C - message.detail = fields.D - message.hint = fields.H - message.position = fields.P - message.internalPosition = fields.p - message.internalQuery = fields.q - message.where = fields.W - message.schema = fields.s - message.table = fields.t - message.column = fields.c - message.dataType = fields.d - message.constraint = fields.n - message.file = fields.F - message.line = fields.L - message.routine = fields.R + const messageValue = fields.M; + + const message = + name === MessageName.notice + ? new NoticeMessage(length, messageValue) + : new DatabaseError(messageValue, length, name); + + message.severity = fields.S; + message.code = fields.C; + message.detail = fields.D; + message.hint = fields.H; + message.position = fields.P; + message.internalPosition = fields.p; + message.internalQuery = fields.q; + message.where = fields.W; + message.schema = fields.s; + message.table = fields.t; + message.column = fields.c; + message.dataType = fields.d; + message.constraint = fields.n; + message.file = fields.F; + message.line = fields.L; + message.routine = fields.R; return message; } } diff --git a/packages/pg-protocol/src/serializer.ts b/packages/pg-protocol/src/serializer.ts index 71ac3c878..904875dd1 100644 --- a/packages/pg-protocol/src/serializer.ts +++ b/packages/pg-protocol/src/serializer.ts @@ -1,4 +1,4 @@ -import { Writer } from './buffer-writer' +import { Writer } from './buffer-writer'; const enum code { startup = 0x70, @@ -13,67 +13,61 @@ const enum code { describe = 0x44, copyFromChunk = 0x64, copyDone = 0x63, - copyFail = 0x66 + copyFail = 0x66, } -const writer = new Writer() +const writer = new Writer(); const startup = (opts: Record): Buffer => { // protocol version - writer.addInt16(3).addInt16(0) + writer.addInt16(3).addInt16(0); for (const key of Object.keys(opts)) { - writer.addCString(key).addCString(opts[key]) + writer.addCString(key).addCString(opts[key]); } - writer.addCString('client_encoding').addCString("'utf-8'") + writer.addCString('client_encoding').addCString("'utf-8'"); - var bodyBuffer = writer.addCString('').flush() + var bodyBuffer = writer.addCString('').flush(); // this message is sent without a code - var length = bodyBuffer.length + 4 + var length = bodyBuffer.length + 4; - return new Writer() - .addInt32(length) - .add(bodyBuffer) - .flush() -} + return new Writer().addInt32(length).add(bodyBuffer).flush(); +}; const requestSsl = (): Buffer => { - const response = Buffer.allocUnsafe(8) + const response = Buffer.allocUnsafe(8); response.writeInt32BE(8, 0); - response.writeInt32BE(80877103, 4) - return response -} + response.writeInt32BE(80877103, 4); + return response; +}; const password = (password: string): Buffer => { - return writer.addCString(password).flush(code.startup) -} + return writer.addCString(password).flush(code.startup); +}; const sendSASLInitialResponseMessage = function (mechanism: string, initialResponse: string): Buffer { // 0x70 = 'p' - writer - .addCString(mechanism) - .addInt32(Buffer.byteLength(initialResponse)) - .addString(initialResponse) + writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse); - return writer.flush(code.startup) -} + return writer.flush(code.startup); +}; const sendSCRAMClientFinalMessage = function (additionalData: string): Buffer { - return writer.addString(additionalData).flush(code.startup) -} + return writer.addString(additionalData).flush(code.startup); +}; const query = (text: string): Buffer => { - return writer.addCString(text).flush(code.query) -} + return writer.addCString(text).flush(code.query); +}; type ParseOpts = { name?: string; types?: number[]; text: string; -} +}; -const emptyArray: any[] = [] +const emptyArray: any[] = []; const parse = (query: ParseOpts): Buffer => { // expect something like this: @@ -82,171 +76,169 @@ const parse = (query: ParseOpts): Buffer => { // types: ['int8', 'bool'] } // normalize missing query names to allow for null - const name = query.name || '' + const name = query.name || ''; if (name.length > 63) { /* eslint-disable no-console */ - console.error('Warning! Postgres only supports 63 characters for query names.') - console.error('You supplied %s (%s)', name, name.length) - console.error('This can cause conflicts and silent errors executing queries') + console.error('Warning! Postgres only supports 63 characters for query names.'); + console.error('You supplied %s (%s)', name, name.length); + console.error('This can cause conflicts and silent errors executing queries'); /* eslint-enable no-console */ } - const types = query.types || emptyArray + const types = query.types || emptyArray; - var len = types.length + var len = types.length; var buffer = writer .addCString(name) // name of query .addCString(query.text) // actual query text - .addInt16(len) + .addInt16(len); for (var i = 0; i < len; i++) { - buffer.addInt32(types[i]) + buffer.addInt32(types[i]); } - return writer.flush(code.parse) -} + return writer.flush(code.parse); +}; type BindOpts = { portal?: string; binary?: boolean; statement?: string; values?: any[]; -} +}; const bind = (config: BindOpts = {}): Buffer => { // normalize config - const portal = config.portal || '' - const statement = config.statement || '' - const binary = config.binary || false - var values = config.values || emptyArray - var len = values.length + const portal = config.portal || ''; + const statement = config.statement || ''; + const binary = config.binary || false; + var values = config.values || emptyArray; + var len = values.length; - var useBinary = false + var useBinary = false; // TODO(bmc): all the loops in here aren't nice, we can do better for (var j = 0; j < len; j++) { - useBinary = useBinary || values[j] instanceof Buffer + useBinary = useBinary || values[j] instanceof Buffer; } - var buffer = writer - .addCString(portal) - .addCString(statement) + var buffer = writer.addCString(portal).addCString(statement); if (!useBinary) { - buffer.addInt16(0) + buffer.addInt16(0); } else { - buffer.addInt16(len) + buffer.addInt16(len); for (j = 0; j < len; j++) { - buffer.addInt16(values[j] instanceof Buffer ? 1 : 0) + buffer.addInt16(values[j] instanceof Buffer ? 1 : 0); } } - buffer.addInt16(len) + buffer.addInt16(len); for (var i = 0; i < len; i++) { - var val = values[i] + var val = values[i]; if (val === null || typeof val === 'undefined') { - buffer.addInt32(-1) + buffer.addInt32(-1); } else if (val instanceof Buffer) { - buffer.addInt32(val.length) - buffer.add(val) + buffer.addInt32(val.length); + buffer.add(val); } else { - buffer.addInt32(Buffer.byteLength(val)) - buffer.addString(val) + buffer.addInt32(Buffer.byteLength(val)); + buffer.addString(val); } } if (binary) { - buffer.addInt16(1) // format codes to use binary - buffer.addInt16(1) + buffer.addInt16(1); // format codes to use binary + buffer.addInt16(1); } else { - buffer.addInt16(0) // format codes to use text + buffer.addInt16(0); // format codes to use text } - return writer.flush(code.bind) -} + return writer.flush(code.bind); +}; type ExecOpts = { portal?: string; rows?: number; -} +}; -const emptyExecute = Buffer.from([code.execute, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00]) +const emptyExecute = Buffer.from([code.execute, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00]); const execute = (config?: ExecOpts): Buffer => { // this is the happy path for most queries - if (!config || !config.portal && !config.rows) { + if (!config || (!config.portal && !config.rows)) { return emptyExecute; } - const portal = config.portal || '' - const rows = config.rows || 0 + const portal = config.portal || ''; + const rows = config.rows || 0; - const portalLength = Buffer.byteLength(portal) - const len = 4 + portalLength + 1 + 4 + const portalLength = Buffer.byteLength(portal); + const len = 4 + portalLength + 1 + 4; // one extra bit for code - const buff = Buffer.allocUnsafe(1 + len) - buff[0] = code.execute - buff.writeInt32BE(len, 1) - buff.write(portal, 5, 'utf-8') + const buff = Buffer.allocUnsafe(1 + len); + buff[0] = code.execute; + buff.writeInt32BE(len, 1); + buff.write(portal, 5, 'utf-8'); buff[portalLength + 5] = 0; // null terminate portal cString - buff.writeUInt32BE(rows, buff.length - 4) + buff.writeUInt32BE(rows, buff.length - 4); return buff; -} +}; const cancel = (processID: number, secretKey: number): Buffer => { - const buffer = Buffer.allocUnsafe(16) - buffer.writeInt32BE(16, 0) - buffer.writeInt16BE(1234, 4) - buffer.writeInt16BE(5678, 6) - buffer.writeInt32BE(processID, 8) - buffer.writeInt32BE(secretKey, 12) + const buffer = Buffer.allocUnsafe(16); + buffer.writeInt32BE(16, 0); + buffer.writeInt16BE(1234, 4); + buffer.writeInt16BE(5678, 6); + buffer.writeInt32BE(processID, 8); + buffer.writeInt32BE(secretKey, 12); return buffer; -} +}; type PortalOpts = { - type: 'S' | 'P', + type: 'S' | 'P'; name?: string; -} +}; const cstringMessage = (code: code, string: string): Buffer => { - const stringLen = Buffer.byteLength(string) - const len = 4 + stringLen + 1 + const stringLen = Buffer.byteLength(string); + const len = 4 + stringLen + 1; // one extra bit for code - const buffer = Buffer.allocUnsafe(1 + len) - buffer[0] = code - buffer.writeInt32BE(len, 1) - buffer.write(string, 5, 'utf-8') - buffer[len] = 0 // null terminate cString - return buffer -} + const buffer = Buffer.allocUnsafe(1 + len); + buffer[0] = code; + buffer.writeInt32BE(len, 1); + buffer.write(string, 5, 'utf-8'); + buffer[len] = 0; // null terminate cString + return buffer; +}; -const emptyDescribePortal = writer.addCString('P').flush(code.describe) -const emptyDescribeStatement = writer.addCString('S').flush(code.describe) +const emptyDescribePortal = writer.addCString('P').flush(code.describe); +const emptyDescribeStatement = writer.addCString('S').flush(code.describe); const describe = (msg: PortalOpts): Buffer => { - return msg.name ? - cstringMessage(code.describe,`${msg.type}${msg.name || ''}`) : - msg.type === 'P' ? - emptyDescribePortal : - emptyDescribeStatement; -} + return msg.name + ? cstringMessage(code.describe, `${msg.type}${msg.name || ''}`) + : msg.type === 'P' + ? emptyDescribePortal + : emptyDescribeStatement; +}; const close = (msg: PortalOpts): Buffer => { - const text = `${msg.type}${msg.name || ''}` - return cstringMessage(code.close, text) -} + const text = `${msg.type}${msg.name || ''}`; + return cstringMessage(code.close, text); +}; const copyData = (chunk: Buffer): Buffer => { - return writer.add(chunk).flush(code.copyFromChunk) -} + return writer.add(chunk).flush(code.copyFromChunk); +}; const copyFail = (message: string): Buffer => { return cstringMessage(code.copyFail, message); -} +}; -const codeOnlyBuffer = (code: code): Buffer => Buffer.from([code, 0x00, 0x00, 0x00, 0x04]) +const codeOnlyBuffer = (code: code): Buffer => Buffer.from([code, 0x00, 0x00, 0x00, 0x04]); -const flushBuffer = codeOnlyBuffer(code.flush) -const syncBuffer = codeOnlyBuffer(code.sync) -const endBuffer = codeOnlyBuffer(code.end) -const copyDoneBuffer = codeOnlyBuffer(code.copyDone) +const flushBuffer = codeOnlyBuffer(code.flush); +const syncBuffer = codeOnlyBuffer(code.sync); +const endBuffer = codeOnlyBuffer(code.end); +const copyDoneBuffer = codeOnlyBuffer(code.copyDone); const serialize = { startup, @@ -266,7 +258,7 @@ const serialize = { copyData, copyDone: () => copyDoneBuffer, copyFail, - cancel -} + cancel, +}; -export { serialize } +export { serialize }; diff --git a/packages/pg-protocol/src/testing/buffer-list.ts b/packages/pg-protocol/src/testing/buffer-list.ts index 51812bce4..d7c7e4574 100644 --- a/packages/pg-protocol/src/testing/buffer-list.ts +++ b/packages/pg-protocol/src/testing/buffer-list.ts @@ -1,79 +1,75 @@ export default class BufferList { - constructor(public buffers: Buffer[] = []) { - - } + constructor(public buffers: Buffer[] = []) {} public add(buffer: Buffer, front?: boolean) { - this.buffers[front ? 'unshift' : 'push'](buffer) - return this + this.buffers[front ? 'unshift' : 'push'](buffer); + return this; } public addInt16(val: number, front?: boolean) { - return this.add(Buffer.from([(val >>> 8), (val >>> 0)]), front) + return this.add(Buffer.from([val >>> 8, val >>> 0]), front); } public getByteLength(initial?: number) { return this.buffers.reduce(function (previous, current) { - return previous + current.length - }, initial || 0) + return previous + current.length; + }, initial || 0); } public addInt32(val: number, first?: boolean) { - return this.add(Buffer.from([ - (val >>> 24 & 0xFF), - (val >>> 16 & 0xFF), - (val >>> 8 & 0xFF), - (val >>> 0 & 0xFF) - ]), first) + return this.add( + Buffer.from([(val >>> 24) & 0xff, (val >>> 16) & 0xff, (val >>> 8) & 0xff, (val >>> 0) & 0xff]), + first + ); } public addCString(val: string, front?: boolean) { - var len = Buffer.byteLength(val) - var buffer = Buffer.alloc(len + 1) - buffer.write(val) - buffer[len] = 0 - return this.add(buffer, front) + var len = Buffer.byteLength(val); + var buffer = Buffer.alloc(len + 1); + buffer.write(val); + buffer[len] = 0; + return this.add(buffer, front); } public addString(val: string, front?: boolean) { - var len = Buffer.byteLength(val) - var buffer = Buffer.alloc(len) - buffer.write(val) - return this.add(buffer, front) + var len = Buffer.byteLength(val); + var buffer = Buffer.alloc(len); + buffer.write(val); + return this.add(buffer, front); } public addChar(char: string, first?: boolean) { - return this.add(Buffer.from(char, 'utf8'), first) + return this.add(Buffer.from(char, 'utf8'), first); } public addByte(byte: number) { - return this.add(Buffer.from([byte])) + return this.add(Buffer.from([byte])); } public join(appendLength?: boolean, char?: string): Buffer { - var length = this.getByteLength() + var length = this.getByteLength(); if (appendLength) { - this.addInt32(length + 4, true) - return this.join(false, char) + this.addInt32(length + 4, true); + return this.join(false, char); } if (char) { - this.addChar(char, true) - length++ + this.addChar(char, true); + length++; } - var result = Buffer.alloc(length) - var index = 0 + var result = Buffer.alloc(length); + var index = 0; this.buffers.forEach(function (buffer) { - buffer.copy(result, index, 0) - index += buffer.length - }) - return result + buffer.copy(result, index, 0); + index += buffer.length; + }); + return result; } public static concat(): Buffer { - var total = new BufferList() + var total = new BufferList(); for (var i = 0; i < arguments.length; i++) { - total.add(arguments[i]) + total.add(arguments[i]); } - return total.join() + return total.join(); } } diff --git a/packages/pg-protocol/src/testing/test-buffers.ts b/packages/pg-protocol/src/testing/test-buffers.ts index 0594eaadc..32384976e 100644 --- a/packages/pg-protocol/src/testing/test-buffers.ts +++ b/packages/pg-protocol/src/testing/test-buffers.ts @@ -1,150 +1,123 @@ // http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html -import BufferList from './buffer-list' +import BufferList from './buffer-list'; const buffers = { readyForQuery: function () { - return new BufferList() - .add(Buffer.from('I')) - .join(true, 'Z') + return new BufferList().add(Buffer.from('I')).join(true, 'Z'); }, authenticationOk: function () { - return new BufferList() - .addInt32(0) - .join(true, 'R') + return new BufferList().addInt32(0).join(true, 'R'); }, authenticationCleartextPassword: function () { - return new BufferList() - .addInt32(3) - .join(true, 'R') + return new BufferList().addInt32(3).join(true, 'R'); }, authenticationMD5Password: function () { return new BufferList() .addInt32(5) .add(Buffer.from([1, 2, 3, 4])) - .join(true, 'R') + .join(true, 'R'); }, authenticationSASL: function () { - return new BufferList() - .addInt32(10) - .addCString('SCRAM-SHA-256') - .addCString('') - .join(true, 'R') + return new BufferList().addInt32(10).addCString('SCRAM-SHA-256').addCString('').join(true, 'R'); }, authenticationSASLContinue: function () { - return new BufferList() - .addInt32(11) - .addString('data') - .join(true, 'R') + return new BufferList().addInt32(11).addString('data').join(true, 'R'); }, authenticationSASLFinal: function () { - return new BufferList() - .addInt32(12) - .addString('data') - .join(true, 'R') + return new BufferList().addInt32(12).addString('data').join(true, 'R'); }, parameterStatus: function (name: string, value: string) { - return new BufferList() - .addCString(name) - .addCString(value) - .join(true, 'S') + return new BufferList().addCString(name).addCString(value).join(true, 'S'); }, backendKeyData: function (processID: number, secretKey: number) { - return new BufferList() - .addInt32(processID) - .addInt32(secretKey) - .join(true, 'K') + return new BufferList().addInt32(processID).addInt32(secretKey).join(true, 'K'); }, commandComplete: function (string: string) { - return new BufferList() - .addCString(string) - .join(true, 'C') + return new BufferList().addCString(string).join(true, 'C'); }, rowDescription: function (fields: any[]) { - fields = fields || [] - var buf = new BufferList() - buf.addInt16(fields.length) + fields = fields || []; + var buf = new BufferList(); + buf.addInt16(fields.length); fields.forEach(function (field) { - buf.addCString(field.name) + buf + .addCString(field.name) .addInt32(field.tableID || 0) .addInt16(field.attributeNumber || 0) .addInt32(field.dataTypeID || 0) .addInt16(field.dataTypeSize || 0) .addInt32(field.typeModifier || 0) - .addInt16(field.formatCode || 0) - }) - return buf.join(true, 'T') + .addInt16(field.formatCode || 0); + }); + return buf.join(true, 'T'); }, dataRow: function (columns: any[]) { - columns = columns || [] - var buf = new BufferList() - buf.addInt16(columns.length) + columns = columns || []; + var buf = new BufferList(); + buf.addInt16(columns.length); columns.forEach(function (col) { if (col == null) { - buf.addInt32(-1) + buf.addInt32(-1); } else { - var strBuf = Buffer.from(col, 'utf8') - buf.addInt32(strBuf.length) - buf.add(strBuf) + var strBuf = Buffer.from(col, 'utf8'); + buf.addInt32(strBuf.length); + buf.add(strBuf); } - }) - return buf.join(true, 'D') + }); + return buf.join(true, 'D'); }, error: function (fields: any) { - return buffers.errorOrNotice(fields).join(true, 'E') + return buffers.errorOrNotice(fields).join(true, 'E'); }, notice: function (fields: any) { - return buffers.errorOrNotice(fields).join(true, 'N') + return buffers.errorOrNotice(fields).join(true, 'N'); }, errorOrNotice: function (fields: any) { - fields = fields || [] - var buf = new BufferList() + fields = fields || []; + var buf = new BufferList(); fields.forEach(function (field: any) { - buf.addChar(field.type) - buf.addCString(field.value) - }) - return buf.add(Buffer.from([0]))// terminator + buf.addChar(field.type); + buf.addCString(field.value); + }); + return buf.add(Buffer.from([0])); // terminator }, parseComplete: function () { - return new BufferList().join(true, '1') + return new BufferList().join(true, '1'); }, bindComplete: function () { - return new BufferList().join(true, '2') + return new BufferList().join(true, '2'); }, notification: function (id: number, channel: string, payload: string) { - return new BufferList() - .addInt32(id) - .addCString(channel) - .addCString(payload) - .join(true, 'A') + return new BufferList().addInt32(id).addCString(channel).addCString(payload).join(true, 'A'); }, emptyQuery: function () { - return new BufferList().join(true, 'I') + return new BufferList().join(true, 'I'); }, portalSuspended: function () { - return new BufferList().join(true, 's') + return new BufferList().join(true, 's'); }, closeComplete: function () { - return new BufferList().join(true, '3') + return new BufferList().join(true, '3'); }, copyIn: function (cols: number) { @@ -156,7 +129,7 @@ const buffers = { for (let i = 0; i < cols; i++) { list.addInt16(i); } - return list.join(true, 'G') + return list.join(true, 'G'); }, copyOut: function (cols: number) { @@ -168,7 +141,7 @@ const buffers = { for (let i = 0; i < cols; i++) { list.addInt16(i); } - return list.join(true, 'H') + return list.join(true, 'H'); }, copyData: function (bytes: Buffer) { @@ -176,8 +149,8 @@ const buffers = { }, copyDone: function () { - return new BufferList().join(true, 'c') - } -} + return new BufferList().join(true, 'c'); + }, +}; -export default buffers +export default buffers; diff --git a/packages/pg-protocol/src/types/chunky.d.ts b/packages/pg-protocol/src/types/chunky.d.ts index 7389bda66..914ce06b1 100644 --- a/packages/pg-protocol/src/types/chunky.d.ts +++ b/packages/pg-protocol/src/types/chunky.d.ts @@ -1 +1 @@ -declare module 'chunky' +declare module 'chunky'; diff --git a/packages/pg/Makefile b/packages/pg/Makefile index a5b0bc1da..e05edbf49 100644 --- a/packages/pg/Makefile +++ b/packages/pg/Makefile @@ -7,7 +7,7 @@ params := $(connectionString) node-command := xargs -n 1 -I file node file $(params) .PHONY : test test-connection test-integration bench test-native \ - lint publish test-missing-native update-npm + publish test-missing-native update-npm all: npm install @@ -17,7 +17,7 @@ help: test: test-unit -test-all: lint test-missing-native test-unit test-integration test-native +test-all: test-missing-native test-unit test-integration test-native update-npm: @@ -59,7 +59,3 @@ test-binary: test-connection test-pool: @find test/integration/connection-pool -name "*.js" | $(node-command) binary - -lint: - @echo "***Starting lint***" - node_modules/.bin/eslint lib diff --git a/yarn.lock b/yarn.lock index 812bf9158..60f2b1bca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -836,6 +836,11 @@ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.7.tgz#1c8c25cbf6e59ffa7d6b9652c78e547d9a41692d" integrity sha512-luq8meHGYwvky0O7u0eQZdA7B4Wd9owUCqvbw2m3XCrCU8mplYOujMBbvyS547AxJkC+pGnd0Cm15eNxEUNU8g== +"@types/eslint-visitor-keys@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" + integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== + "@types/events@*": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" @@ -890,6 +895,16 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" +"@typescript-eslint/parser@^2.27.0": + version "2.27.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.27.0.tgz#d91664335b2c46584294e42eb4ff35838c427287" + integrity sha512-HFUXZY+EdwrJXZo31DW4IS1ujQW3krzlRjBrFRrJcMDh0zCu107/nRfhk/uBasO8m0NVDbBF5WZKcIUMRO7vPg== + dependencies: + "@types/eslint-visitor-keys" "^1.0.0" + "@typescript-eslint/experimental-utils" "2.27.0" + "@typescript-eslint/typescript-estree" "2.27.0" + eslint-visitor-keys "^1.1.0" + "@typescript-eslint/typescript-estree@2.27.0": version "2.27.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.27.0.tgz#a288e54605412da8b81f1660b56c8b2e42966ce8" From c13cf81ee8d2dd7cdd4d0c134b4ada2ccc079c89 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 10 Apr 2020 10:47:57 -0500 Subject: [PATCH 0620/1037] Lint pg & turn off semicolons --- .eslintrc | 4 +- .prettierrc.json | 2 +- packages/pg-cursor/index.js | 206 +++++----- packages/pg-cursor/test/close.js | 74 ++-- packages/pg-cursor/test/error-handling.js | 130 +++---- packages/pg-cursor/test/index.js | 234 ++++++------ packages/pg-cursor/test/no-data-handling.js | 46 +-- packages/pg-cursor/test/pool.js | 116 +++--- packages/pg-cursor/test/query-config.js | 52 +-- packages/pg-cursor/test/transactions.js | 68 ++-- packages/pg-pool/index.js | 59 ++- .../pg-pool/test/bring-your-own-promise.js | 46 ++- packages/pg-pool/test/connection-strings.js | 5 +- packages/pg-pool/test/connection-timeout.js | 35 +- packages/pg-pool/test/ending.js | 32 +- packages/pg-pool/test/error-handling.js | 202 +++++----- packages/pg-pool/test/events.js | 8 +- packages/pg-pool/test/idle-timeout.js | 110 +++--- packages/pg-pool/test/index.js | 19 +- packages/pg-pool/test/max-uses.js | 133 ++++--- packages/pg-pool/test/setup.js | 4 +- packages/pg-pool/test/sizing.js | 78 ++-- packages/pg-pool/test/verify.js | 2 +- packages/pg-protocol/src/b.ts | 34 +- packages/pg-protocol/src/buffer-reader.ts | 48 +-- packages/pg-protocol/src/buffer-writer.ts | 88 ++--- .../pg-protocol/src/inbound-parser.test.ts | 328 ++++++++-------- packages/pg-protocol/src/index.ts | 14 +- packages/pg-protocol/src/messages.ts | 154 ++++---- .../src/outbound-serializer.test.ts | 212 +++++------ packages/pg-protocol/src/parser.ts | 306 +++++++-------- packages/pg-protocol/src/serializer.ts | 242 ++++++------ .../pg-protocol/src/testing/buffer-list.ts | 62 +-- .../pg-protocol/src/testing/test-buffers.ts | 100 ++--- packages/pg-protocol/src/types/chunky.d.ts | 2 +- packages/pg-query-stream/index.js | 40 +- .../pg-query-stream/test/async-iterator.js | 2 +- packages/pg-query-stream/test/close.js | 118 +++--- packages/pg-query-stream/test/concat.js | 30 +- packages/pg-query-stream/test/config.js | 24 +- packages/pg-query-stream/test/empty-query.js | 22 +- packages/pg-query-stream/test/error.js | 26 +- packages/pg-query-stream/test/fast-reader.js | 40 +- packages/pg-query-stream/test/helper.js | 20 +- packages/pg-query-stream/test/instant.js | 20 +- packages/pg-query-stream/test/issue-3.js | 50 +-- .../pg-query-stream/test/passing-options.js | 50 +-- packages/pg-query-stream/test/pauses.js | 26 +- packages/pg-query-stream/test/slow-reader.js | 32 +- .../test/stream-tester-timestamp.js | 34 +- .../pg-query-stream/test/stream-tester.js | 16 +- packages/pg/bench.js | 72 ++-- packages/pg/lib/client.js | 71 ++-- packages/pg/lib/connection-fast.js | 12 +- packages/pg/lib/connection-parameters.js | 8 +- packages/pg/lib/connection.js | 72 ++-- packages/pg/lib/defaults.js | 2 +- packages/pg/lib/index.js | 6 +- packages/pg/lib/native/client.js | 16 +- packages/pg/lib/native/query.js | 49 +-- packages/pg/lib/query.js | 68 ++-- packages/pg/lib/sasl.js | 64 ++-- packages/pg/lib/type-overrides.js | 11 +- packages/pg/lib/utils.js | 70 ++-- packages/pg/script/create-test-tables.js | 69 ++-- packages/pg/script/dump-db-types.js | 17 +- packages/pg/script/list-db-types.js | 11 +- packages/pg/test/buffer-list.js | 12 +- .../pg/test/integration/client/api-tests.js | 103 ++--- .../test/integration/client/appname-tests.js | 39 +- .../pg/test/integration/client/array-tests.js | 354 ++++++++++-------- .../client/big-simple-query-tests.js | 66 +++- .../integration/client/configuration-tests.js | 6 +- .../client/connection-timeout-tests.js | 30 +- .../integration/client/custom-types-tests.js | 30 +- .../integration/client/empty-query-tests.js | 2 +- .../client/error-handling-tests.js | 123 +++--- .../integration/client/huge-numeric-tests.js | 39 +- ...le_in_transaction_session_timeout-tests.js | 68 ++-- .../client/json-type-parsing-tests.js | 55 +-- .../client/multiple-results-tests.js | 83 ++-- .../client/network-partition-tests.js | 52 +-- .../test/integration/client/no-data-tests.js | 44 ++- .../integration/client/no-row-result-tests.js | 12 +- .../test/integration/client/notice-tests.js | 57 +-- .../integration/client/parse-int-8-tests.js | 46 ++- .../client/prepared-statement-tests.js | 119 +++--- .../integration/client/promise-api-tests.js | 48 ++- .../client/query-as-promise-tests.js | 21 +- .../client/query-column-names-tests.js | 21 +- ...error-handling-prepared-statement-tests.js | 151 +++++--- .../client/query-error-handling-tests.js | 185 +++++---- .../client/result-metadata-tests.js | 59 +-- .../client/results-as-array-tests.js | 29 +- .../row-description-on-results-tests.js | 36 +- .../integration/client/simple-query-tests.js | 16 +- .../pg/test/integration/client/ssl-tests.js | 20 +- .../client/statement_timeout-tests.js | 51 +-- .../integration/client/transaction-tests.js | 139 ++++--- .../integration/client/type-coercion-tests.js | 298 +++++++++------ .../client/type-parser-override-tests.js | 59 +-- .../connection-pool/error-tests.js | 178 +++++---- .../connection-pool/idle-timeout-tests.js | 12 +- .../connection-pool/native-instance-tests.js | 20 +- .../connection-pool/yield-support-tests.js | 31 +- .../connection/bound-command-tests.js | 4 +- .../test/integration/connection/copy-tests.js | 24 +- .../connection/dynamic-password-tests.js | 181 ++++----- .../integration/connection/test-helper.js | 8 +- packages/pg/test/integration/domain-tests.js | 47 ++- .../test/integration/gh-issues/130-tests.js | 9 +- .../test/integration/gh-issues/131-tests.js | 37 +- .../test/integration/gh-issues/1382-tests.js | 2 +- .../test/integration/gh-issues/1542-tests.js | 11 +- .../test/integration/gh-issues/1854-tests.js | 14 +- .../test/integration/gh-issues/199-tests.js | 3 +- .../test/integration/gh-issues/1992-tests.js | 3 +- .../test/integration/gh-issues/2056-tests.js | 8 +- .../test/integration/gh-issues/2064-tests.js | 19 +- .../test/integration/gh-issues/2079-tests.js | 7 +- .../test/integration/gh-issues/2085-tests.js | 16 +- .../test/integration/gh-issues/2108-tests.js | 2 +- .../test/integration/gh-issues/507-tests.js | 20 +- .../test/integration/gh-issues/600-tests.js | 86 +++-- .../test/integration/gh-issues/699-tests.js | 32 +- .../test/integration/gh-issues/787-tests.js | 5 +- .../test/integration/gh-issues/882-tests.js | 2 +- .../test/integration/gh-issues/981-tests.js | 21 +- packages/pg/test/integration/test-helper.js | 13 +- packages/pg/test/native/callback-api-tests.js | 25 +- packages/pg/test/native/evented-api-tests.js | 16 +- packages/pg/test/suite.js | 22 +- packages/pg/test/test-buffers.js | 53 +-- packages/pg/test/test-helper.js | 31 +- .../test/unit/client/configuration-tests.js | 6 +- .../unit/client/early-disconnect-tests.js | 8 +- packages/pg/test/unit/client/escape-tests.js | 58 ++- .../pg/test/unit/client/md5-password-tests.js | 5 +- .../unit/client/prepared-statement-tests.js | 28 +- .../pg/test/unit/client/query-queue-tests.js | 7 +- .../test/unit/client/result-metadata-tests.js | 13 +- .../pg/test/unit/client/sasl-scram-tests.js | 167 +++++---- .../test/unit/client/set-keepalives-tests.js | 6 +- .../pg/test/unit/client/simple-query-tests.js | 26 +- ...tream-and-query-error-interaction-tests.js | 17 +- packages/pg/test/unit/client/test-helper.js | 13 +- .../unit/client/throw-in-type-parser-tests.js | 10 +- .../connection-parameters/creation-tests.js | 162 ++++---- .../environment-variable-tests.js | 2 +- .../pg/test/unit/connection/error-tests.js | 16 +- .../unit/connection/inbound-parser-tests.js | 186 ++++----- .../unit/connection/outbound-sending-tests.js | 81 ++-- .../pg/test/unit/connection/startup-tests.js | 6 +- packages/pg/test/unit/test-helper.js | 14 +- packages/pg/test/unit/utils-tests.js | 30 +- 155 files changed, 4684 insertions(+), 4035 deletions(-) diff --git a/.eslintrc b/.eslintrc index 2840a3646..57948b711 100644 --- a/.eslintrc +++ b/.eslintrc @@ -9,9 +9,7 @@ ], "ignorePatterns": [ "node_modules", - "packages/pg", - "packages/pg-protocol/dist/**/*", - "packages/pg-pool" + "packages/pg-protocol/dist/**/*" ], "parserOptions": { "ecmaVersion": 2017, diff --git a/.prettierrc.json b/.prettierrc.json index 7e83b67a6..eb146cdce 100644 --- a/.prettierrc.json +++ b/.prettierrc.json @@ -1,5 +1,5 @@ { - "semi": true, + "semi": false, "printWidth": 120, "trailingComma": "es5", "singleQuote": true diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index 7c041322a..9d672dbff 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -1,53 +1,53 @@ -'use strict'; -const Result = require('pg/lib/result.js'); -const prepare = require('pg/lib/utils.js').prepareValue; -const EventEmitter = require('events').EventEmitter; -const util = require('util'); +'use strict' +const Result = require('pg/lib/result.js') +const prepare = require('pg/lib/utils.js').prepareValue +const EventEmitter = require('events').EventEmitter +const util = require('util') -let nextUniqueID = 1; // concept borrowed from org.postgresql.core.v3.QueryExecutorImpl +let nextUniqueID = 1 // concept borrowed from org.postgresql.core.v3.QueryExecutorImpl function Cursor(text, values, config) { - EventEmitter.call(this); - - this._conf = config || {}; - this.text = text; - this.values = values ? values.map(prepare) : null; - this.connection = null; - this._queue = []; - this.state = 'initialized'; - this._result = new Result(this._conf.rowMode, this._conf.types); - this._cb = null; - this._rows = null; - this._portal = null; - this._ifNoData = this._ifNoData.bind(this); - this._rowDescription = this._rowDescription.bind(this); + EventEmitter.call(this) + + this._conf = config || {} + this.text = text + this.values = values ? values.map(prepare) : null + this.connection = null + this._queue = [] + this.state = 'initialized' + this._result = new Result(this._conf.rowMode, this._conf.types) + this._cb = null + this._rows = null + this._portal = null + this._ifNoData = this._ifNoData.bind(this) + this._rowDescription = this._rowDescription.bind(this) } -util.inherits(Cursor, EventEmitter); +util.inherits(Cursor, EventEmitter) Cursor.prototype._ifNoData = function () { - this.state = 'idle'; - this._shiftQueue(); -}; + this.state = 'idle' + this._shiftQueue() +} Cursor.prototype._rowDescription = function () { if (this.connection) { - this.connection.removeListener('noData', this._ifNoData); + this.connection.removeListener('noData', this._ifNoData) } -}; +} Cursor.prototype.submit = function (connection) { - this.connection = connection; - this._portal = 'C_' + nextUniqueID++; + this.connection = connection + this._portal = 'C_' + nextUniqueID++ - const con = connection; + const con = connection con.parse( { text: this.text, }, true - ); + ) con.bind( { @@ -55,7 +55,7 @@ Cursor.prototype.submit = function (connection) { values: this.values, }, true - ); + ) con.describe( { @@ -63,156 +63,156 @@ Cursor.prototype.submit = function (connection) { name: this._portal, // AWS Redshift requires a portal name }, true - ); + ) - con.flush(); + con.flush() if (this._conf.types) { - this._result._getTypeParser = this._conf.types.getTypeParser; + this._result._getTypeParser = this._conf.types.getTypeParser } - con.once('noData', this._ifNoData); - con.once('rowDescription', this._rowDescription); -}; + con.once('noData', this._ifNoData) + con.once('rowDescription', this._rowDescription) +} Cursor.prototype._shiftQueue = function () { if (this._queue.length) { - this._getRows.apply(this, this._queue.shift()); + this._getRows.apply(this, this._queue.shift()) } -}; +} Cursor.prototype._closePortal = function () { // because we opened a named portal to stream results // we need to close the same named portal. Leaving a named portal // open can lock tables for modification if inside a transaction. // see https://github.com/brianc/node-pg-cursor/issues/56 - this.connection.close({ type: 'P', name: this._portal }); - this.connection.sync(); -}; + this.connection.close({ type: 'P', name: this._portal }) + this.connection.sync() +} Cursor.prototype.handleRowDescription = function (msg) { - this._result.addFields(msg.fields); - this.state = 'idle'; - this._shiftQueue(); -}; + this._result.addFields(msg.fields) + this.state = 'idle' + this._shiftQueue() +} Cursor.prototype.handleDataRow = function (msg) { - const row = this._result.parseRow(msg.fields); - this.emit('row', row, this._result); - this._rows.push(row); -}; + const row = this._result.parseRow(msg.fields) + this.emit('row', row, this._result) + this._rows.push(row) +} Cursor.prototype._sendRows = function () { - this.state = 'idle'; + this.state = 'idle' setImmediate(() => { - const cb = this._cb; + const cb = this._cb // remove callback before calling it // because likely a new one will be added // within the call to this callback - this._cb = null; + this._cb = null if (cb) { - this._result.rows = this._rows; - cb(null, this._rows, this._result); + this._result.rows = this._rows + cb(null, this._rows, this._result) } - this._rows = []; - }); -}; + this._rows = [] + }) +} Cursor.prototype.handleCommandComplete = function (msg) { - this._result.addCommandComplete(msg); - this._closePortal(); -}; + this._result.addCommandComplete(msg) + this._closePortal() +} Cursor.prototype.handlePortalSuspended = function () { - this._sendRows(); -}; + this._sendRows() +} Cursor.prototype.handleReadyForQuery = function () { - this._sendRows(); - this.state = 'done'; - this.emit('end', this._result); -}; + this._sendRows() + this.state = 'done' + this.emit('end', this._result) +} Cursor.prototype.handleEmptyQuery = function () { - this.connection.sync(); -}; + this.connection.sync() +} Cursor.prototype.handleError = function (msg) { - this.connection.removeListener('noData', this._ifNoData); - this.connection.removeListener('rowDescription', this._rowDescription); - this.state = 'error'; - this._error = msg; + this.connection.removeListener('noData', this._ifNoData) + this.connection.removeListener('rowDescription', this._rowDescription) + this.state = 'error' + this._error = msg // satisfy any waiting callback if (this._cb) { - this._cb(msg); + this._cb(msg) } // dispatch error to all waiting callbacks for (let i = 0; i < this._queue.length; i++) { - this._queue.pop()[1](msg); + this._queue.pop()[1](msg) } if (this.listenerCount('error') > 0) { // only dispatch error events if we have a listener - this.emit('error', msg); + this.emit('error', msg) } // call sync to keep this connection from hanging - this.connection.sync(); -}; + this.connection.sync() +} Cursor.prototype._getRows = function (rows, cb) { - this.state = 'busy'; - this._cb = cb; - this._rows = []; + this.state = 'busy' + this._cb = cb + this._rows = [] const msg = { portal: this._portal, rows: rows, - }; - this.connection.execute(msg, true); - this.connection.flush(); -}; + } + this.connection.execute(msg, true) + this.connection.flush() +} // users really shouldn't be calling 'end' here and terminating a connection to postgres // via the low level connection.end api Cursor.prototype.end = util.deprecate(function (cb) { if (this.state !== 'initialized') { - this.connection.sync(); + this.connection.sync() } - this.connection.once('end', cb); - this.connection.end(); -}, 'Cursor.end is deprecated. Call end on the client itself to end a connection to the database.'); + this.connection.once('end', cb) + this.connection.end() +}, 'Cursor.end is deprecated. Call end on the client itself to end a connection to the database.') Cursor.prototype.close = function (cb) { if (!this.connection || this.state === 'done') { if (cb) { - return setImmediate(cb); + return setImmediate(cb) } else { - return; + return } } - this._closePortal(); - this.state = 'done'; + this._closePortal() + this.state = 'done' if (cb) { this.connection.once('readyForQuery', function () { - cb(); - }); + cb() + }) } -}; +} Cursor.prototype.read = function (rows, cb) { if (this.state === 'idle') { - return this._getRows(rows, cb); + return this._getRows(rows, cb) } if (this.state === 'busy' || this.state === 'initialized') { - return this._queue.push([rows, cb]); + return this._queue.push([rows, cb]) } if (this.state === 'error') { - return setImmediate(() => cb(this._error)); + return setImmediate(() => cb(this._error)) } if (this.state === 'done') { - return setImmediate(() => cb(null, [])); + return setImmediate(() => cb(null, [])) } else { - throw new Error('Unknown state: ' + this.state); + throw new Error('Unknown state: ' + this.state) } -}; +} -module.exports = Cursor; +module.exports = Cursor diff --git a/packages/pg-cursor/test/close.js b/packages/pg-cursor/test/close.js index ec545265f..e63512abd 100644 --- a/packages/pg-cursor/test/close.js +++ b/packages/pg-cursor/test/close.js @@ -1,54 +1,54 @@ -const assert = require('assert'); -const Cursor = require('../'); -const pg = require('pg'); +const assert = require('assert') +const Cursor = require('../') +const pg = require('pg') -const text = 'SELECT generate_series as num FROM generate_series(0, 50)'; +const text = 'SELECT generate_series as num FROM generate_series(0, 50)' describe('close', function () { beforeEach(function (done) { - const client = (this.client = new pg.Client()); - client.connect(done); - }); + const client = (this.client = new pg.Client()) + client.connect(done) + }) this.afterEach(function (done) { - this.client.end(done); - }); + this.client.end(done) + }) it('can close a finished cursor without a callback', function (done) { - const cursor = new Cursor(text); - this.client.query(cursor); - this.client.query('SELECT NOW()', done); + const cursor = new Cursor(text) + this.client.query(cursor) + this.client.query('SELECT NOW()', done) cursor.read(100, function (err) { - assert.ifError(err); - cursor.close(); - }); - }); + assert.ifError(err) + cursor.close() + }) + }) it('closes cursor early', function (done) { - const cursor = new Cursor(text); - this.client.query(cursor); - this.client.query('SELECT NOW()', done); + const cursor = new Cursor(text) + this.client.query(cursor) + this.client.query('SELECT NOW()', done) cursor.read(25, function (err) { - assert.ifError(err); - cursor.close(); - }); - }); + assert.ifError(err) + cursor.close() + }) + }) it('works with callback style', function (done) { - const cursor = new Cursor(text); - const client = this.client; - client.query(cursor); + const cursor = new Cursor(text) + const client = this.client + client.query(cursor) cursor.read(25, function (err, rows) { - assert.ifError(err); - assert.strictEqual(rows.length, 25); + assert.ifError(err) + assert.strictEqual(rows.length, 25) cursor.close(function (err) { - assert.ifError(err); - client.query('SELECT NOW()', done); - }); - }); - }); + assert.ifError(err) + client.query('SELECT NOW()', done) + }) + }) + }) it('is a no-op to "close" the cursor before submitting it', function (done) { - const cursor = new Cursor(text); - cursor.close(done); - }); -}); + const cursor = new Cursor(text) + cursor.close(done) + }) +}) diff --git a/packages/pg-cursor/test/error-handling.js b/packages/pg-cursor/test/error-handling.js index 235dbed38..f6edef6d5 100644 --- a/packages/pg-cursor/test/error-handling.js +++ b/packages/pg-cursor/test/error-handling.js @@ -1,86 +1,86 @@ -'use strict'; -const assert = require('assert'); -const Cursor = require('../'); -const pg = require('pg'); +'use strict' +const assert = require('assert') +const Cursor = require('../') +const pg = require('pg') -const text = 'SELECT generate_series as num FROM generate_series(0, 4)'; +const text = 'SELECT generate_series as num FROM generate_series(0, 4)' describe('error handling', function () { it('can continue after error', function (done) { - const client = new pg.Client(); - client.connect(); - const cursor = client.query(new Cursor('asdfdffsdf')); + const client = new pg.Client() + client.connect() + const cursor = client.query(new Cursor('asdfdffsdf')) cursor.read(1, function (err) { - assert(err); + assert(err) client.query('SELECT NOW()', function (err) { - assert.ifError(err); - client.end(); - done(); - }); - }); - }); -}); + assert.ifError(err) + client.end() + done() + }) + }) + }) +}) describe('read callback does not fire sync', () => { it('does not fire error callback sync', (done) => { - const client = new pg.Client(); - client.connect(); - const cursor = client.query(new Cursor('asdfdffsdf')); - let after = false; + const client = new pg.Client() + client.connect() + const cursor = client.query(new Cursor('asdfdffsdf')) + let after = false cursor.read(1, function (err) { - assert(err, 'error should be returned'); - assert.strictEqual(after, true, 'should not call read sync'); - after = false; + assert(err, 'error should be returned') + assert.strictEqual(after, true, 'should not call read sync') + after = false cursor.read(1, function (err) { - assert(err, 'error should be returned'); - assert.strictEqual(after, true, 'should not call read sync'); - client.end(); - done(); - }); - after = true; - }); - after = true; - }); + assert(err, 'error should be returned') + assert.strictEqual(after, true, 'should not call read sync') + client.end() + done() + }) + after = true + }) + after = true + }) it('does not fire result sync after finished', (done) => { - const client = new pg.Client(); - client.connect(); - const cursor = client.query(new Cursor('SELECT NOW()')); - let after = false; + const client = new pg.Client() + client.connect() + const cursor = client.query(new Cursor('SELECT NOW()')) + let after = false cursor.read(1, function (err) { - assert(!err); - assert.strictEqual(after, true, 'should not call read sync'); + assert(!err) + assert.strictEqual(after, true, 'should not call read sync') cursor.read(1, function (err) { - assert(!err); - after = false; + assert(!err) + after = false cursor.read(1, function (err) { - assert(!err); - assert.strictEqual(after, true, 'should not call read sync'); - client.end(); - done(); - }); - after = true; - }); - }); - after = true; - }); -}); + assert(!err) + assert.strictEqual(after, true, 'should not call read sync') + client.end() + done() + }) + after = true + }) + }) + after = true + }) +}) describe('proper cleanup', function () { it('can issue multiple cursors on one client', function (done) { - const client = new pg.Client(); - client.connect(); - const cursor1 = client.query(new Cursor(text)); + const client = new pg.Client() + client.connect() + const cursor1 = client.query(new Cursor(text)) cursor1.read(8, function (err, rows) { - assert.ifError(err); - assert.strictEqual(rows.length, 5); - const cursor2 = client.query(new Cursor(text)); + assert.ifError(err) + assert.strictEqual(rows.length, 5) + const cursor2 = client.query(new Cursor(text)) cursor2.read(8, function (err, rows) { - assert.ifError(err); - assert.strictEqual(rows.length, 5); - client.end(); - done(); - }); - }); - }); -}); + assert.ifError(err) + assert.strictEqual(rows.length, 5) + client.end() + done() + }) + }) + }) +}) diff --git a/packages/pg-cursor/test/index.js b/packages/pg-cursor/test/index.js index 4193bfab6..24d3cfd79 100644 --- a/packages/pg-cursor/test/index.js +++ b/packages/pg-cursor/test/index.js @@ -1,181 +1,181 @@ -const assert = require('assert'); -const Cursor = require('../'); -const pg = require('pg'); +const assert = require('assert') +const Cursor = require('../') +const pg = require('pg') -const text = 'SELECT generate_series as num FROM generate_series(0, 5)'; +const text = 'SELECT generate_series as num FROM generate_series(0, 5)' describe('cursor', function () { beforeEach(function (done) { - const client = (this.client = new pg.Client()); - client.connect(done); + const client = (this.client = new pg.Client()) + client.connect(done) this.pgCursor = function (text, values) { - return client.query(new Cursor(text, values || [])); - }; - }); + return client.query(new Cursor(text, values || [])) + } + }) afterEach(function () { - this.client.end(); - }); + this.client.end() + }) it('fetch 6 when asking for 10', function (done) { - const cursor = this.pgCursor(text); + const cursor = this.pgCursor(text) cursor.read(10, function (err, res) { - assert.ifError(err); - assert.strictEqual(res.length, 6); - done(); - }); - }); + assert.ifError(err) + assert.strictEqual(res.length, 6) + done() + }) + }) it('end before reading to end', function (done) { - const cursor = this.pgCursor(text); + const cursor = this.pgCursor(text) cursor.read(3, function (err, res) { - assert.ifError(err); - assert.strictEqual(res.length, 3); - done(); - }); - }); + assert.ifError(err) + assert.strictEqual(res.length, 3) + done() + }) + }) it('callback with error', function (done) { - const cursor = this.pgCursor('select asdfasdf'); + const cursor = this.pgCursor('select asdfasdf') cursor.read(1, function (err) { - assert(err); - done(); - }); - }); + assert(err) + done() + }) + }) it('read a partial chunk of data', function (done) { - const cursor = this.pgCursor(text); + const cursor = this.pgCursor(text) cursor.read(2, function (err, res) { - assert.ifError(err); - assert.strictEqual(res.length, 2); + assert.ifError(err) + assert.strictEqual(res.length, 2) cursor.read(3, function (err, res) { - assert(!err); - assert.strictEqual(res.length, 3); + assert(!err) + assert.strictEqual(res.length, 3) cursor.read(1, function (err, res) { - assert(!err); - assert.strictEqual(res.length, 1); + assert(!err) + assert.strictEqual(res.length, 1) cursor.read(1, function (err, res) { - assert(!err); - assert.ifError(err); - assert.strictEqual(res.length, 0); - done(); - }); - }); - }); - }); - }); + assert(!err) + assert.ifError(err) + assert.strictEqual(res.length, 0) + done() + }) + }) + }) + }) + }) it('read return length 0 past the end', function (done) { - const cursor = this.pgCursor(text); + const cursor = this.pgCursor(text) cursor.read(2, function (err) { - assert(!err); + assert(!err) cursor.read(100, function (err, res) { - assert(!err); - assert.strictEqual(res.length, 4); + assert(!err) + assert.strictEqual(res.length, 4) cursor.read(100, function (err, res) { - assert(!err); - assert.strictEqual(res.length, 0); - done(); - }); - }); - }); - }); + assert(!err) + assert.strictEqual(res.length, 0) + done() + }) + }) + }) + }) it('read huge result', function (done) { - this.timeout(10000); - const text = 'SELECT generate_series as num FROM generate_series(0, 100000)'; - const values = []; - const cursor = this.pgCursor(text, values); - let count = 0; + this.timeout(10000) + const text = 'SELECT generate_series as num FROM generate_series(0, 100000)' + const values = [] + const cursor = this.pgCursor(text, values) + let count = 0 const read = function () { cursor.read(100, function (err, rows) { - if (err) return done(err); + if (err) return done(err) if (!rows.length) { - assert.strictEqual(count, 100001); - return done(); + assert.strictEqual(count, 100001) + return done() } - count += rows.length; + count += rows.length if (count % 10000 === 0) { // console.log(count) } - setImmediate(read); - }); - }; - read(); - }); + setImmediate(read) + }) + } + read() + }) it('normalizes parameter values', function (done) { - const text = 'SELECT $1::json me'; - const values = [{ name: 'brian' }]; - const cursor = this.pgCursor(text, values); + const text = 'SELECT $1::json me' + const values = [{ name: 'brian' }] + const cursor = this.pgCursor(text, values) cursor.read(1, function (err, rows) { - if (err) return done(err); - assert.strictEqual(rows[0].me.name, 'brian'); + if (err) return done(err) + assert.strictEqual(rows[0].me.name, 'brian') cursor.read(1, function (err, rows) { - assert(!err); - assert.strictEqual(rows.length, 0); - done(); - }); - }); - }); + assert(!err) + assert.strictEqual(rows.length, 0) + done() + }) + }) + }) it('returns result along with rows', function (done) { - const cursor = this.pgCursor(text); + const cursor = this.pgCursor(text) cursor.read(1, function (err, rows, result) { - assert.ifError(err); - assert.strictEqual(rows.length, 1); - assert.strictEqual(rows, result.rows); + assert.ifError(err) + assert.strictEqual(rows.length, 1) + assert.strictEqual(rows, result.rows) assert.deepStrictEqual( result.fields.map((f) => f.name), ['num'] - ); - done(); - }); - }); + ) + done() + }) + }) it('emits row events', function (done) { - const cursor = this.pgCursor(text); - cursor.read(10); - cursor.on('row', (row, result) => result.addRow(row)); + const cursor = this.pgCursor(text) + cursor.read(10) + cursor.on('row', (row, result) => result.addRow(row)) cursor.on('end', (result) => { - assert.strictEqual(result.rows.length, 6); - done(); - }); - }); + assert.strictEqual(result.rows.length, 6) + done() + }) + }) it('emits row events when cursor is closed manually', function (done) { - const cursor = this.pgCursor(text); - cursor.on('row', (row, result) => result.addRow(row)); + const cursor = this.pgCursor(text) + cursor.on('row', (row, result) => result.addRow(row)) cursor.on('end', (result) => { - assert.strictEqual(result.rows.length, 3); - done(); - }); + assert.strictEqual(result.rows.length, 3) + done() + }) - cursor.read(3, () => cursor.close()); - }); + cursor.read(3, () => cursor.close()) + }) it('emits error events', function (done) { - const cursor = this.pgCursor('select asdfasdf'); + const cursor = this.pgCursor('select asdfasdf') cursor.on('error', function (err) { - assert(err); - done(); - }); - }); + assert(err) + done() + }) + }) it('returns rowCount on insert', function (done) { - const pgCursor = this.pgCursor; + const pgCursor = this.pgCursor this.client .query('CREATE TEMPORARY TABLE pg_cursor_test (foo VARCHAR(1), bar VARCHAR(1))') .then(function () { - const cursor = pgCursor('insert into pg_cursor_test values($1, $2)', ['a', 'b']); + const cursor = pgCursor('insert into pg_cursor_test values($1, $2)', ['a', 'b']) cursor.read(1, function (err, rows, result) { - assert.ifError(err); - assert.strictEqual(rows.length, 0); - assert.strictEqual(result.rowCount, 1); - done(); - }); + assert.ifError(err) + assert.strictEqual(rows.length, 0) + assert.strictEqual(result.rowCount, 1) + done() + }) }) - .catch(done); - }); -}); + .catch(done) + }) +}) diff --git a/packages/pg-cursor/test/no-data-handling.js b/packages/pg-cursor/test/no-data-handling.js index a25f83328..9c860b9cd 100644 --- a/packages/pg-cursor/test/no-data-handling.js +++ b/packages/pg-cursor/test/no-data-handling.js @@ -1,34 +1,34 @@ -const assert = require('assert'); -const pg = require('pg'); -const Cursor = require('../'); +const assert = require('assert') +const pg = require('pg') +const Cursor = require('../') describe('queries with no data', function () { beforeEach(function (done) { - const client = (this.client = new pg.Client()); - client.connect(done); - }); + const client = (this.client = new pg.Client()) + client.connect(done) + }) afterEach(function () { - this.client.end(); - }); + this.client.end() + }) it('handles queries that return no data', function (done) { - const cursor = new Cursor('CREATE TEMPORARY TABLE whatwhat (thing int)'); - this.client.query(cursor); + const cursor = new Cursor('CREATE TEMPORARY TABLE whatwhat (thing int)') + this.client.query(cursor) cursor.read(100, function (err, rows) { - assert.ifError(err); - assert.strictEqual(rows.length, 0); - done(); - }); - }); + assert.ifError(err) + assert.strictEqual(rows.length, 0) + done() + }) + }) it('handles empty query', function (done) { - let cursor = new Cursor('-- this is a comment'); - cursor = this.client.query(cursor); + let cursor = new Cursor('-- this is a comment') + cursor = this.client.query(cursor) cursor.read(100, function (err, rows) { - assert.ifError(err); - assert.strictEqual(rows.length, 0); - done(); - }); - }); -}); + assert.ifError(err) + assert.strictEqual(rows.length, 0) + done() + }) + }) +}) diff --git a/packages/pg-cursor/test/pool.js b/packages/pg-cursor/test/pool.js index 74ad19919..9d8ca772f 100644 --- a/packages/pg-cursor/test/pool.js +++ b/packages/pg-cursor/test/pool.js @@ -1,107 +1,107 @@ -'use strict'; -const assert = require('assert'); -const Cursor = require('../'); -const pg = require('pg'); +'use strict' +const assert = require('assert') +const Cursor = require('../') +const pg = require('pg') -const text = 'SELECT generate_series as num FROM generate_series(0, 50)'; +const text = 'SELECT generate_series as num FROM generate_series(0, 50)' function poolQueryPromise(pool, readRowCount) { return new Promise((resolve, reject) => { pool.connect((err, client, done) => { if (err) { - done(err); - return reject(err); + done(err) + return reject(err) } - const cursor = client.query(new Cursor(text)); + const cursor = client.query(new Cursor(text)) cursor.read(readRowCount, (err) => { if (err) { - done(err); - return reject(err); + done(err) + return reject(err) } cursor.close((err) => { if (err) { - done(err); - return reject(err); + done(err) + return reject(err) } - done(); - resolve(); - }); - }); - }); - }); + done() + resolve() + }) + }) + }) + }) } describe('pool', function () { beforeEach(function () { - this.pool = new pg.Pool({ max: 1 }); - }); + this.pool = new pg.Pool({ max: 1 }) + }) afterEach(function () { - this.pool.end(); - }); + this.pool.end() + }) it('closes cursor early, single pool query', function (done) { poolQueryPromise(this.pool, 25) .then(() => done()) .catch((err) => { - assert.ifError(err); - done(); - }); - }); + assert.ifError(err) + done() + }) + }) it('closes cursor early, saturated pool', function (done) { - const promises = []; + const promises = [] for (let i = 0; i < 10; i++) { - promises.push(poolQueryPromise(this.pool, 25)); + promises.push(poolQueryPromise(this.pool, 25)) } Promise.all(promises) .then(() => done()) .catch((err) => { - assert.ifError(err); - done(); - }); - }); + assert.ifError(err) + done() + }) + }) it('closes exhausted cursor, single pool query', function (done) { poolQueryPromise(this.pool, 100) .then(() => done()) .catch((err) => { - assert.ifError(err); - done(); - }); - }); + assert.ifError(err) + done() + }) + }) it('closes exhausted cursor, saturated pool', function (done) { - const promises = []; + const promises = [] for (let i = 0; i < 10; i++) { - promises.push(poolQueryPromise(this.pool, 100)); + promises.push(poolQueryPromise(this.pool, 100)) } Promise.all(promises) .then(() => done()) .catch((err) => { - assert.ifError(err); - done(); - }); - }); + assert.ifError(err) + done() + }) + }) it('can close multiple times on a pool', async function () { - const pool = new pg.Pool({ max: 1 }); + const pool = new pg.Pool({ max: 1 }) const run = async () => { - const cursor = new Cursor(text); - const client = await pool.connect(); - client.query(cursor); + const cursor = new Cursor(text) + const client = await pool.connect() + client.query(cursor) await new Promise((resolve) => { cursor.read(25, function (err) { - assert.ifError(err); + assert.ifError(err) cursor.close(function (err) { - assert.ifError(err); - client.release(); - resolve(); - }); - }); - }); - }; - await Promise.all([run(), run(), run()]); - await pool.end(); - }); -}); + assert.ifError(err) + client.release() + resolve() + }) + }) + }) + } + await Promise.all([run(), run(), run()]) + await pool.end() + }) +}) diff --git a/packages/pg-cursor/test/query-config.js b/packages/pg-cursor/test/query-config.js index b97cbbc26..855af305c 100644 --- a/packages/pg-cursor/test/query-config.js +++ b/packages/pg-cursor/test/query-config.js @@ -1,35 +1,35 @@ -'use strict'; -const assert = require('assert'); -const Cursor = require('../'); -const pg = require('pg'); +'use strict' +const assert = require('assert') +const Cursor = require('../') +const pg = require('pg') describe('query config passed to result', () => { it('passes rowMode to result', (done) => { - const client = new pg.Client(); - client.connect(); - const text = 'SELECT generate_series as num FROM generate_series(0, 5)'; - const cursor = client.query(new Cursor(text, null, { rowMode: 'array' })); + const client = new pg.Client() + client.connect() + const text = 'SELECT generate_series as num FROM generate_series(0, 5)' + const cursor = client.query(new Cursor(text, null, { rowMode: 'array' })) cursor.read(10, (err, rows) => { - assert(!err); - assert.deepStrictEqual(rows, [[0], [1], [2], [3], [4], [5]]); - client.end(); - done(); - }); - }); + assert(!err) + assert.deepStrictEqual(rows, [[0], [1], [2], [3], [4], [5]]) + client.end() + done() + }) + }) it('passes types to result', (done) => { - const client = new pg.Client(); - client.connect(); - const text = 'SELECT generate_series as num FROM generate_series(0, 2)'; + const client = new pg.Client() + client.connect() + const text = 'SELECT generate_series as num FROM generate_series(0, 2)' const types = { getTypeParser: () => () => 'foo', - }; - const cursor = client.query(new Cursor(text, null, { types })); + } + const cursor = client.query(new Cursor(text, null, { types })) cursor.read(10, (err, rows) => { - assert(!err); - assert.deepStrictEqual(rows, [{ num: 'foo' }, { num: 'foo' }, { num: 'foo' }]); - client.end(); - done(); - }); - }); -}); + assert(!err) + assert.deepStrictEqual(rows, [{ num: 'foo' }, { num: 'foo' }, { num: 'foo' }]) + client.end() + done() + }) + }) +}) diff --git a/packages/pg-cursor/test/transactions.js b/packages/pg-cursor/test/transactions.js index 08a605d9b..37ca7db64 100644 --- a/packages/pg-cursor/test/transactions.js +++ b/packages/pg-cursor/test/transactions.js @@ -1,43 +1,43 @@ -const assert = require('assert'); -const Cursor = require('../'); -const pg = require('pg'); +const assert = require('assert') +const Cursor = require('../') +const pg = require('pg') describe('transactions', () => { it('can execute multiple statements in a transaction', async () => { - const client = new pg.Client(); - await client.connect(); - await client.query('begin'); - await client.query('CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)'); - const cursor = client.query(new Cursor('SELECT * FROM foobar')); + const client = new pg.Client() + await client.connect() + await client.query('begin') + await client.query('CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)') + const cursor = client.query(new Cursor('SELECT * FROM foobar')) const rows = await new Promise((resolve, reject) => { - cursor.read(10, (err, rows) => (err ? reject(err) : resolve(rows))); - }); - assert.strictEqual(rows.length, 0); - await client.query('ALTER TABLE foobar ADD COLUMN name TEXT'); - await client.end(); - }); + cursor.read(10, (err, rows) => (err ? reject(err) : resolve(rows))) + }) + assert.strictEqual(rows.length, 0) + await client.query('ALTER TABLE foobar ADD COLUMN name TEXT') + await client.end() + }) it('can execute multiple statements in a transaction if ending cursor early', async () => { - const client = new pg.Client(); - await client.connect(); - await client.query('begin'); - await client.query('CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)'); - const cursor = client.query(new Cursor('SELECT * FROM foobar')); - await new Promise((resolve) => cursor.close(resolve)); - await client.query('ALTER TABLE foobar ADD COLUMN name TEXT'); - await client.end(); - }); + const client = new pg.Client() + await client.connect() + await client.query('begin') + await client.query('CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)') + const cursor = client.query(new Cursor('SELECT * FROM foobar')) + await new Promise((resolve) => cursor.close(resolve)) + await client.query('ALTER TABLE foobar ADD COLUMN name TEXT') + await client.end() + }) it('can execute multiple statements in a transaction if no data', async () => { - const client = new pg.Client(); - await client.connect(); - await client.query('begin'); + const client = new pg.Client() + await client.connect() + await client.query('begin') // create a cursor that has no data response - const createText = 'CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)'; - const cursor = client.query(new Cursor(createText)); - const err = await new Promise((resolve) => cursor.read(100, resolve)); - assert.ifError(err); - await client.query('ALTER TABLE foobar ADD COLUMN name TEXT'); - await client.end(); - }); -}); + const createText = 'CREATE TEMP TABLE foobar(id SERIAL PRIMARY KEY)' + const cursor = client.query(new Cursor(createText)) + const err = await new Promise((resolve) => cursor.read(100, resolve)) + assert.ifError(err) + await client.query('ALTER TABLE foobar ADD COLUMN name TEXT') + await client.end() + }) +}) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 32a4736d7..27875c1f8 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -1,18 +1,16 @@ 'use strict' const EventEmitter = require('events').EventEmitter -const NOOP = function () { } +const NOOP = function () {} const removeWhere = (list, predicate) => { const i = list.findIndex(predicate) - return i === -1 - ? undefined - : list.splice(i, 1)[0] + return i === -1 ? undefined : list.splice(i, 1)[0] } class IdleItem { - constructor (client, idleListener, timeoutId) { + constructor(client, idleListener, timeoutId) { this.client = client this.idleListener = idleListener this.timeoutId = timeoutId @@ -20,16 +18,16 @@ class IdleItem { } class PendingItem { - constructor (callback) { + constructor(callback) { this.callback = callback } } -function throwOnDoubleRelease () { +function throwOnDoubleRelease() { throw new Error('Release called on client which has already been released to the pool.') } -function promisify (Promise, callback) { +function promisify(Promise, callback) { if (callback) { return { callback: callback, result: undefined } } @@ -45,8 +43,8 @@ function promisify (Promise, callback) { return { callback: cb, result: result } } -function makeIdleListener (pool, client) { - return function idleListener (err) { +function makeIdleListener(pool, client) { + return function idleListener(err) { err.client = client client.removeListener('error', idleListener) @@ -61,7 +59,7 @@ function makeIdleListener (pool, client) { } class Pool extends EventEmitter { - constructor (options, Client) { + constructor(options, Client) { super() this.options = Object.assign({}, options) @@ -72,13 +70,13 @@ class Pool extends EventEmitter { configurable: true, enumerable: false, writable: true, - value: options.password + value: options.password, }) } this.options.max = this.options.max || this.options.poolSize || 10 this.options.maxUses = this.options.maxUses || Infinity - this.log = this.options.log || function () { } + this.log = this.options.log || function () {} this.Client = this.options.Client || Client || require('pg').Client this.Promise = this.options.Promise || global.Promise @@ -94,11 +92,11 @@ class Pool extends EventEmitter { this.ended = false } - _isFull () { + _isFull() { return this._clients.length >= this.options.max } - _pulseQueue () { + _pulseQueue() { this.log('pulse queue') if (this.ended) { this.log('pulse queue ended') @@ -107,7 +105,7 @@ class Pool extends EventEmitter { if (this.ending) { this.log('pulse queue on ending') if (this._idle.length) { - this._idle.slice().map(item => { + this._idle.slice().map((item) => { this._remove(item.client) }) } @@ -141,22 +139,19 @@ class Pool extends EventEmitter { throw new Error('unexpected condition') } - _remove (client) { - const removed = removeWhere( - this._idle, - item => item.client === client - ) + _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) + this._clients = this._clients.filter((c) => c !== client) client.end() this.emit('remove', client) } - connect (cb) { + 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) @@ -202,7 +197,7 @@ class Pool extends EventEmitter { return result } - newClient (pendingItem) { + newClient(pendingItem) { const client = new this.Client(this.options) this._clients.push(client) const idleListener = makeIdleListener(this, client) @@ -230,7 +225,7 @@ class Pool extends EventEmitter { if (err) { this.log('client failed to connect', err) // remove the dead client from our list of clients - this._clients = this._clients.filter(c => c !== client) + this._clients = this._clients.filter((c) => c !== client) if (timeoutHit) { err.message = 'Connection terminated due to connection timeout' } @@ -250,7 +245,7 @@ class Pool extends EventEmitter { } // acquire a client for a pending work item - _acquireClient (client, pendingItem, idleListener, isNew) { + _acquireClient(client, pendingItem, idleListener, isNew) { if (isNew) { this.emit('connect', client) } @@ -294,7 +289,7 @@ class Pool extends EventEmitter { // release a client back to the poll, include an error // to remove it from the pool - _release (client, idleListener, err) { + _release(client, idleListener, err) { client.on('error', idleListener) client._poolUseCount = (client._poolUseCount || 0) + 1 @@ -322,7 +317,7 @@ class Pool extends EventEmitter { this._pulseQueue() } - query (text, values, cb) { + query(text, values, cb) { // guard clause against passing a function as the first parameter if (typeof text === 'function') { const response = promisify(this.Promise, text) @@ -375,7 +370,7 @@ class Pool extends EventEmitter { return response.result } - end (cb) { + end(cb) { this.log('ending') if (this.ending) { const err = new Error('Called end on pool more than once') @@ -388,15 +383,15 @@ class Pool extends EventEmitter { return promised.result } - get waitingCount () { + get waitingCount() { return this._pendingQueue.length } - get idleCount () { + get idleCount() { return this._idle.length } - get totalCount () { + get totalCount() { return this._clients.length } } diff --git a/packages/pg-pool/test/bring-your-own-promise.js b/packages/pg-pool/test/bring-your-own-promise.js index f7fe3bde9..e905ccc0b 100644 --- a/packages/pg-pool/test/bring-your-own-promise.js +++ b/packages/pg-pool/test/bring-your-own-promise.js @@ -8,29 +8,35 @@ const BluebirdPromise = require('bluebird') const Pool = require('../') -const checkType = promise => { +const checkType = (promise) => { expect(promise).to.be.a(BluebirdPromise) - return promise.catch(e => undefined) + 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 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()) - })) + 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()) + }) + ) }) diff --git a/packages/pg-pool/test/connection-strings.js b/packages/pg-pool/test/connection-strings.js index 7013f28da..de45830dc 100644 --- a/packages/pg-pool/test/connection-strings.js +++ b/packages/pg-pool/test/connection-strings.js @@ -15,10 +15,10 @@ describe('Connection strings', function () { connect: function (cb) { cb(new Error('testing')) }, - on: function () { } + on: function () {}, } }, - connectionString: connectionString + connectionString: connectionString, }) pool.connect(function (err, client) { @@ -27,4 +27,3 @@ describe('Connection strings', function () { }) }) }) - diff --git a/packages/pg-pool/test/connection-timeout.js b/packages/pg-pool/test/connection-timeout.js index 970785209..05e8931df 100644 --- a/packages/pg-pool/test/connection-timeout.js +++ b/packages/pg-pool/test/connection-timeout.js @@ -43,7 +43,7 @@ describe('connection timeout', () => { it('should reject promise with an error if timeout is passed', (done) => { const pool = new Pool({ connectionTimeoutMillis: 10, port: this.port, host: 'localhost' }) - pool.connect().catch(err => { + pool.connect().catch((err) => { expect(err).to.be.an(Error) expect(err.message).to.contain('timeout') expect(pool.idleCount).to.equal(0) @@ -51,18 +51,23 @@ describe('connection timeout', () => { }) }) - it('should handle multiple timeouts', co.wrap(function* () { - const errors = [] - const pool = new Pool({ connectionTimeoutMillis: 1, port: this.port, host: 'localhost' }) - 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 handle multiple timeouts', + co.wrap( + function* () { + const errors = [] + const pool = new Pool({ connectionTimeoutMillis: 1, port: this.port, host: 'localhost' }) + 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 }) @@ -153,7 +158,7 @@ describe('connection timeout', () => { const pool = new Pool({ Client: Client, connectionTimeoutMillis: 1000, - max: 1 + max: 1, }) pool.connect((err, client, release) => { @@ -199,7 +204,7 @@ describe('connection timeout', () => { const pool = new Pool({ Client: Client, connectionTimeoutMillis: 1000, - max: 1 + max: 1, }) // Direct connect diff --git a/packages/pg-pool/test/ending.js b/packages/pg-pool/test/ending.js index 1956b13f6..e1839b46c 100644 --- a/packages/pg-pool/test/ending.js +++ b/packages/pg-pool/test/ending.js @@ -17,18 +17,24 @@ describe('pool ending', () => { 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( + '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') - })) + 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') + }) + ) }) diff --git a/packages/pg-pool/test/error-handling.js b/packages/pg-pool/test/error-handling.js index 90de4ec41..fea1d1148 100644 --- a/packages/pg-pool/test/error-handling.js +++ b/packages/pg-pool/test/error-handling.js @@ -16,12 +16,15 @@ describe('pool error handling', function () { 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) - }) + pool + .query("SELECT 'asd'+1 ") + .then(function (res) { + reject(res) // this should always error + }) + .catch(function (err) { + errors++ + resolve(err) + }) }) } const ps = [] @@ -35,14 +38,17 @@ describe('pool error handling', function () { }) 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() - })) + 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() + }) + ) it('should throw each time with callbacks', function (done) { const pool = new Pool() @@ -75,17 +81,16 @@ describe('pool error handling', function () { 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() - }) + 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) => { @@ -106,68 +111,74 @@ describe('pool error handling', function () { }) 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(() => { - let poolError - pool.once('error', (err) => { - poolError = err - }) + 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(() => { + let poolError + pool.once('error', (err) => { + poolError = err + }) - let clientError - client.once('error', (err) => { - clientError = err - }) + let clientError + client.once('error', (err) => { + clientError = err + }) - client.emit('error', new Error('expected')) + client.emit('error', new Error('expected')) - expect(clientError.message).to.equal('expected') - expect(poolError.message).to.equal('expected') - expect(pool.idleCount).to.equal(0) - expect(pool.totalCount).to.equal(0) - pool.end().then(resolve, reject) + expect(clientError.message).to.equal('expected') + expect(poolError.message).to.equal('expected') + expect(pool.idleCount).to.equal(0) + expect(pool.totalCount).to.equal(0) + pool.end().then(resolve, reject) + }) }) }) - })) + ) }) describe('error from in-use client', () => { - it('keeps the client in the 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) - - yield new Promise((resolve, reject) => { - process.nextTick(() => { - let poolError - pool.once('error', (err) => { - poolError = err - }) + it( + 'keeps the client in the 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) - let clientError - client.once('error', (err) => { - clientError = err - }) + yield new Promise((resolve, reject) => { + process.nextTick(() => { + let poolError + pool.once('error', (err) => { + poolError = err + }) - client.emit('error', new Error('expected')) + let clientError + client.once('error', (err) => { + clientError = err + }) + + client.emit('error', new Error('expected')) - expect(clientError.message).to.equal('expected') - expect(poolError).not.to.be.ok() - expect(pool.idleCount).to.equal(0) - expect(pool.totalCount).to.equal(1) - client.release() - pool.end().then(resolve, reject) + expect(clientError.message).to.equal('expected') + expect(poolError).not.to.be.ok() + expect(pool.idleCount).to.equal(0) + expect(pool.totalCount).to.equal(1) + client.release() + pool.end().then(resolve, reject) + }) }) }) - })) + ) }) describe('passing a function to pool.query', () => { @@ -182,30 +193,35 @@ describe('pool error handling', function () { }) 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) + 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() - })) + 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() + }) + ) }) it('should continue with queued items after a connection failure', (done) => { - const closeServer = net.createServer((socket) => { - socket.destroy() - }).unref() + const closeServer = net + .createServer((socket) => { + socket.destroy() + }) + .unref() closeServer.listen(() => { const pool = new Pool({ max: 1, port: closeServer.address().port, host: 'localhost' }) diff --git a/packages/pg-pool/test/events.js b/packages/pg-pool/test/events.js index a2da48100..61979247d 100644 --- a/packages/pg-pool/test/events.js +++ b/packages/pg-pool/test/events.js @@ -31,13 +31,13 @@ describe('events', function () { process.nextTick(() => { cb(new Error('bad news')) }) - } - }) + }, + }), }) pool.on('connect', function () { throw new Error('should never get here') }) - return pool.connect().catch(e => expect(e.message).to.equal('bad news')) + return pool.connect().catch((e) => expect(e.message).to.equal('bad news')) }) it('emits acquire every time a client is acquired', function (done) { @@ -77,7 +77,7 @@ describe('events', function () { }) }) -function mockClient (methods) { +function mockClient(methods) { return function () { const client = new EventEmitter() Object.assign(client, methods) diff --git a/packages/pg-pool/test/idle-timeout.js b/packages/pg-pool/test/idle-timeout.js index a24ab7b06..fd9fba4a4 100644 --- a/packages/pg-pool/test/idle-timeout.js +++ b/packages/pg-pool/test/idle-timeout.js @@ -7,7 +7,7 @@ const it = require('mocha').it const Pool = require('../') -const wait = time => new Promise((resolve) => setTimeout(resolve, time)) +const wait = (time) => new Promise((resolve) => setTimeout(resolve, time)) describe('idle timeout', () => { it('should timeout and remove the client', (done) => { @@ -20,60 +20,68 @@ describe('idle timeout', () => { }) }) - 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()) + 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 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'))) + const timeout = wait(100).then(() => Promise.reject(new Error('Idle timeout failed to occur'))) - try { - yield Promise.race([removal, timeout]) - } finally { - pool.end() - } - })) + 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( + '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() - })) + 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() + }) + ) }) diff --git a/packages/pg-pool/test/index.js b/packages/pg-pool/test/index.js index 010d99c56..57a68e01e 100644 --- a/packages/pg-pool/test/index.js +++ b/packages/pg-pool/test/index.js @@ -167,13 +167,11 @@ describe('pool', function () { 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() - }) + 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 () { @@ -210,10 +208,9 @@ describe('pool', function () { const errors = [] const promises = _.times(30, () => { - return pool.query('SELECT asldkfjasldkf') - .catch(function (e) { - errors.push(e) - }) + return pool.query('SELECT asldkfjasldkf').catch(function (e) { + errors.push(e) + }) }) return Promise.all(promises).then(() => { expect(errors).to.have.length(30) diff --git a/packages/pg-pool/test/max-uses.js b/packages/pg-pool/test/max-uses.js index 2abede31e..c94ddec6b 100644 --- a/packages/pg-pool/test/max-uses.js +++ b/packages/pg-pool/test/max-uses.js @@ -8,78 +8,91 @@ const it = require('mocha').it const Pool = require('../') describe('maxUses', () => { - it('can create a single client and use it once', co.wrap(function * () { - const pool = new Pool({ maxUses: 2 }) - 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 once', + co.wrap(function* () { + const pool = new Pool({ maxUses: 2 }) + 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('getting a connection a second time returns the same connection and releasing it also closes it', co.wrap(function * () { - const pool = new Pool({ maxUses: 2 }) - expect(pool.waitingCount).to.equal(0) - const client = yield pool.connect() - client.release() - const client2 = yield pool.connect() - expect(client).to.equal(client2) - expect(client2._ending).to.equal(false) - client2.release() - expect(client2._ending).to.equal(true) - return yield pool.end() - })) + it( + 'getting a connection a second time returns the same connection and releasing it also closes it', + co.wrap(function* () { + const pool = new Pool({ maxUses: 2 }) + expect(pool.waitingCount).to.equal(0) + const client = yield pool.connect() + client.release() + const client2 = yield pool.connect() + expect(client).to.equal(client2) + expect(client2._ending).to.equal(false) + client2.release() + expect(client2._ending).to.equal(true) + return yield pool.end() + }) + ) - it('getting a connection a third time returns a new connection', co.wrap(function * () { - const pool = new Pool({ maxUses: 2 }) - expect(pool.waitingCount).to.equal(0) - const client = yield pool.connect() - client.release() - const client2 = yield pool.connect() - expect(client).to.equal(client2) - client2.release() - const client3 = yield pool.connect() - expect(client3).not.to.equal(client2) - client3.release() - return yield pool.end() - })) + it( + 'getting a connection a third time returns a new connection', + co.wrap(function* () { + const pool = new Pool({ maxUses: 2 }) + expect(pool.waitingCount).to.equal(0) + const client = yield pool.connect() + client.release() + const client2 = yield pool.connect() + expect(client).to.equal(client2) + client2.release() + const client3 = yield pool.connect() + expect(client3).not.to.equal(client2) + client3.release() + return yield pool.end() + }) + ) - it('getting a connection from a pending request gets a fresh client when the released candidate is expended', co.wrap(function * () { - const pool = new Pool({ max: 1, maxUses: 2 }) - expect(pool.waitingCount).to.equal(0) - const client1 = yield pool.connect() - pool.connect() - .then(client2 => { + it( + 'getting a connection from a pending request gets a fresh client when the released candidate is expended', + co.wrap(function* () { + const pool = new Pool({ max: 1, maxUses: 2 }) + expect(pool.waitingCount).to.equal(0) + const client1 = yield pool.connect() + pool.connect().then((client2) => { expect(client2).to.equal(client1) expect(pool.waitingCount).to.equal(1) // Releasing the client this time should also expend it since maxUses is 2, causing client3 to be a fresh client client2.release() }) - const client3Promise = pool.connect() - .then(client3 => { + const client3Promise = pool.connect().then((client3) => { // client3 should be a fresh client since client2's release caused the first client to be expended expect(pool.waitingCount).to.equal(0) expect(client3).not.to.equal(client1) return client3.release() }) - // There should be two pending requests since we have 3 connect requests but a max size of 1 - expect(pool.waitingCount).to.equal(2) - // Releasing the client should not yet expend it since maxUses is 2 - client1.release() - yield client3Promise - return yield pool.end() - })) + // There should be two pending requests since we have 3 connect requests but a max size of 1 + expect(pool.waitingCount).to.equal(2) + // Releasing the client should not yet expend it since maxUses is 2 + client1.release() + yield client3Promise + return yield pool.end() + }) + ) - it('logs when removing an expended client', co.wrap(function * () { - const messages = [] - const log = function (msg) { - messages.push(msg) - } - const pool = new Pool({ maxUses: 1, log }) - const client = yield pool.connect() - client.release() - expect(messages).to.contain('remove expended client') - return yield pool.end() - })) + it( + 'logs when removing an expended client', + co.wrap(function* () { + const messages = [] + const log = function (msg) { + messages.push(msg) + } + const pool = new Pool({ maxUses: 1, log }) + const client = yield pool.connect() + client.release() + expect(messages).to.contain('remove expended client') + return yield pool.end() + }) + ) }) diff --git a/packages/pg-pool/test/setup.js b/packages/pg-pool/test/setup.js index cf75b7a67..811e956d4 100644 --- a/packages/pg-pool/test/setup.js +++ b/packages/pg-pool/test/setup.js @@ -1,5 +1,5 @@ -const crash = reason => { - process.on(reason, err => { +const crash = (reason) => { + process.on(reason, (err) => { console.error(reason, err.stack) process.exit(-1) }) diff --git a/packages/pg-pool/test/sizing.js b/packages/pg-pool/test/sizing.js index b310b3d35..e7863ba07 100644 --- a/packages/pg-pool/test/sizing.js +++ b/packages/pg-pool/test/sizing.js @@ -8,43 +8,51 @@ 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 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 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 }) + it( + 'can only send 1 query at a time', + co.wrap(function* () { + const pool = new Pool({ max: 1 }) - // the query text column name changed in PostgreSQL 9.2 - const versionResult = yield pool.query('SHOW server_version_num') - const version = parseInt(versionResult.rows[0].server_version_num, 10) - const queryColumn = version < 90200 ? 'current_query' : 'query' + // the query text column name changed in PostgreSQL 9.2 + const versionResult = yield pool.query('SHOW server_version_num') + const version = parseInt(versionResult.rows[0].server_version_num, 10) + const queryColumn = version < 90200 ? 'current_query' : 'query' - const queryText = 'SELECT COUNT(*) as counts FROM pg_stat_activity WHERE ' + queryColumn + ' = $1' - const queries = _.times(20, () => - pool.query(queryText, [queryText])) - 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() - })) + const queryText = 'SELECT COUNT(*) as counts FROM pg_stat_activity WHERE ' + queryColumn + ' = $1' + const queries = _.times(20, () => pool.query(queryText, [queryText])) + 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() + }) + ) }) diff --git a/packages/pg-pool/test/verify.js b/packages/pg-pool/test/verify.js index 667dea9ff..e7ae1dd88 100644 --- a/packages/pg-pool/test/verify.js +++ b/packages/pg-pool/test/verify.js @@ -12,7 +12,7 @@ describe('verify', () => { verify: (client, cb) => { client.release() cb(new Error('nope')) - } + }, }) pool.connect((err, client) => { diff --git a/packages/pg-protocol/src/b.ts b/packages/pg-protocol/src/b.ts index 27a24c6a5..028b76393 100644 --- a/packages/pg-protocol/src/b.ts +++ b/packages/pg-protocol/src/b.ts @@ -1,28 +1,28 @@ // file for microbenchmarking -import { Writer } from './buffer-writer'; -import { serialize } from './index'; -import { BufferReader } from './buffer-reader'; +import { Writer } from './buffer-writer' +import { serialize } from './index' +import { BufferReader } from './buffer-reader' -const LOOPS = 1000; -let count = 0; -let start = Date.now(); -const writer = new Writer(); +const LOOPS = 1000 +let count = 0 +let start = Date.now() +const writer = new Writer() -const reader = new BufferReader(); -const buffer = Buffer.from([33, 33, 33, 33, 33, 33, 33, 0]); +const reader = new BufferReader() +const buffer = Buffer.from([33, 33, 33, 33, 33, 33, 33, 0]) const run = () => { if (count > LOOPS) { - console.log(Date.now() - start); - return; + console.log(Date.now() - start) + return } - count++; + count++ for (let i = 0; i < LOOPS; i++) { - reader.setBuffer(0, buffer); - reader.cstring(); + reader.setBuffer(0, buffer) + reader.cstring() } - setImmediate(run); -}; + setImmediate(run) +} -run(); +run() diff --git a/packages/pg-protocol/src/buffer-reader.ts b/packages/pg-protocol/src/buffer-reader.ts index 62ea85240..2305e130c 100644 --- a/packages/pg-protocol/src/buffer-reader.ts +++ b/packages/pg-protocol/src/buffer-reader.ts @@ -1,53 +1,53 @@ -const emptyBuffer = Buffer.allocUnsafe(0); +const emptyBuffer = Buffer.allocUnsafe(0) export class BufferReader { - private buffer: Buffer = emptyBuffer; + private buffer: Buffer = emptyBuffer // TODO(bmc): support non-utf8 encoding? - private encoding: string = 'utf-8'; + private encoding: string = 'utf-8' constructor(private offset: number = 0) {} public setBuffer(offset: number, buffer: Buffer): void { - this.offset = offset; - this.buffer = buffer; + this.offset = offset + this.buffer = buffer } public int16(): number { - const result = this.buffer.readInt16BE(this.offset); - this.offset += 2; - return result; + const result = this.buffer.readInt16BE(this.offset) + this.offset += 2 + return result } public byte(): number { - const result = this.buffer[this.offset]; - this.offset++; - return result; + const result = this.buffer[this.offset] + this.offset++ + return result } public int32(): number { - const result = this.buffer.readInt32BE(this.offset); - this.offset += 4; - return result; + const result = this.buffer.readInt32BE(this.offset) + this.offset += 4 + return result } public string(length: number): string { - const result = this.buffer.toString(this.encoding, this.offset, this.offset + length); - this.offset += length; - return result; + const result = this.buffer.toString(this.encoding, this.offset, this.offset + length) + this.offset += length + return result } public cstring(): string { - const start = this.offset; - let end = start; + const start = this.offset + let end = start while (this.buffer[end++] !== 0) {} - this.offset = end; - return this.buffer.toString(this.encoding, start, end - 1); + this.offset = end + return this.buffer.toString(this.encoding, start, end - 1) } public bytes(length: number): Buffer { - const result = this.buffer.slice(this.offset, this.offset + length); - this.offset += length; - return result; + const result = this.buffer.slice(this.offset, this.offset + length) + this.offset += length + return result } } diff --git a/packages/pg-protocol/src/buffer-writer.ts b/packages/pg-protocol/src/buffer-writer.ts index 58efb3b25..3a8d80b30 100644 --- a/packages/pg-protocol/src/buffer-writer.ts +++ b/packages/pg-protocol/src/buffer-writer.ts @@ -1,85 +1,85 @@ //binary data writer tuned for encoding binary specific to the postgres binary protocol export class Writer { - private buffer: Buffer; - private offset: number = 5; - private headerPosition: number = 0; + private buffer: Buffer + private offset: number = 5 + private headerPosition: number = 0 constructor(private size = 256) { - this.buffer = Buffer.alloc(size); + this.buffer = Buffer.alloc(size) } private ensure(size: number): void { - var remaining = this.buffer.length - this.offset; + var remaining = this.buffer.length - this.offset if (remaining < size) { - var oldBuffer = this.buffer; + var oldBuffer = this.buffer // exponential growth factor of around ~ 1.5 // https://stackoverflow.com/questions/2269063/buffer-growth-strategy - var newSize = oldBuffer.length + (oldBuffer.length >> 1) + size; - this.buffer = Buffer.alloc(newSize); - oldBuffer.copy(this.buffer); + var newSize = oldBuffer.length + (oldBuffer.length >> 1) + size + this.buffer = Buffer.alloc(newSize) + oldBuffer.copy(this.buffer) } } public addInt32(num: number): Writer { - this.ensure(4); - this.buffer[this.offset++] = (num >>> 24) & 0xff; - this.buffer[this.offset++] = (num >>> 16) & 0xff; - this.buffer[this.offset++] = (num >>> 8) & 0xff; - this.buffer[this.offset++] = (num >>> 0) & 0xff; - return this; + this.ensure(4) + this.buffer[this.offset++] = (num >>> 24) & 0xff + this.buffer[this.offset++] = (num >>> 16) & 0xff + this.buffer[this.offset++] = (num >>> 8) & 0xff + this.buffer[this.offset++] = (num >>> 0) & 0xff + return this } public addInt16(num: number): Writer { - this.ensure(2); - this.buffer[this.offset++] = (num >>> 8) & 0xff; - this.buffer[this.offset++] = (num >>> 0) & 0xff; - return this; + this.ensure(2) + this.buffer[this.offset++] = (num >>> 8) & 0xff + this.buffer[this.offset++] = (num >>> 0) & 0xff + return this } public addCString(string: string): Writer { if (!string) { - this.ensure(1); + this.ensure(1) } else { - var len = Buffer.byteLength(string); - this.ensure(len + 1); // +1 for null terminator - this.buffer.write(string, this.offset, 'utf-8'); - this.offset += len; + var len = Buffer.byteLength(string) + this.ensure(len + 1) // +1 for null terminator + this.buffer.write(string, this.offset, 'utf-8') + this.offset += len } - this.buffer[this.offset++] = 0; // null terminator - return this; + this.buffer[this.offset++] = 0 // null terminator + return this } public addString(string: string = ''): Writer { - var len = Buffer.byteLength(string); - this.ensure(len); - this.buffer.write(string, this.offset); - this.offset += len; - return this; + var len = Buffer.byteLength(string) + this.ensure(len) + this.buffer.write(string, this.offset) + this.offset += len + return this } public add(otherBuffer: Buffer): Writer { - this.ensure(otherBuffer.length); - otherBuffer.copy(this.buffer, this.offset); - this.offset += otherBuffer.length; - return this; + this.ensure(otherBuffer.length) + otherBuffer.copy(this.buffer, this.offset) + this.offset += otherBuffer.length + return this } private join(code?: number): Buffer { if (code) { - this.buffer[this.headerPosition] = code; + this.buffer[this.headerPosition] = code //length is everything in this packet minus the code - const length = this.offset - (this.headerPosition + 1); - this.buffer.writeInt32BE(length, this.headerPosition + 1); + const length = this.offset - (this.headerPosition + 1) + this.buffer.writeInt32BE(length, this.headerPosition + 1) } - return this.buffer.slice(code ? 0 : 5, this.offset); + return this.buffer.slice(code ? 0 : 5, this.offset) } public flush(code?: number): Buffer { - var result = this.join(code); - this.offset = 5; - this.headerPosition = 0; - this.buffer = Buffer.allocUnsafe(this.size); - return result; + var result = this.join(code) + this.offset = 5 + this.headerPosition = 0 + this.buffer = Buffer.allocUnsafe(this.size) + return result } } diff --git a/packages/pg-protocol/src/inbound-parser.test.ts b/packages/pg-protocol/src/inbound-parser.test.ts index f50e95bed..8a8785a5c 100644 --- a/packages/pg-protocol/src/inbound-parser.test.ts +++ b/packages/pg-protocol/src/inbound-parser.test.ts @@ -1,18 +1,18 @@ -import buffers from './testing/test-buffers'; -import BufferList from './testing/buffer-list'; -import { parse } from '.'; -import assert from 'assert'; -import { PassThrough } from 'stream'; -import { BackendMessage } from './messages'; - -var authOkBuffer = buffers.authenticationOk(); -var paramStatusBuffer = buffers.parameterStatus('client_encoding', 'UTF8'); -var readyForQueryBuffer = buffers.readyForQuery(); -var backendKeyDataBuffer = buffers.backendKeyData(1, 2); -var commandCompleteBuffer = buffers.commandComplete('SELECT 3'); -var parseCompleteBuffer = buffers.parseComplete(); -var bindCompleteBuffer = buffers.bindComplete(); -var portalSuspendedBuffer = buffers.portalSuspended(); +import buffers from './testing/test-buffers' +import BufferList from './testing/buffer-list' +import { parse } from '.' +import assert from 'assert' +import { PassThrough } from 'stream' +import { BackendMessage } from './messages' + +var authOkBuffer = buffers.authenticationOk() +var paramStatusBuffer = buffers.parameterStatus('client_encoding', 'UTF8') +var readyForQueryBuffer = buffers.readyForQuery() +var backendKeyDataBuffer = buffers.backendKeyData(1, 2) +var commandCompleteBuffer = buffers.commandComplete('SELECT 3') +var parseCompleteBuffer = buffers.parseComplete() +var bindCompleteBuffer = buffers.bindComplete() +var portalSuspendedBuffer = buffers.portalSuspended() var addRow = function (bufferList: BufferList, name: string, offset: number) { return bufferList @@ -22,8 +22,8 @@ var addRow = function (bufferList: BufferList, name: string, offset: number) { .addInt32(offset++) // objectId of field's data type .addInt16(offset++) // datatype size .addInt32(offset++) // type modifier - .addInt16(0); // format code, 0 => text -}; + .addInt16(0) // format code, 0 => text +} var row1 = { name: 'id', @@ -33,9 +33,9 @@ var row1 = { dataTypeSize: 4, typeModifier: 5, formatCode: 0, -}; -var oneRowDescBuff = buffers.rowDescription([row1]); -row1.name = 'bang'; +} +var oneRowDescBuff = buffers.rowDescription([row1]) +row1.name = 'bang' var twoRowBuf = buffers.rowDescription([ row1, @@ -48,59 +48,59 @@ var twoRowBuf = buffers.rowDescription([ typeModifier: 14, formatCode: 0, }, -]); +]) -var emptyRowFieldBuf = new BufferList().addInt16(0).join(true, 'D'); +var emptyRowFieldBuf = new BufferList().addInt16(0).join(true, 'D') -var emptyRowFieldBuf = buffers.dataRow([]); +var emptyRowFieldBuf = buffers.dataRow([]) var oneFieldBuf = new BufferList() .addInt16(1) // number of fields .addInt32(5) // length of bytes of fields .addCString('test') - .join(true, 'D'); + .join(true, 'D') -var oneFieldBuf = buffers.dataRow(['test']); +var oneFieldBuf = buffers.dataRow(['test']) var expectedAuthenticationOkayMessage = { name: 'authenticationOk', length: 8, -}; +} var expectedParameterStatusMessage = { name: 'parameterStatus', parameterName: 'client_encoding', parameterValue: 'UTF8', length: 25, -}; +} var expectedBackendKeyDataMessage = { name: 'backendKeyData', processID: 1, secretKey: 2, -}; +} var expectedReadyForQueryMessage = { name: 'readyForQuery', length: 5, status: 'I', -}; +} var expectedCommandCompleteMessage = { name: 'commandComplete', length: 13, text: 'SELECT 3', -}; +} var emptyRowDescriptionBuffer = new BufferList() .addInt16(0) // number of fields - .join(true, 'T'); + .join(true, 'T') var expectedEmptyRowDescriptionMessage = { name: 'rowDescription', length: 6, fieldCount: 0, fields: [], -}; +} var expectedOneRowMessage = { name: 'rowDescription', length: 27, @@ -116,7 +116,7 @@ var expectedOneRowMessage = { format: 'text', }, ], -}; +} var expectedTwoRowMessage = { name: 'rowDescription', @@ -142,125 +142,125 @@ var expectedTwoRowMessage = { format: 'text', }, ], -}; +} var testForMessage = function (buffer: Buffer, expectedMessage: any) { it('recieves and parses ' + expectedMessage.name, async () => { - const messages = await parseBuffers([buffer]); - const [lastMessage] = messages; + const messages = await parseBuffers([buffer]) + const [lastMessage] = messages for (const key in expectedMessage) { - assert.deepEqual((lastMessage as any)[key], expectedMessage[key]); + assert.deepEqual((lastMessage as any)[key], expectedMessage[key]) } - }); -}; + }) +} -var plainPasswordBuffer = buffers.authenticationCleartextPassword(); -var md5PasswordBuffer = buffers.authenticationMD5Password(); -var SASLBuffer = buffers.authenticationSASL(); -var SASLContinueBuffer = buffers.authenticationSASLContinue(); -var SASLFinalBuffer = buffers.authenticationSASLFinal(); +var plainPasswordBuffer = buffers.authenticationCleartextPassword() +var md5PasswordBuffer = buffers.authenticationMD5Password() +var SASLBuffer = buffers.authenticationSASL() +var SASLContinueBuffer = buffers.authenticationSASLContinue() +var SASLFinalBuffer = buffers.authenticationSASLFinal() var expectedPlainPasswordMessage = { name: 'authenticationCleartextPassword', -}; +} var expectedMD5PasswordMessage = { name: 'authenticationMD5Password', salt: Buffer.from([1, 2, 3, 4]), -}; +} var expectedSASLMessage = { name: 'authenticationSASL', mechanisms: ['SCRAM-SHA-256'], -}; +} var expectedSASLContinueMessage = { name: 'authenticationSASLContinue', data: 'data', -}; +} var expectedSASLFinalMessage = { name: 'authenticationSASLFinal', data: 'data', -}; +} -var notificationResponseBuffer = buffers.notification(4, 'hi', 'boom'); +var notificationResponseBuffer = buffers.notification(4, 'hi', 'boom') var expectedNotificationResponseMessage = { name: 'notification', processId: 4, channel: 'hi', payload: 'boom', -}; +} const parseBuffers = async (buffers: Buffer[]): Promise => { - const stream = new PassThrough(); + const stream = new PassThrough() for (const buffer of buffers) { - stream.write(buffer); + stream.write(buffer) } - stream.end(); - const msgs: BackendMessage[] = []; - await parse(stream, (msg) => msgs.push(msg)); - return msgs; -}; + stream.end() + const msgs: BackendMessage[] = [] + await parse(stream, (msg) => msgs.push(msg)) + return msgs +} describe('PgPacketStream', function () { - testForMessage(authOkBuffer, expectedAuthenticationOkayMessage); - testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage); - testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage); - testForMessage(SASLBuffer, expectedSASLMessage); - testForMessage(SASLContinueBuffer, expectedSASLContinueMessage); - testForMessage(SASLFinalBuffer, expectedSASLFinalMessage); - - testForMessage(paramStatusBuffer, expectedParameterStatusMessage); - testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage); - testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage); - testForMessage(commandCompleteBuffer, expectedCommandCompleteMessage); - testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage); + testForMessage(authOkBuffer, expectedAuthenticationOkayMessage) + testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage) + testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage) + testForMessage(SASLBuffer, expectedSASLMessage) + testForMessage(SASLContinueBuffer, expectedSASLContinueMessage) + testForMessage(SASLFinalBuffer, expectedSASLFinalMessage) + + testForMessage(paramStatusBuffer, expectedParameterStatusMessage) + testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage) + testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage) + testForMessage(commandCompleteBuffer, expectedCommandCompleteMessage) + testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage) testForMessage(buffers.emptyQuery(), { name: 'emptyQuery', length: 4, - }); + }) testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), { name: 'noData', - }); + }) describe('rowDescription messages', function () { - testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage); - testForMessage(oneRowDescBuff, expectedOneRowMessage); - testForMessage(twoRowBuf, expectedTwoRowMessage); - }); + testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage) + testForMessage(oneRowDescBuff, expectedOneRowMessage) + testForMessage(twoRowBuf, expectedTwoRowMessage) + }) describe('parsing rows', function () { describe('parsing empty row', function () { testForMessage(emptyRowFieldBuf, { name: 'dataRow', fieldCount: 0, - }); - }); + }) + }) describe('parsing data row with fields', function () { testForMessage(oneFieldBuf, { name: 'dataRow', fieldCount: 1, fields: ['test'], - }); - }); - }); + }) + }) + }) describe('notice message', function () { // this uses the same logic as error message - var buff = buffers.notice([{ type: 'C', value: 'code' }]); + var buff = buffers.notice([{ type: 'C', value: 'code' }]) testForMessage(buff, { name: 'notice', code: 'code', - }); - }); + }) + }) testForMessage(buffers.error([]), { name: 'error', - }); + }) describe('with all the fields', function () { var buffer = buffers.error([ @@ -316,7 +316,7 @@ describe('PgPacketStream', function () { type: 'Z', // ignored value: 'alsdkf', }, - ]); + ]) testForMessage(buffer, { name: 'error', @@ -332,37 +332,37 @@ describe('PgPacketStream', function () { file: 'file', line: 'line', routine: 'routine', - }); - }); + }) + }) testForMessage(parseCompleteBuffer, { name: 'parseComplete', - }); + }) testForMessage(bindCompleteBuffer, { name: 'bindComplete', - }); + }) testForMessage(bindCompleteBuffer, { name: 'bindComplete', - }); + }) testForMessage(buffers.closeComplete(), { name: 'closeComplete', - }); + }) describe('parses portal suspended message', function () { testForMessage(portalSuspendedBuffer, { name: 'portalSuspended', - }); - }); + }) + }) describe('parses replication start message', function () { testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { name: 'replicationStart', length: 4, - }); - }); + }) + }) describe('copy', () => { testForMessage(buffers.copyIn(0), { @@ -370,140 +370,140 @@ describe('PgPacketStream', function () { length: 7, binary: false, columnTypes: [], - }); + }) testForMessage(buffers.copyIn(2), { name: 'copyInResponse', length: 11, binary: false, columnTypes: [0, 1], - }); + }) testForMessage(buffers.copyOut(0), { name: 'copyOutResponse', length: 7, binary: false, columnTypes: [], - }); + }) testForMessage(buffers.copyOut(3), { name: 'copyOutResponse', length: 13, binary: false, columnTypes: [0, 1, 2], - }); + }) testForMessage(buffers.copyDone(), { name: 'copyDone', length: 4, - }); + }) testForMessage(buffers.copyData(Buffer.from([5, 6, 7])), { name: 'copyData', length: 7, chunk: Buffer.from([5, 6, 7]), - }); - }); + }) + }) // since the data message on a stream can randomly divide the incomming // tcp packets anywhere, we need to make sure we can parse every single // split on a tcp message describe('split buffer, single message parsing', function () { - var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']); + var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']) it('parses when full buffer comes in', async function () { - const messages = await parseBuffers([fullBuffer]); - const message = messages[0] as any; - assert.equal(message.fields.length, 5); - assert.equal(message.fields[0], null); - assert.equal(message.fields[1], 'bang'); - assert.equal(message.fields[2], 'zug zug'); - assert.equal(message.fields[3], null); - assert.equal(message.fields[4], '!'); - }); + const messages = await parseBuffers([fullBuffer]) + const message = messages[0] as any + assert.equal(message.fields.length, 5) + assert.equal(message.fields[0], null) + assert.equal(message.fields[1], 'bang') + assert.equal(message.fields[2], 'zug zug') + assert.equal(message.fields[3], null) + assert.equal(message.fields[4], '!') + }) var testMessageRecievedAfterSpiltAt = async function (split: number) { - var firstBuffer = Buffer.alloc(fullBuffer.length - split); - var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length); - fullBuffer.copy(firstBuffer, 0, 0); - fullBuffer.copy(secondBuffer, 0, firstBuffer.length); - const messages = await parseBuffers([fullBuffer]); - const message = messages[0] as any; - assert.equal(message.fields.length, 5); - assert.equal(message.fields[0], null); - assert.equal(message.fields[1], 'bang'); - assert.equal(message.fields[2], 'zug zug'); - assert.equal(message.fields[3], null); - assert.equal(message.fields[4], '!'); - }; + var firstBuffer = Buffer.alloc(fullBuffer.length - split) + var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) + fullBuffer.copy(firstBuffer, 0, 0) + fullBuffer.copy(secondBuffer, 0, firstBuffer.length) + const messages = await parseBuffers([fullBuffer]) + const message = messages[0] as any + assert.equal(message.fields.length, 5) + assert.equal(message.fields[0], null) + assert.equal(message.fields[1], 'bang') + assert.equal(message.fields[2], 'zug zug') + assert.equal(message.fields[3], null) + assert.equal(message.fields[4], '!') + } it('parses when split in the middle', function () { - testMessageRecievedAfterSpiltAt(6); - }); + testMessageRecievedAfterSpiltAt(6) + }) it('parses when split at end', function () { - testMessageRecievedAfterSpiltAt(2); - }); + testMessageRecievedAfterSpiltAt(2) + }) it('parses when split at beginning', function () { - testMessageRecievedAfterSpiltAt(fullBuffer.length - 2); - testMessageRecievedAfterSpiltAt(fullBuffer.length - 1); - testMessageRecievedAfterSpiltAt(fullBuffer.length - 5); - }); - }); + testMessageRecievedAfterSpiltAt(fullBuffer.length - 2) + testMessageRecievedAfterSpiltAt(fullBuffer.length - 1) + testMessageRecievedAfterSpiltAt(fullBuffer.length - 5) + }) + }) describe('split buffer, multiple message parsing', function () { - var dataRowBuffer = buffers.dataRow(['!']); - var readyForQueryBuffer = buffers.readyForQuery(); - var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length); - dataRowBuffer.copy(fullBuffer, 0, 0); - readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0); + var dataRowBuffer = buffers.dataRow(['!']) + var readyForQueryBuffer = buffers.readyForQuery() + var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length) + dataRowBuffer.copy(fullBuffer, 0, 0) + readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0) var verifyMessages = function (messages: any[]) { - assert.strictEqual(messages.length, 2); + assert.strictEqual(messages.length, 2) assert.deepEqual(messages[0], { name: 'dataRow', fieldCount: 1, length: 11, fields: ['!'], - }); - assert.equal(messages[0].fields[0], '!'); + }) + assert.equal(messages[0].fields[0], '!') assert.deepEqual(messages[1], { name: 'readyForQuery', length: 5, status: 'I', - }); - }; + }) + } // sanity check it('recieves both messages when packet is not split', async function () { - const messages = await parseBuffers([fullBuffer]); - verifyMessages(messages); - }); + const messages = await parseBuffers([fullBuffer]) + verifyMessages(messages) + }) var splitAndVerifyTwoMessages = async function (split: number) { - var firstBuffer = Buffer.alloc(fullBuffer.length - split); - var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length); - fullBuffer.copy(firstBuffer, 0, 0); - fullBuffer.copy(secondBuffer, 0, firstBuffer.length); - const messages = await parseBuffers([firstBuffer, secondBuffer]); - verifyMessages(messages); - }; + var firstBuffer = Buffer.alloc(fullBuffer.length - split) + var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) + fullBuffer.copy(firstBuffer, 0, 0) + fullBuffer.copy(secondBuffer, 0, firstBuffer.length) + const messages = await parseBuffers([firstBuffer, secondBuffer]) + verifyMessages(messages) + } describe('recieves both messages when packet is split', function () { it('in the middle', function () { - return splitAndVerifyTwoMessages(11); - }); + return splitAndVerifyTwoMessages(11) + }) it('at the front', function () { return Promise.all([ splitAndVerifyTwoMessages(fullBuffer.length - 1), splitAndVerifyTwoMessages(fullBuffer.length - 4), splitAndVerifyTwoMessages(fullBuffer.length - 6), - ]); - }); + ]) + }) it('at the end', function () { - return Promise.all([splitAndVerifyTwoMessages(8), splitAndVerifyTwoMessages(1)]); - }); - }); - }); -}); + return Promise.all([splitAndVerifyTwoMessages(8), splitAndVerifyTwoMessages(1)]) + }) + }) + }) +}) diff --git a/packages/pg-protocol/src/index.ts b/packages/pg-protocol/src/index.ts index 57580f6ec..486f79c86 100644 --- a/packages/pg-protocol/src/index.ts +++ b/packages/pg-protocol/src/index.ts @@ -1,11 +1,11 @@ -import { BackendMessage } from './messages'; -import { serialize } from './serializer'; -import { Parser, MessageCallback } from './parser'; +import { BackendMessage } from './messages' +import { serialize } from './serializer' +import { Parser, MessageCallback } from './parser' export function parse(stream: NodeJS.ReadableStream, callback: MessageCallback): Promise { - const parser = new Parser(); - stream.on('data', (buffer: Buffer) => parser.parse(buffer, callback)); - return new Promise((resolve) => stream.on('end', () => resolve())); + const parser = new Parser() + stream.on('data', (buffer: Buffer) => parser.parse(buffer, callback)) + return new Promise((resolve) => stream.on('end', () => resolve())) } -export { serialize }; +export { serialize } diff --git a/packages/pg-protocol/src/messages.ts b/packages/pg-protocol/src/messages.ts index 20d17f1d1..03c2f61ea 100644 --- a/packages/pg-protocol/src/messages.ts +++ b/packages/pg-protocol/src/messages.ts @@ -1,4 +1,4 @@ -export type Mode = 'text' | 'binary'; +export type Mode = 'text' | 'binary' export const enum MessageName { parseComplete = 'parseComplete', @@ -30,106 +30,106 @@ export const enum MessageName { } export interface BackendMessage { - name: MessageName; - length: number; + name: MessageName + length: number } export const parseComplete: BackendMessage = { name: MessageName.parseComplete, length: 5, -}; +} export const bindComplete: BackendMessage = { name: MessageName.bindComplete, length: 5, -}; +} export const closeComplete: BackendMessage = { name: MessageName.closeComplete, length: 5, -}; +} export const noData: BackendMessage = { name: MessageName.noData, length: 5, -}; +} export const portalSuspended: BackendMessage = { name: MessageName.portalSuspended, length: 5, -}; +} export const replicationStart: BackendMessage = { name: MessageName.replicationStart, length: 4, -}; +} export const emptyQuery: BackendMessage = { name: MessageName.emptyQuery, length: 4, -}; +} export const copyDone: BackendMessage = { name: MessageName.copyDone, length: 4, -}; +} interface NoticeOrError { - message: string | undefined; - severity: string | undefined; - code: string | undefined; - detail: string | undefined; - hint: string | undefined; - position: string | undefined; - internalPosition: string | undefined; - internalQuery: string | undefined; - where: string | undefined; - schema: string | undefined; - table: string | undefined; - column: string | undefined; - dataType: string | undefined; - constraint: string | undefined; - file: string | undefined; - line: string | undefined; - routine: string | undefined; + message: string | undefined + severity: string | undefined + code: string | undefined + detail: string | undefined + hint: string | undefined + position: string | undefined + internalPosition: string | undefined + internalQuery: string | undefined + where: string | undefined + schema: string | undefined + table: string | undefined + column: string | undefined + dataType: string | undefined + constraint: string | undefined + file: string | undefined + line: string | undefined + routine: string | undefined } export class DatabaseError extends Error implements NoticeOrError { - public severity: string | undefined; - public code: string | undefined; - public detail: string | undefined; - public hint: string | undefined; - public position: string | undefined; - public internalPosition: string | undefined; - public internalQuery: string | undefined; - public where: string | undefined; - public schema: string | undefined; - public table: string | undefined; - public column: string | undefined; - public dataType: string | undefined; - public constraint: string | undefined; - public file: string | undefined; - public line: string | undefined; - public routine: string | undefined; + public severity: string | undefined + public code: string | undefined + public detail: string | undefined + public hint: string | undefined + public position: string | undefined + public internalPosition: string | undefined + public internalQuery: string | undefined + public where: string | undefined + public schema: string | undefined + public table: string | undefined + public column: string | undefined + public dataType: string | undefined + public constraint: string | undefined + public file: string | undefined + public line: string | undefined + public routine: string | undefined constructor(message: string, public readonly length: number, public readonly name: MessageName) { - super(message); + super(message) } } export class CopyDataMessage { - public readonly name = MessageName.copyData; + public readonly name = MessageName.copyData constructor(public readonly length: number, public readonly chunk: Buffer) {} } export class CopyResponse { - public readonly columnTypes: number[]; + public readonly columnTypes: number[] constructor( public readonly length: number, public readonly name: MessageName, public readonly binary: boolean, columnCount: number ) { - this.columnTypes = new Array(columnCount); + this.columnTypes = new Array(columnCount) } } @@ -146,15 +146,15 @@ export class Field { } export class RowDescriptionMessage { - public readonly name: MessageName = MessageName.rowDescription; - public readonly fields: Field[]; + public readonly name: MessageName = MessageName.rowDescription + public readonly fields: Field[] constructor(public readonly length: number, public readonly fieldCount: number) { - this.fields = new Array(this.fieldCount); + this.fields = new Array(this.fieldCount) } } export class ParameterStatusMessage { - public readonly name: MessageName = MessageName.parameterStatus; + public readonly name: MessageName = MessageName.parameterStatus constructor( public readonly length: number, public readonly parameterName: string, @@ -163,17 +163,17 @@ export class ParameterStatusMessage { } export class AuthenticationMD5Password implements BackendMessage { - public readonly name: MessageName = MessageName.authenticationMD5Password; + public readonly name: MessageName = MessageName.authenticationMD5Password constructor(public readonly length: number, public readonly salt: Buffer) {} } export class BackendKeyDataMessage { - public readonly name: MessageName = MessageName.backendKeyData; + public readonly name: MessageName = MessageName.backendKeyData constructor(public readonly length: number, public readonly processID: number, public readonly secretKey: number) {} } export class NotificationResponseMessage { - public readonly name: MessageName = MessageName.notification; + public readonly name: MessageName = MessageName.notification constructor( public readonly length: number, public readonly processId: number, @@ -183,40 +183,40 @@ export class NotificationResponseMessage { } export class ReadyForQueryMessage { - public readonly name: MessageName = MessageName.readyForQuery; + public readonly name: MessageName = MessageName.readyForQuery constructor(public readonly length: number, public readonly status: string) {} } export class CommandCompleteMessage { - public readonly name: MessageName = MessageName.commandComplete; + public readonly name: MessageName = MessageName.commandComplete constructor(public readonly length: number, public readonly text: string) {} } export class DataRowMessage { - public readonly fieldCount: number; - public readonly name: MessageName = MessageName.dataRow; + public readonly fieldCount: number + public readonly name: MessageName = MessageName.dataRow constructor(public length: number, public fields: any[]) { - this.fieldCount = fields.length; + this.fieldCount = fields.length } } export class NoticeMessage implements BackendMessage, NoticeOrError { constructor(public readonly length: number, public readonly message: string | undefined) {} - public readonly name = MessageName.notice; - public severity: string | undefined; - public code: string | undefined; - public detail: string | undefined; - public hint: string | undefined; - public position: string | undefined; - public internalPosition: string | undefined; - public internalQuery: string | undefined; - public where: string | undefined; - public schema: string | undefined; - public table: string | undefined; - public column: string | undefined; - public dataType: string | undefined; - public constraint: string | undefined; - public file: string | undefined; - public line: string | undefined; - public routine: string | undefined; + public readonly name = MessageName.notice + public severity: string | undefined + public code: string | undefined + public detail: string | undefined + public hint: string | undefined + public position: string | undefined + public internalPosition: string | undefined + public internalQuery: string | undefined + public where: string | undefined + public schema: string | undefined + public table: string | undefined + public column: string | undefined + public dataType: string | undefined + public constraint: string | undefined + public file: string | undefined + public line: string | undefined + public routine: string | undefined } diff --git a/packages/pg-protocol/src/outbound-serializer.test.ts b/packages/pg-protocol/src/outbound-serializer.test.ts index c2ef22db7..4d2457e19 100644 --- a/packages/pg-protocol/src/outbound-serializer.test.ts +++ b/packages/pg-protocol/src/outbound-serializer.test.ts @@ -1,13 +1,13 @@ -import assert from 'assert'; -import { serialize } from './serializer'; -import BufferList from './testing/buffer-list'; +import assert from 'assert' +import { serialize } from './serializer' +import BufferList from './testing/buffer-list' describe('serializer', () => { it('builds startup message', function () { const actual = serialize.startup({ user: 'brian', database: 'bang', - }); + }) assert.deepEqual( actual, new BufferList() @@ -21,59 +21,59 @@ describe('serializer', () => { .addCString("'utf-8'") .addCString('') .join(true) - ); - }); + ) + }) it('builds password message', function () { - const actual = serialize.password('!'); - assert.deepEqual(actual, new BufferList().addCString('!').join(true, 'p')); - }); + const actual = serialize.password('!') + assert.deepEqual(actual, new BufferList().addCString('!').join(true, 'p')) + }) it('builds request ssl message', function () { - const actual = serialize.requestSsl(); - const expected = new BufferList().addInt32(80877103).join(true); - assert.deepEqual(actual, expected); - }); + const actual = serialize.requestSsl() + const expected = new BufferList().addInt32(80877103).join(true) + assert.deepEqual(actual, expected) + }) it('builds SASLInitialResponseMessage message', function () { - const actual = serialize.sendSASLInitialResponseMessage('mech', 'data'); - assert.deepEqual(actual, new BufferList().addCString('mech').addInt32(4).addString('data').join(true, 'p')); - }); + const actual = serialize.sendSASLInitialResponseMessage('mech', 'data') + assert.deepEqual(actual, new BufferList().addCString('mech').addInt32(4).addString('data').join(true, 'p')) + }) it('builds SCRAMClientFinalMessage message', function () { - const actual = serialize.sendSCRAMClientFinalMessage('data'); - assert.deepEqual(actual, new BufferList().addString('data').join(true, 'p')); - }); + const actual = serialize.sendSCRAMClientFinalMessage('data') + assert.deepEqual(actual, new BufferList().addString('data').join(true, 'p')) + }) it('builds query message', function () { - var txt = 'select * from boom'; - const actual = serialize.query(txt); - assert.deepEqual(actual, new BufferList().addCString(txt).join(true, 'Q')); - }); + var txt = 'select * from boom' + const actual = serialize.query(txt) + assert.deepEqual(actual, new BufferList().addCString(txt).join(true, 'Q')) + }) describe('parse message', () => { it('builds parse message', function () { - const actual = serialize.parse({ text: '!' }); - var expected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P'); - assert.deepEqual(actual, expected); - }); + const actual = serialize.parse({ text: '!' }) + var expected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P') + assert.deepEqual(actual, expected) + }) it('builds parse message with named query', function () { const actual = serialize.parse({ name: 'boom', text: 'select * from boom', types: [], - }); - var expected = new BufferList().addCString('boom').addCString('select * from boom').addInt16(0).join(true, 'P'); - assert.deepEqual(actual, expected); - }); + }) + var expected = new BufferList().addCString('boom').addCString('select * from boom').addInt16(0).join(true, 'P') + assert.deepEqual(actual, expected) + }) it('with multiple parameters', function () { const actual = serialize.parse({ name: 'force', text: 'select * from bang where name = $1', types: [1, 2, 3, 4], - }); + }) var expected = new BufferList() .addCString('force') .addCString('select * from bang where name = $1') @@ -82,14 +82,14 @@ describe('serializer', () => { .addInt32(2) .addInt32(3) .addInt32(4) - .join(true, 'P'); - assert.deepEqual(actual, expected); - }); - }); + .join(true, 'P') + assert.deepEqual(actual, expected) + }) + }) describe('bind messages', function () { it('with no values', function () { - const actual = serialize.bind(); + const actual = serialize.bind() var expectedBuffer = new BufferList() .addCString('') @@ -97,16 +97,16 @@ describe('serializer', () => { .addInt16(0) .addInt16(0) .addInt16(0) - .join(true, 'B'); - assert.deepEqual(actual, expectedBuffer); - }); + .join(true, 'B') + assert.deepEqual(actual, expectedBuffer) + }) it('with named statement, portal, and values', function () { const actual = serialize.bind({ portal: 'bang', statement: 'woo', values: ['1', 'hi', null, 'zing'], - }); + }) var expectedBuffer = new BufferList() .addCString('bang') // portal name .addCString('woo') // statement name @@ -120,17 +120,17 @@ describe('serializer', () => { .addInt32(4) .add(Buffer.from('zing')) .addInt16(0) - .join(true, 'B'); - assert.deepEqual(actual, expectedBuffer); - }); - }); + .join(true, 'B') + assert.deepEqual(actual, expectedBuffer) + }) + }) it('with named statement, portal, and buffer value', function () { const actual = serialize.bind({ portal: 'bang', statement: 'woo', values: ['1', 'hi', null, Buffer.from('zing', 'utf8')], - }); + }) var expectedBuffer = new BufferList() .addCString('bang') // portal name .addCString('woo') // statement name @@ -148,96 +148,96 @@ describe('serializer', () => { .addInt32(4) .add(Buffer.from('zing', 'utf-8')) .addInt16(0) - .join(true, 'B'); - assert.deepEqual(actual, expectedBuffer); - }); + .join(true, 'B') + assert.deepEqual(actual, expectedBuffer) + }) describe('builds execute message', function () { it('for unamed portal with no row limit', function () { - const actual = serialize.execute(); - var expectedBuffer = new BufferList().addCString('').addInt32(0).join(true, 'E'); - assert.deepEqual(actual, expectedBuffer); - }); + const actual = serialize.execute() + var expectedBuffer = new BufferList().addCString('').addInt32(0).join(true, 'E') + assert.deepEqual(actual, expectedBuffer) + }) it('for named portal with row limit', function () { const actual = serialize.execute({ portal: 'my favorite portal', rows: 100, - }); - var expectedBuffer = new BufferList().addCString('my favorite portal').addInt32(100).join(true, 'E'); - assert.deepEqual(actual, expectedBuffer); - }); - }); + }) + var expectedBuffer = new BufferList().addCString('my favorite portal').addInt32(100).join(true, 'E') + assert.deepEqual(actual, expectedBuffer) + }) + }) it('builds flush command', function () { - const actual = serialize.flush(); - var expected = new BufferList().join(true, 'H'); - assert.deepEqual(actual, expected); - }); + const actual = serialize.flush() + var expected = new BufferList().join(true, 'H') + assert.deepEqual(actual, expected) + }) it('builds sync command', function () { - const actual = serialize.sync(); - var expected = new BufferList().join(true, 'S'); - assert.deepEqual(actual, expected); - }); + const actual = serialize.sync() + var expected = new BufferList().join(true, 'S') + assert.deepEqual(actual, expected) + }) it('builds end command', function () { - const actual = serialize.end(); - var expected = Buffer.from([0x58, 0, 0, 0, 4]); - assert.deepEqual(actual, expected); - }); + const actual = serialize.end() + var expected = Buffer.from([0x58, 0, 0, 0, 4]) + assert.deepEqual(actual, expected) + }) describe('builds describe command', function () { it('describe statement', function () { - const actual = serialize.describe({ type: 'S', name: 'bang' }); - var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D'); - assert.deepEqual(actual, expected); - }); + const actual = serialize.describe({ type: 'S', name: 'bang' }) + var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D') + assert.deepEqual(actual, expected) + }) it('describe unnamed portal', function () { - const actual = serialize.describe({ type: 'P' }); - var expected = new BufferList().addChar('P').addCString('').join(true, 'D'); - assert.deepEqual(actual, expected); - }); - }); + const actual = serialize.describe({ type: 'P' }) + var expected = new BufferList().addChar('P').addCString('').join(true, 'D') + assert.deepEqual(actual, expected) + }) + }) describe('builds close command', function () { it('describe statement', function () { - const actual = serialize.close({ type: 'S', name: 'bang' }); - var expected = new BufferList().addChar('S').addCString('bang').join(true, 'C'); - assert.deepEqual(actual, expected); - }); + const actual = serialize.close({ type: 'S', name: 'bang' }) + var expected = new BufferList().addChar('S').addCString('bang').join(true, 'C') + assert.deepEqual(actual, expected) + }) it('describe unnamed portal', function () { - const actual = serialize.close({ type: 'P' }); - var expected = new BufferList().addChar('P').addCString('').join(true, 'C'); - assert.deepEqual(actual, expected); - }); - }); + const actual = serialize.close({ type: 'P' }) + var expected = new BufferList().addChar('P').addCString('').join(true, 'C') + assert.deepEqual(actual, expected) + }) + }) describe('copy messages', function () { it('builds copyFromChunk', () => { - const actual = serialize.copyData(Buffer.from([1, 2, 3])); - const expected = new BufferList().add(Buffer.from([1, 2, 3])).join(true, 'd'); - assert.deepEqual(actual, expected); - }); + const actual = serialize.copyData(Buffer.from([1, 2, 3])) + const expected = new BufferList().add(Buffer.from([1, 2, 3])).join(true, 'd') + assert.deepEqual(actual, expected) + }) it('builds copy fail', () => { - const actual = serialize.copyFail('err!'); - const expected = new BufferList().addCString('err!').join(true, 'f'); - assert.deepEqual(actual, expected); - }); + const actual = serialize.copyFail('err!') + const expected = new BufferList().addCString('err!').join(true, 'f') + assert.deepEqual(actual, expected) + }) it('builds copy done', () => { - const actual = serialize.copyDone(); - const expected = new BufferList().join(true, 'c'); - assert.deepEqual(actual, expected); - }); - }); + const actual = serialize.copyDone() + const expected = new BufferList().join(true, 'c') + assert.deepEqual(actual, expected) + }) + }) it('builds cancel message', () => { - const actual = serialize.cancel(3, 4); - const expected = new BufferList().addInt16(1234).addInt16(5678).addInt32(3).addInt32(4).join(true); - assert.deepEqual(actual, expected); - }); -}); + const actual = serialize.cancel(3, 4) + const expected = new BufferList().addInt16(1234).addInt16(5678).addInt32(3).addInt32(4).join(true) + assert.deepEqual(actual, expected) + }) +}) diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 58de45e1f..1531f3c0d 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -1,4 +1,4 @@ -import { TransformOptions } from 'stream'; +import { TransformOptions } from 'stream' import { Mode, bindComplete, @@ -24,28 +24,28 @@ import { MessageName, AuthenticationMD5Password, NoticeMessage, -} from './messages'; -import { BufferReader } from './buffer-reader'; -import assert from 'assert'; +} from './messages' +import { BufferReader } from './buffer-reader' +import assert from 'assert' // every message is prefixed with a single bye -const CODE_LENGTH = 1; +const CODE_LENGTH = 1 // every message has an int32 length which includes itself but does // NOT include the code in the length -const LEN_LENGTH = 4; +const LEN_LENGTH = 4 -const HEADER_LENGTH = CODE_LENGTH + LEN_LENGTH; +const HEADER_LENGTH = CODE_LENGTH + LEN_LENGTH export type Packet = { - code: number; - packet: Buffer; -}; + code: number + packet: Buffer +} -const emptyBuffer = Buffer.allocUnsafe(0); +const emptyBuffer = Buffer.allocUnsafe(0) type StreamOptions = TransformOptions & { - mode: Mode; -}; + mode: Mode +} const enum MessageCodes { DataRow = 0x44, // D @@ -71,275 +71,275 @@ const enum MessageCodes { CopyData = 0x64, // d } -export type MessageCallback = (msg: BackendMessage) => void; +export type MessageCallback = (msg: BackendMessage) => void export class Parser { - private remainingBuffer: Buffer = emptyBuffer; - private reader = new BufferReader(); - private mode: Mode; + private remainingBuffer: Buffer = emptyBuffer + private reader = new BufferReader() + private mode: Mode constructor(opts?: StreamOptions) { if (opts?.mode === 'binary') { - throw new Error('Binary mode not supported yet'); + throw new Error('Binary mode not supported yet') } - this.mode = opts?.mode || 'text'; + this.mode = opts?.mode || 'text' } public parse(buffer: Buffer, callback: MessageCallback) { - let combinedBuffer = buffer; + let combinedBuffer = buffer if (this.remainingBuffer.byteLength) { - combinedBuffer = Buffer.allocUnsafe(this.remainingBuffer.byteLength + buffer.byteLength); - this.remainingBuffer.copy(combinedBuffer); - buffer.copy(combinedBuffer, this.remainingBuffer.byteLength); + combinedBuffer = Buffer.allocUnsafe(this.remainingBuffer.byteLength + buffer.byteLength) + this.remainingBuffer.copy(combinedBuffer) + buffer.copy(combinedBuffer, this.remainingBuffer.byteLength) } - let offset = 0; + let offset = 0 while (offset + HEADER_LENGTH <= combinedBuffer.byteLength) { // code is 1 byte long - it identifies the message type - const code = combinedBuffer[offset]; + const code = combinedBuffer[offset] // length is 1 Uint32BE - it is the length of the message EXCLUDING the code - const length = combinedBuffer.readUInt32BE(offset + CODE_LENGTH); + const length = combinedBuffer.readUInt32BE(offset + CODE_LENGTH) - const fullMessageLength = CODE_LENGTH + length; + const fullMessageLength = CODE_LENGTH + length if (fullMessageLength + offset <= combinedBuffer.byteLength) { - const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer); - callback(message); - offset += fullMessageLength; + const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer) + callback(message) + offset += fullMessageLength } else { - break; + break } } if (offset === combinedBuffer.byteLength) { - this.remainingBuffer = emptyBuffer; + this.remainingBuffer = emptyBuffer } else { - this.remainingBuffer = combinedBuffer.slice(offset); + this.remainingBuffer = combinedBuffer.slice(offset) } } private handlePacket(offset: number, code: number, length: number, bytes: Buffer): BackendMessage { switch (code) { case MessageCodes.BindComplete: - return bindComplete; + return bindComplete case MessageCodes.ParseComplete: - return parseComplete; + return parseComplete case MessageCodes.CloseComplete: - return closeComplete; + return closeComplete case MessageCodes.NoData: - return noData; + return noData case MessageCodes.PortalSuspended: - return portalSuspended; + return portalSuspended case MessageCodes.CopyDone: - return copyDone; + return copyDone case MessageCodes.ReplicationStart: - return replicationStart; + return replicationStart case MessageCodes.EmptyQuery: - return emptyQuery; + return emptyQuery case MessageCodes.DataRow: - return this.parseDataRowMessage(offset, length, bytes); + return this.parseDataRowMessage(offset, length, bytes) case MessageCodes.CommandComplete: - return this.parseCommandCompleteMessage(offset, length, bytes); + return this.parseCommandCompleteMessage(offset, length, bytes) case MessageCodes.ReadyForQuery: - return this.parseReadyForQueryMessage(offset, length, bytes); + return this.parseReadyForQueryMessage(offset, length, bytes) case MessageCodes.NotificationResponse: - return this.parseNotificationMessage(offset, length, bytes); + return this.parseNotificationMessage(offset, length, bytes) case MessageCodes.AuthenticationResponse: - return this.parseAuthenticationResponse(offset, length, bytes); + return this.parseAuthenticationResponse(offset, length, bytes) case MessageCodes.ParameterStatus: - return this.parseParameterStatusMessage(offset, length, bytes); + return this.parseParameterStatusMessage(offset, length, bytes) case MessageCodes.BackendKeyData: - return this.parseBackendKeyData(offset, length, bytes); + return this.parseBackendKeyData(offset, length, bytes) case MessageCodes.ErrorMessage: - return this.parseErrorMessage(offset, length, bytes, MessageName.error); + return this.parseErrorMessage(offset, length, bytes, MessageName.error) case MessageCodes.NoticeMessage: - return this.parseErrorMessage(offset, length, bytes, MessageName.notice); + return this.parseErrorMessage(offset, length, bytes, MessageName.notice) case MessageCodes.RowDescriptionMessage: - return this.parseRowDescriptionMessage(offset, length, bytes); + return this.parseRowDescriptionMessage(offset, length, bytes) case MessageCodes.CopyIn: - return this.parseCopyInMessage(offset, length, bytes); + return this.parseCopyInMessage(offset, length, bytes) case MessageCodes.CopyOut: - return this.parseCopyOutMessage(offset, length, bytes); + return this.parseCopyOutMessage(offset, length, bytes) case MessageCodes.CopyData: - return this.parseCopyData(offset, length, bytes); + return this.parseCopyData(offset, length, bytes) default: - assert.fail(`unknown message code: ${code.toString(16)}`); + assert.fail(`unknown message code: ${code.toString(16)}`) } } private parseReadyForQueryMessage(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); - const status = this.reader.string(1); - return new ReadyForQueryMessage(length, status); + this.reader.setBuffer(offset, bytes) + const status = this.reader.string(1) + return new ReadyForQueryMessage(length, status) } private parseCommandCompleteMessage(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); - const text = this.reader.cstring(); - return new CommandCompleteMessage(length, text); + this.reader.setBuffer(offset, bytes) + const text = this.reader.cstring() + return new CommandCompleteMessage(length, text) } private parseCopyData(offset: number, length: number, bytes: Buffer) { - const chunk = bytes.slice(offset, offset + (length - 4)); - return new CopyDataMessage(length, chunk); + const chunk = bytes.slice(offset, offset + (length - 4)) + return new CopyDataMessage(length, chunk) } private parseCopyInMessage(offset: number, length: number, bytes: Buffer) { - return this.parseCopyMessage(offset, length, bytes, MessageName.copyInResponse); + return this.parseCopyMessage(offset, length, bytes, MessageName.copyInResponse) } private parseCopyOutMessage(offset: number, length: number, bytes: Buffer) { - return this.parseCopyMessage(offset, length, bytes, MessageName.copyOutResponse); + return this.parseCopyMessage(offset, length, bytes, MessageName.copyOutResponse) } private parseCopyMessage(offset: number, length: number, bytes: Buffer, messageName: MessageName) { - this.reader.setBuffer(offset, bytes); - const isBinary = this.reader.byte() !== 0; - const columnCount = this.reader.int16(); - const message = new CopyResponse(length, messageName, isBinary, columnCount); + this.reader.setBuffer(offset, bytes) + const isBinary = this.reader.byte() !== 0 + const columnCount = this.reader.int16() + const message = new CopyResponse(length, messageName, isBinary, columnCount) for (let i = 0; i < columnCount; i++) { - message.columnTypes[i] = this.reader.int16(); + message.columnTypes[i] = this.reader.int16() } - return message; + return message } private parseNotificationMessage(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); - const processId = this.reader.int32(); - const channel = this.reader.cstring(); - const payload = this.reader.cstring(); - return new NotificationResponseMessage(length, processId, channel, payload); + this.reader.setBuffer(offset, bytes) + const processId = this.reader.int32() + const channel = this.reader.cstring() + const payload = this.reader.cstring() + return new NotificationResponseMessage(length, processId, channel, payload) } private parseRowDescriptionMessage(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); - const fieldCount = this.reader.int16(); - const message = new RowDescriptionMessage(length, fieldCount); + this.reader.setBuffer(offset, bytes) + const fieldCount = this.reader.int16() + const message = new RowDescriptionMessage(length, fieldCount) for (let i = 0; i < fieldCount; i++) { - message.fields[i] = this.parseField(); + message.fields[i] = this.parseField() } - return message; + return message } private parseField(): Field { - const name = this.reader.cstring(); - const tableID = this.reader.int32(); - const columnID = this.reader.int16(); - const dataTypeID = this.reader.int32(); - const dataTypeSize = this.reader.int16(); - const dataTypeModifier = this.reader.int32(); - const mode = this.reader.int16() === 0 ? 'text' : 'binary'; - return new Field(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, mode); + const name = this.reader.cstring() + const tableID = this.reader.int32() + const columnID = this.reader.int16() + const dataTypeID = this.reader.int32() + const dataTypeSize = this.reader.int16() + const dataTypeModifier = this.reader.int32() + const mode = this.reader.int16() === 0 ? 'text' : 'binary' + return new Field(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, mode) } private parseDataRowMessage(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); - const fieldCount = this.reader.int16(); - const fields: any[] = new Array(fieldCount); + this.reader.setBuffer(offset, bytes) + const fieldCount = this.reader.int16() + const fields: any[] = new Array(fieldCount) for (let i = 0; i < fieldCount; i++) { - const len = this.reader.int32(); + const len = this.reader.int32() // a -1 for length means the value of the field is null - fields[i] = len === -1 ? null : this.reader.string(len); + fields[i] = len === -1 ? null : this.reader.string(len) } - return new DataRowMessage(length, fields); + return new DataRowMessage(length, fields) } private parseParameterStatusMessage(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); - const name = this.reader.cstring(); - const value = this.reader.cstring(); - return new ParameterStatusMessage(length, name, value); + this.reader.setBuffer(offset, bytes) + const name = this.reader.cstring() + const value = this.reader.cstring() + return new ParameterStatusMessage(length, name, value) } private parseBackendKeyData(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); - const processID = this.reader.int32(); - const secretKey = this.reader.int32(); - return new BackendKeyDataMessage(length, processID, secretKey); + this.reader.setBuffer(offset, bytes) + const processID = this.reader.int32() + const secretKey = this.reader.int32() + return new BackendKeyDataMessage(length, processID, secretKey) } public parseAuthenticationResponse(offset: number, length: number, bytes: Buffer) { - this.reader.setBuffer(offset, bytes); - const code = this.reader.int32(); + this.reader.setBuffer(offset, bytes) + const code = this.reader.int32() // TODO(bmc): maybe better types here const message: BackendMessage & any = { name: MessageName.authenticationOk, length, - }; + } switch (code) { case 0: // AuthenticationOk - break; + break case 3: // AuthenticationCleartextPassword if (message.length === 8) { - message.name = MessageName.authenticationCleartextPassword; + message.name = MessageName.authenticationCleartextPassword } - break; + break case 5: // AuthenticationMD5Password if (message.length === 12) { - message.name = MessageName.authenticationMD5Password; - const salt = this.reader.bytes(4); - return new AuthenticationMD5Password(length, salt); + message.name = MessageName.authenticationMD5Password + const salt = this.reader.bytes(4) + return new AuthenticationMD5Password(length, salt) } - break; + break case 10: // AuthenticationSASL - message.name = MessageName.authenticationSASL; - message.mechanisms = []; - let mechanism: string; + message.name = MessageName.authenticationSASL + message.mechanisms = [] + let mechanism: string do { - mechanism = this.reader.cstring(); + mechanism = this.reader.cstring() if (mechanism) { - message.mechanisms.push(mechanism); + message.mechanisms.push(mechanism) } - } while (mechanism); - break; + } while (mechanism) + break case 11: // AuthenticationSASLContinue - message.name = MessageName.authenticationSASLContinue; - message.data = this.reader.string(length - 4); - break; + message.name = MessageName.authenticationSASLContinue + message.data = this.reader.string(length - 4) + break case 12: // AuthenticationSASLFinal - message.name = MessageName.authenticationSASLFinal; - message.data = this.reader.string(length - 4); - break; + message.name = MessageName.authenticationSASLFinal + message.data = this.reader.string(length - 4) + break default: - throw new Error('Unknown authenticationOk message type ' + code); + throw new Error('Unknown authenticationOk message type ' + code) } - return message; + return message } private parseErrorMessage(offset: number, length: number, bytes: Buffer, name: MessageName) { - this.reader.setBuffer(offset, bytes); - const fields: Record = {}; - let fieldType = this.reader.string(1); + this.reader.setBuffer(offset, bytes) + const fields: Record = {} + let fieldType = this.reader.string(1) while (fieldType !== '\0') { - fields[fieldType] = this.reader.cstring(); - fieldType = this.reader.string(1); + fields[fieldType] = this.reader.cstring() + fieldType = this.reader.string(1) } - const messageValue = fields.M; + const messageValue = fields.M const message = name === MessageName.notice ? new NoticeMessage(length, messageValue) - : new DatabaseError(messageValue, length, name); - - message.severity = fields.S; - message.code = fields.C; - message.detail = fields.D; - message.hint = fields.H; - message.position = fields.P; - message.internalPosition = fields.p; - message.internalQuery = fields.q; - message.where = fields.W; - message.schema = fields.s; - message.table = fields.t; - message.column = fields.c; - message.dataType = fields.d; - message.constraint = fields.n; - message.file = fields.F; - message.line = fields.L; - message.routine = fields.R; - return message; + : new DatabaseError(messageValue, length, name) + + message.severity = fields.S + message.code = fields.C + message.detail = fields.D + message.hint = fields.H + message.position = fields.P + message.internalPosition = fields.p + message.internalQuery = fields.q + message.where = fields.W + message.schema = fields.s + message.table = fields.t + message.column = fields.c + message.dataType = fields.d + message.constraint = fields.n + message.file = fields.F + message.line = fields.L + message.routine = fields.R + return message } } diff --git a/packages/pg-protocol/src/serializer.ts b/packages/pg-protocol/src/serializer.ts index 904875dd1..00e43fffe 100644 --- a/packages/pg-protocol/src/serializer.ts +++ b/packages/pg-protocol/src/serializer.ts @@ -1,4 +1,4 @@ -import { Writer } from './buffer-writer'; +import { Writer } from './buffer-writer' const enum code { startup = 0x70, @@ -16,58 +16,58 @@ const enum code { copyFail = 0x66, } -const writer = new Writer(); +const writer = new Writer() const startup = (opts: Record): Buffer => { // protocol version - writer.addInt16(3).addInt16(0); + writer.addInt16(3).addInt16(0) for (const key of Object.keys(opts)) { - writer.addCString(key).addCString(opts[key]); + writer.addCString(key).addCString(opts[key]) } - writer.addCString('client_encoding').addCString("'utf-8'"); + writer.addCString('client_encoding').addCString("'utf-8'") - var bodyBuffer = writer.addCString('').flush(); + var bodyBuffer = writer.addCString('').flush() // this message is sent without a code - var length = bodyBuffer.length + 4; + var length = bodyBuffer.length + 4 - return new Writer().addInt32(length).add(bodyBuffer).flush(); -}; + return new Writer().addInt32(length).add(bodyBuffer).flush() +} const requestSsl = (): Buffer => { - const response = Buffer.allocUnsafe(8); - response.writeInt32BE(8, 0); - response.writeInt32BE(80877103, 4); - return response; -}; + const response = Buffer.allocUnsafe(8) + response.writeInt32BE(8, 0) + response.writeInt32BE(80877103, 4) + return response +} const password = (password: string): Buffer => { - return writer.addCString(password).flush(code.startup); -}; + return writer.addCString(password).flush(code.startup) +} const sendSASLInitialResponseMessage = function (mechanism: string, initialResponse: string): Buffer { // 0x70 = 'p' - writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse); + writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse) - return writer.flush(code.startup); -}; + return writer.flush(code.startup) +} const sendSCRAMClientFinalMessage = function (additionalData: string): Buffer { - return writer.addString(additionalData).flush(code.startup); -}; + return writer.addString(additionalData).flush(code.startup) +} const query = (text: string): Buffer => { - return writer.addCString(text).flush(code.query); -}; + return writer.addCString(text).flush(code.query) +} type ParseOpts = { - name?: string; - types?: number[]; - text: string; -}; + name?: string + types?: number[] + text: string +} -const emptyArray: any[] = []; +const emptyArray: any[] = [] const parse = (query: ParseOpts): Buffer => { // expect something like this: @@ -76,169 +76,169 @@ const parse = (query: ParseOpts): Buffer => { // types: ['int8', 'bool'] } // normalize missing query names to allow for null - const name = query.name || ''; + const name = query.name || '' if (name.length > 63) { /* eslint-disable no-console */ - console.error('Warning! Postgres only supports 63 characters for query names.'); - console.error('You supplied %s (%s)', name, name.length); - console.error('This can cause conflicts and silent errors executing queries'); + console.error('Warning! Postgres only supports 63 characters for query names.') + console.error('You supplied %s (%s)', name, name.length) + console.error('This can cause conflicts and silent errors executing queries') /* eslint-enable no-console */ } - const types = query.types || emptyArray; + const types = query.types || emptyArray - var len = types.length; + var len = types.length var buffer = writer .addCString(name) // name of query .addCString(query.text) // actual query text - .addInt16(len); + .addInt16(len) for (var i = 0; i < len; i++) { - buffer.addInt32(types[i]); + buffer.addInt32(types[i]) } - return writer.flush(code.parse); -}; + return writer.flush(code.parse) +} type BindOpts = { - portal?: string; - binary?: boolean; - statement?: string; - values?: any[]; -}; + portal?: string + binary?: boolean + statement?: string + values?: any[] +} const bind = (config: BindOpts = {}): Buffer => { // normalize config - const portal = config.portal || ''; - const statement = config.statement || ''; - const binary = config.binary || false; - var values = config.values || emptyArray; - var len = values.length; + const portal = config.portal || '' + const statement = config.statement || '' + const binary = config.binary || false + var values = config.values || emptyArray + var len = values.length - var useBinary = false; + var useBinary = false // TODO(bmc): all the loops in here aren't nice, we can do better for (var j = 0; j < len; j++) { - useBinary = useBinary || values[j] instanceof Buffer; + useBinary = useBinary || values[j] instanceof Buffer } - var buffer = writer.addCString(portal).addCString(statement); + var buffer = writer.addCString(portal).addCString(statement) if (!useBinary) { - buffer.addInt16(0); + buffer.addInt16(0) } else { - buffer.addInt16(len); + buffer.addInt16(len) for (j = 0; j < len; j++) { - buffer.addInt16(values[j] instanceof Buffer ? 1 : 0); + buffer.addInt16(values[j] instanceof Buffer ? 1 : 0) } } - buffer.addInt16(len); + buffer.addInt16(len) for (var i = 0; i < len; i++) { - var val = values[i]; + var val = values[i] if (val === null || typeof val === 'undefined') { - buffer.addInt32(-1); + buffer.addInt32(-1) } else if (val instanceof Buffer) { - buffer.addInt32(val.length); - buffer.add(val); + buffer.addInt32(val.length) + buffer.add(val) } else { - buffer.addInt32(Buffer.byteLength(val)); - buffer.addString(val); + buffer.addInt32(Buffer.byteLength(val)) + buffer.addString(val) } } if (binary) { - buffer.addInt16(1); // format codes to use binary - buffer.addInt16(1); + buffer.addInt16(1) // format codes to use binary + buffer.addInt16(1) } else { - buffer.addInt16(0); // format codes to use text + buffer.addInt16(0) // format codes to use text } - return writer.flush(code.bind); -}; + return writer.flush(code.bind) +} type ExecOpts = { - portal?: string; - rows?: number; -}; + portal?: string + rows?: number +} -const emptyExecute = Buffer.from([code.execute, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00]); +const emptyExecute = Buffer.from([code.execute, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00]) const execute = (config?: ExecOpts): Buffer => { // this is the happy path for most queries if (!config || (!config.portal && !config.rows)) { - return emptyExecute; + return emptyExecute } - const portal = config.portal || ''; - const rows = config.rows || 0; + const portal = config.portal || '' + const rows = config.rows || 0 - const portalLength = Buffer.byteLength(portal); - const len = 4 + portalLength + 1 + 4; + const portalLength = Buffer.byteLength(portal) + const len = 4 + portalLength + 1 + 4 // one extra bit for code - const buff = Buffer.allocUnsafe(1 + len); - buff[0] = code.execute; - buff.writeInt32BE(len, 1); - buff.write(portal, 5, 'utf-8'); - buff[portalLength + 5] = 0; // null terminate portal cString - buff.writeUInt32BE(rows, buff.length - 4); - return buff; -}; + const buff = Buffer.allocUnsafe(1 + len) + buff[0] = code.execute + buff.writeInt32BE(len, 1) + buff.write(portal, 5, 'utf-8') + buff[portalLength + 5] = 0 // null terminate portal cString + buff.writeUInt32BE(rows, buff.length - 4) + return buff +} const cancel = (processID: number, secretKey: number): Buffer => { - const buffer = Buffer.allocUnsafe(16); - buffer.writeInt32BE(16, 0); - buffer.writeInt16BE(1234, 4); - buffer.writeInt16BE(5678, 6); - buffer.writeInt32BE(processID, 8); - buffer.writeInt32BE(secretKey, 12); - return buffer; -}; + const buffer = Buffer.allocUnsafe(16) + buffer.writeInt32BE(16, 0) + buffer.writeInt16BE(1234, 4) + buffer.writeInt16BE(5678, 6) + buffer.writeInt32BE(processID, 8) + buffer.writeInt32BE(secretKey, 12) + return buffer +} type PortalOpts = { - type: 'S' | 'P'; - name?: string; -}; + type: 'S' | 'P' + name?: string +} const cstringMessage = (code: code, string: string): Buffer => { - const stringLen = Buffer.byteLength(string); - const len = 4 + stringLen + 1; + const stringLen = Buffer.byteLength(string) + const len = 4 + stringLen + 1 // one extra bit for code - const buffer = Buffer.allocUnsafe(1 + len); - buffer[0] = code; - buffer.writeInt32BE(len, 1); - buffer.write(string, 5, 'utf-8'); - buffer[len] = 0; // null terminate cString - return buffer; -}; + const buffer = Buffer.allocUnsafe(1 + len) + buffer[0] = code + buffer.writeInt32BE(len, 1) + buffer.write(string, 5, 'utf-8') + buffer[len] = 0 // null terminate cString + return buffer +} -const emptyDescribePortal = writer.addCString('P').flush(code.describe); -const emptyDescribeStatement = writer.addCString('S').flush(code.describe); +const emptyDescribePortal = writer.addCString('P').flush(code.describe) +const emptyDescribeStatement = writer.addCString('S').flush(code.describe) const describe = (msg: PortalOpts): Buffer => { return msg.name ? cstringMessage(code.describe, `${msg.type}${msg.name || ''}`) : msg.type === 'P' ? emptyDescribePortal - : emptyDescribeStatement; -}; + : emptyDescribeStatement +} const close = (msg: PortalOpts): Buffer => { - const text = `${msg.type}${msg.name || ''}`; - return cstringMessage(code.close, text); -}; + const text = `${msg.type}${msg.name || ''}` + return cstringMessage(code.close, text) +} const copyData = (chunk: Buffer): Buffer => { - return writer.add(chunk).flush(code.copyFromChunk); -}; + return writer.add(chunk).flush(code.copyFromChunk) +} const copyFail = (message: string): Buffer => { - return cstringMessage(code.copyFail, message); -}; + return cstringMessage(code.copyFail, message) +} -const codeOnlyBuffer = (code: code): Buffer => Buffer.from([code, 0x00, 0x00, 0x00, 0x04]); +const codeOnlyBuffer = (code: code): Buffer => Buffer.from([code, 0x00, 0x00, 0x00, 0x04]) -const flushBuffer = codeOnlyBuffer(code.flush); -const syncBuffer = codeOnlyBuffer(code.sync); -const endBuffer = codeOnlyBuffer(code.end); -const copyDoneBuffer = codeOnlyBuffer(code.copyDone); +const flushBuffer = codeOnlyBuffer(code.flush) +const syncBuffer = codeOnlyBuffer(code.sync) +const endBuffer = codeOnlyBuffer(code.end) +const copyDoneBuffer = codeOnlyBuffer(code.copyDone) const serialize = { startup, @@ -259,6 +259,6 @@ const serialize = { copyDone: () => copyDoneBuffer, copyFail, cancel, -}; +} -export { serialize }; +export { serialize } diff --git a/packages/pg-protocol/src/testing/buffer-list.ts b/packages/pg-protocol/src/testing/buffer-list.ts index d7c7e4574..15ac785cc 100644 --- a/packages/pg-protocol/src/testing/buffer-list.ts +++ b/packages/pg-protocol/src/testing/buffer-list.ts @@ -2,74 +2,74 @@ export default class BufferList { constructor(public buffers: Buffer[] = []) {} public add(buffer: Buffer, front?: boolean) { - this.buffers[front ? 'unshift' : 'push'](buffer); - return this; + this.buffers[front ? 'unshift' : 'push'](buffer) + return this } public addInt16(val: number, front?: boolean) { - return this.add(Buffer.from([val >>> 8, val >>> 0]), front); + return this.add(Buffer.from([val >>> 8, val >>> 0]), front) } public getByteLength(initial?: number) { return this.buffers.reduce(function (previous, current) { - return previous + current.length; - }, initial || 0); + return previous + current.length + }, initial || 0) } public addInt32(val: number, first?: boolean) { return this.add( Buffer.from([(val >>> 24) & 0xff, (val >>> 16) & 0xff, (val >>> 8) & 0xff, (val >>> 0) & 0xff]), first - ); + ) } public addCString(val: string, front?: boolean) { - var len = Buffer.byteLength(val); - var buffer = Buffer.alloc(len + 1); - buffer.write(val); - buffer[len] = 0; - return this.add(buffer, front); + var len = Buffer.byteLength(val) + var buffer = Buffer.alloc(len + 1) + buffer.write(val) + buffer[len] = 0 + return this.add(buffer, front) } public addString(val: string, front?: boolean) { - var len = Buffer.byteLength(val); - var buffer = Buffer.alloc(len); - buffer.write(val); - return this.add(buffer, front); + var len = Buffer.byteLength(val) + var buffer = Buffer.alloc(len) + buffer.write(val) + return this.add(buffer, front) } public addChar(char: string, first?: boolean) { - return this.add(Buffer.from(char, 'utf8'), first); + return this.add(Buffer.from(char, 'utf8'), first) } public addByte(byte: number) { - return this.add(Buffer.from([byte])); + return this.add(Buffer.from([byte])) } public join(appendLength?: boolean, char?: string): Buffer { - var length = this.getByteLength(); + var length = this.getByteLength() if (appendLength) { - this.addInt32(length + 4, true); - return this.join(false, char); + this.addInt32(length + 4, true) + return this.join(false, char) } if (char) { - this.addChar(char, true); - length++; + this.addChar(char, true) + length++ } - var result = Buffer.alloc(length); - var index = 0; + var result = Buffer.alloc(length) + var index = 0 this.buffers.forEach(function (buffer) { - buffer.copy(result, index, 0); - index += buffer.length; - }); - return result; + buffer.copy(result, index, 0) + index += buffer.length + }) + return result } public static concat(): Buffer { - var total = new BufferList(); + var total = new BufferList() for (var i = 0; i < arguments.length; i++) { - total.add(arguments[i]); + total.add(arguments[i]) } - return total.join(); + return total.join() } } diff --git a/packages/pg-protocol/src/testing/test-buffers.ts b/packages/pg-protocol/src/testing/test-buffers.ts index 32384976e..19ba16cce 100644 --- a/packages/pg-protocol/src/testing/test-buffers.ts +++ b/packages/pg-protocol/src/testing/test-buffers.ts @@ -1,54 +1,54 @@ // http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html -import BufferList from './buffer-list'; +import BufferList from './buffer-list' const buffers = { readyForQuery: function () { - return new BufferList().add(Buffer.from('I')).join(true, 'Z'); + return new BufferList().add(Buffer.from('I')).join(true, 'Z') }, authenticationOk: function () { - return new BufferList().addInt32(0).join(true, 'R'); + return new BufferList().addInt32(0).join(true, 'R') }, authenticationCleartextPassword: function () { - return new BufferList().addInt32(3).join(true, 'R'); + return new BufferList().addInt32(3).join(true, 'R') }, authenticationMD5Password: function () { return new BufferList() .addInt32(5) .add(Buffer.from([1, 2, 3, 4])) - .join(true, 'R'); + .join(true, 'R') }, authenticationSASL: function () { - return new BufferList().addInt32(10).addCString('SCRAM-SHA-256').addCString('').join(true, 'R'); + return new BufferList().addInt32(10).addCString('SCRAM-SHA-256').addCString('').join(true, 'R') }, authenticationSASLContinue: function () { - return new BufferList().addInt32(11).addString('data').join(true, 'R'); + return new BufferList().addInt32(11).addString('data').join(true, 'R') }, authenticationSASLFinal: function () { - return new BufferList().addInt32(12).addString('data').join(true, 'R'); + return new BufferList().addInt32(12).addString('data').join(true, 'R') }, parameterStatus: function (name: string, value: string) { - return new BufferList().addCString(name).addCString(value).join(true, 'S'); + return new BufferList().addCString(name).addCString(value).join(true, 'S') }, backendKeyData: function (processID: number, secretKey: number) { - return new BufferList().addInt32(processID).addInt32(secretKey).join(true, 'K'); + return new BufferList().addInt32(processID).addInt32(secretKey).join(true, 'K') }, commandComplete: function (string: string) { - return new BufferList().addCString(string).join(true, 'C'); + return new BufferList().addCString(string).join(true, 'C') }, rowDescription: function (fields: any[]) { - fields = fields || []; - var buf = new BufferList(); - buf.addInt16(fields.length); + fields = fields || [] + var buf = new BufferList() + buf.addInt16(fields.length) fields.forEach(function (field) { buf .addCString(field.name) @@ -57,67 +57,67 @@ const buffers = { .addInt32(field.dataTypeID || 0) .addInt16(field.dataTypeSize || 0) .addInt32(field.typeModifier || 0) - .addInt16(field.formatCode || 0); - }); - return buf.join(true, 'T'); + .addInt16(field.formatCode || 0) + }) + return buf.join(true, 'T') }, dataRow: function (columns: any[]) { - columns = columns || []; - var buf = new BufferList(); - buf.addInt16(columns.length); + columns = columns || [] + var buf = new BufferList() + buf.addInt16(columns.length) columns.forEach(function (col) { if (col == null) { - buf.addInt32(-1); + buf.addInt32(-1) } else { - var strBuf = Buffer.from(col, 'utf8'); - buf.addInt32(strBuf.length); - buf.add(strBuf); + var strBuf = Buffer.from(col, 'utf8') + buf.addInt32(strBuf.length) + buf.add(strBuf) } - }); - return buf.join(true, 'D'); + }) + return buf.join(true, 'D') }, error: function (fields: any) { - return buffers.errorOrNotice(fields).join(true, 'E'); + return buffers.errorOrNotice(fields).join(true, 'E') }, notice: function (fields: any) { - return buffers.errorOrNotice(fields).join(true, 'N'); + return buffers.errorOrNotice(fields).join(true, 'N') }, errorOrNotice: function (fields: any) { - fields = fields || []; - var buf = new BufferList(); + fields = fields || [] + var buf = new BufferList() fields.forEach(function (field: any) { - buf.addChar(field.type); - buf.addCString(field.value); - }); - return buf.add(Buffer.from([0])); // terminator + buf.addChar(field.type) + buf.addCString(field.value) + }) + return buf.add(Buffer.from([0])) // terminator }, parseComplete: function () { - return new BufferList().join(true, '1'); + return new BufferList().join(true, '1') }, bindComplete: function () { - return new BufferList().join(true, '2'); + return new BufferList().join(true, '2') }, notification: function (id: number, channel: string, payload: string) { - return new BufferList().addInt32(id).addCString(channel).addCString(payload).join(true, 'A'); + return new BufferList().addInt32(id).addCString(channel).addCString(payload).join(true, 'A') }, emptyQuery: function () { - return new BufferList().join(true, 'I'); + return new BufferList().join(true, 'I') }, portalSuspended: function () { - return new BufferList().join(true, 's'); + return new BufferList().join(true, 's') }, closeComplete: function () { - return new BufferList().join(true, '3'); + return new BufferList().join(true, '3') }, copyIn: function (cols: number) { @@ -125,11 +125,11 @@ const buffers = { // text mode .addByte(0) // column count - .addInt16(cols); + .addInt16(cols) for (let i = 0; i < cols; i++) { - list.addInt16(i); + list.addInt16(i) } - return list.join(true, 'G'); + return list.join(true, 'G') }, copyOut: function (cols: number) { @@ -137,20 +137,20 @@ const buffers = { // text mode .addByte(0) // column count - .addInt16(cols); + .addInt16(cols) for (let i = 0; i < cols; i++) { - list.addInt16(i); + list.addInt16(i) } - return list.join(true, 'H'); + return list.join(true, 'H') }, copyData: function (bytes: Buffer) { - return new BufferList().add(bytes).join(true, 'd'); + return new BufferList().add(bytes).join(true, 'd') }, copyDone: function () { - return new BufferList().join(true, 'c'); + return new BufferList().join(true, 'c') }, -}; +} -export default buffers; +export default buffers diff --git a/packages/pg-protocol/src/types/chunky.d.ts b/packages/pg-protocol/src/types/chunky.d.ts index 914ce06b1..7389bda66 100644 --- a/packages/pg-protocol/src/types/chunky.d.ts +++ b/packages/pg-protocol/src/types/chunky.d.ts @@ -1 +1 @@ -declare module 'chunky'; +declare module 'chunky' diff --git a/packages/pg-query-stream/index.js b/packages/pg-query-stream/index.js index 01903cc3c..914a7e32b 100644 --- a/packages/pg-query-stream/index.js +++ b/packages/pg-query-stream/index.js @@ -1,31 +1,31 @@ -const { Readable } = require('stream'); -const Cursor = require('pg-cursor'); +const { Readable } = require('stream') +const Cursor = require('pg-cursor') class PgQueryStream extends Readable { constructor(text, values, config = {}) { - const { batchSize, highWaterMark = 100 } = config; + const { batchSize, highWaterMark = 100 } = config // https://nodejs.org/api/stream.html#stream_new_stream_readable_options - super({ objectMode: true, emitClose: true, autoDestroy: true, highWaterMark: batchSize || highWaterMark }); - this.cursor = new Cursor(text, values, config); + super({ objectMode: true, emitClose: true, autoDestroy: true, highWaterMark: batchSize || highWaterMark }) + this.cursor = new Cursor(text, values, config) // delegate Submittable callbacks to cursor - this.handleRowDescription = this.cursor.handleRowDescription.bind(this.cursor); - this.handleDataRow = this.cursor.handleDataRow.bind(this.cursor); - this.handlePortalSuspended = this.cursor.handlePortalSuspended.bind(this.cursor); - this.handleCommandComplete = this.cursor.handleCommandComplete.bind(this.cursor); - this.handleReadyForQuery = this.cursor.handleReadyForQuery.bind(this.cursor); - this.handleError = this.cursor.handleError.bind(this.cursor); - this.handleEmptyQuery = this.cursor.handleEmptyQuery.bind(this.cursor); + this.handleRowDescription = this.cursor.handleRowDescription.bind(this.cursor) + this.handleDataRow = this.cursor.handleDataRow.bind(this.cursor) + this.handlePortalSuspended = this.cursor.handlePortalSuspended.bind(this.cursor) + this.handleCommandComplete = this.cursor.handleCommandComplete.bind(this.cursor) + this.handleReadyForQuery = this.cursor.handleReadyForQuery.bind(this.cursor) + this.handleError = this.cursor.handleError.bind(this.cursor) + this.handleEmptyQuery = this.cursor.handleEmptyQuery.bind(this.cursor) } submit(connection) { - this.cursor.submit(connection); + this.cursor.submit(connection) } _destroy(_err, cb) { this.cursor.close((err) => { - cb(err || _err); - }); + cb(err || _err) + }) } // https://nodejs.org/api/stream.html#stream_readable_read_size_1 @@ -33,13 +33,13 @@ class PgQueryStream extends Readable { this.cursor.read(size, (err, rows, result) => { if (err) { // https://nodejs.org/api/stream.html#stream_errors_while_reading - this.destroy(err); + this.destroy(err) } else { - for (const row of rows) this.push(row); - if (rows.length < size) this.push(null); + for (const row of rows) this.push(row) + if (rows.length < size) this.push(null) } - }); + }) } } -module.exports = PgQueryStream; +module.exports = PgQueryStream diff --git a/packages/pg-query-stream/test/async-iterator.js b/packages/pg-query-stream/test/async-iterator.js index 63acb99b3..19718fe3b 100644 --- a/packages/pg-query-stream/test/async-iterator.js +++ b/packages/pg-query-stream/test/async-iterator.js @@ -1,4 +1,4 @@ // only newer versions of node support async iterator if (!process.version.startsWith('v8')) { - require('./async-iterator.es6'); + require('./async-iterator.es6') } diff --git a/packages/pg-query-stream/test/close.js b/packages/pg-query-stream/test/close.js index d1d38f747..4a95464a7 100644 --- a/packages/pg-query-stream/test/close.js +++ b/packages/pg-query-stream/test/close.js @@ -1,91 +1,91 @@ -var assert = require('assert'); -var concat = require('concat-stream'); +var assert = require('assert') +var concat = require('concat-stream') -var QueryStream = require('../'); -var helper = require('./helper'); +var QueryStream = require('../') +var helper = require('./helper') if (process.version.startsWith('v8.')) { - console.error('warning! node less than 10lts stream closing semantics may not behave properly'); + console.error('warning! node less than 10lts stream closing semantics may not behave properly') } else { helper('close', function (client) { it('emits close', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], { batchSize: 2, highWaterMark: 2 }); - var query = client.query(stream); - query.pipe(concat(function () {})); - query.on('close', done); - }); - }); + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], { batchSize: 2, highWaterMark: 2 }) + var query = client.query(stream) + query.pipe(concat(function () {})) + query.on('close', done) + }) + }) helper('early close', function (client) { it('can be closed early', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [20000], { batchSize: 2, highWaterMark: 2, - }); - var query = client.query(stream); - var readCount = 0; + }) + var query = client.query(stream) + var readCount = 0 query.on('readable', function () { - readCount++; - query.read(); - }); + readCount++ + query.read() + }) query.once('readable', function () { - query.destroy(); - }); + query.destroy() + }) query.on('close', function () { - assert(readCount < 10, 'should not have read more than 10 rows'); - done(); - }); - }); + assert(readCount < 10, 'should not have read more than 10 rows') + done() + }) + }) it('can destroy stream while reading', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)'); - client.query(stream); - stream.on('data', () => done(new Error('stream should not have returned rows'))); + var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') + client.query(stream) + stream.on('data', () => done(new Error('stream should not have returned rows'))) setTimeout(() => { - stream.destroy(); - stream.on('close', done); - }, 100); - }); + stream.destroy() + stream.on('close', done) + }, 100) + }) it('emits an error when calling destroy with an error', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)'); - client.query(stream); - stream.on('data', () => done(new Error('stream should not have returned rows'))); + var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') + client.query(stream) + stream.on('data', () => done(new Error('stream should not have returned rows'))) setTimeout(() => { - stream.destroy(new Error('intentional error')); + stream.destroy(new Error('intentional error')) stream.on('error', (err) => { // make sure there's an error - assert(err); - assert.strictEqual(err.message, 'intentional error'); - done(); - }); - }, 100); - }); + assert(err) + assert.strictEqual(err.message, 'intentional error') + done() + }) + }, 100) + }) it('can destroy stream while reading an error', function (done) { - var stream = new QueryStream('SELECT * from pg_sleep(1), basdfasdf;'); - client.query(stream); - stream.on('data', () => done(new Error('stream should not have returned rows'))); + var stream = new QueryStream('SELECT * from pg_sleep(1), basdfasdf;') + client.query(stream) + stream.on('data', () => done(new Error('stream should not have returned rows'))) stream.once('error', () => { - stream.destroy(); + stream.destroy() // wait a bit to let any other errors shake through - setTimeout(done, 100); - }); - }); + setTimeout(done, 100) + }) + }) it('does not crash when destroying the stream immediately after calling read', function (done) { - var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);'); - client.query(stream); - stream.on('data', () => done(new Error('stream should not have returned rows'))); - stream.destroy(); - stream.on('close', done); - }); + var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') + client.query(stream) + stream.on('data', () => done(new Error('stream should not have returned rows'))) + stream.destroy() + stream.on('close', done) + }) it('does not crash when destroying the stream before its submitted', function (done) { - var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);'); - stream.on('data', () => done(new Error('stream should not have returned rows'))); - stream.destroy(); - stream.on('close', done); - }); - }); + var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') + stream.on('data', () => done(new Error('stream should not have returned rows'))) + stream.destroy() + stream.on('close', done) + }) + }) } diff --git a/packages/pg-query-stream/test/concat.js b/packages/pg-query-stream/test/concat.js index bf479d328..6ce17a28e 100644 --- a/packages/pg-query-stream/test/concat.js +++ b/packages/pg-query-stream/test/concat.js @@ -1,28 +1,28 @@ -var assert = require('assert'); -var concat = require('concat-stream'); -var through = require('through'); -var helper = require('./helper'); +var assert = require('assert') +var concat = require('concat-stream') +var through = require('through') +var helper = require('./helper') -var QueryStream = require('../'); +var QueryStream = require('../') helper('concat', function (client) { it('concats correctly', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []); - var query = client.query(stream); + var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) + var query = client.query(stream) query .pipe( through(function (row) { - this.push(row.num); + this.push(row.num) }) ) .pipe( concat(function (result) { var total = result.reduce(function (prev, cur) { - return prev + cur; - }); - assert.equal(total, 20100); + return prev + cur + }) + assert.equal(total, 20100) }) - ); - stream.on('end', done); - }); -}); + ) + stream.on('end', done) + }) +}) diff --git a/packages/pg-query-stream/test/config.js b/packages/pg-query-stream/test/config.js index 859f7064b..061fb1153 100644 --- a/packages/pg-query-stream/test/config.js +++ b/packages/pg-query-stream/test/config.js @@ -1,26 +1,26 @@ -var assert = require('assert'); -var QueryStream = require('../'); +var assert = require('assert') +var QueryStream = require('../') describe('stream config options', () => { // this is mostly for backwards compatability. it('sets readable.highWaterMark based on batch size', () => { var stream = new QueryStream('SELECT NOW()', [], { batchSize: 88, - }); - assert.equal(stream._readableState.highWaterMark, 88); - }); + }) + assert.equal(stream._readableState.highWaterMark, 88) + }) it('sets readable.highWaterMark based on highWaterMark config', () => { var stream = new QueryStream('SELECT NOW()', [], { highWaterMark: 88, - }); + }) - assert.equal(stream._readableState.highWaterMark, 88); - }); + assert.equal(stream._readableState.highWaterMark, 88) + }) it('defaults to 100 for highWaterMark', () => { - var stream = new QueryStream('SELECT NOW()', []); + var stream = new QueryStream('SELECT NOW()', []) - assert.equal(stream._readableState.highWaterMark, 100); - }); -}); + assert.equal(stream._readableState.highWaterMark, 100) + }) +}) diff --git a/packages/pg-query-stream/test/empty-query.js b/packages/pg-query-stream/test/empty-query.js index 8e45f6823..25f7d6956 100644 --- a/packages/pg-query-stream/test/empty-query.js +++ b/packages/pg-query-stream/test/empty-query.js @@ -1,22 +1,22 @@ -const assert = require('assert'); -const helper = require('./helper'); -const QueryStream = require('../'); +const assert = require('assert') +const helper = require('./helper') +const QueryStream = require('../') helper('empty-query', function (client) { it('handles empty query', function (done) { - const stream = new QueryStream('-- this is a comment', []); - const query = client.query(stream); + const stream = new QueryStream('-- this is a comment', []) + const query = client.query(stream) query .on('end', function () { // nothing should happen for empty query - done(); + done() }) .on('data', function () { // noop to kick off reading - }); - }); + }) + }) it('continues to function after stream', function (done) { - client.query('SELECT NOW()', done); - }); -}); + client.query('SELECT NOW()', done) + }) +}) diff --git a/packages/pg-query-stream/test/error.js b/packages/pg-query-stream/test/error.js index 848915dc2..0b732923d 100644 --- a/packages/pg-query-stream/test/error.js +++ b/packages/pg-query-stream/test/error.js @@ -1,24 +1,24 @@ -var assert = require('assert'); -var helper = require('./helper'); +var assert = require('assert') +var helper = require('./helper') -var QueryStream = require('../'); +var QueryStream = require('../') helper('error', function (client) { it('receives error on stream', function (done) { - var stream = new QueryStream('SELECT * FROM asdf num', []); - var query = client.query(stream); + var stream = new QueryStream('SELECT * FROM asdf num', []) + var query = client.query(stream) query .on('error', function (err) { - assert(err); - assert.equal(err.code, '42P01'); - done(); + assert(err) + assert.equal(err.code, '42P01') + done() }) .on('data', function () { // noop to kick of reading - }); - }); + }) + }) it('continues to function after stream', function (done) { - client.query('SELECT NOW()', done); - }); -}); + client.query('SELECT NOW()', done) + }) +}) diff --git a/packages/pg-query-stream/test/fast-reader.js b/packages/pg-query-stream/test/fast-reader.js index 54e47c3b2..4c6f31f95 100644 --- a/packages/pg-query-stream/test/fast-reader.js +++ b/packages/pg-query-stream/test/fast-reader.js @@ -1,35 +1,35 @@ -var assert = require('assert'); -var helper = require('./helper'); -var QueryStream = require('../'); +var assert = require('assert') +var helper = require('./helper') +var QueryStream = require('../') helper('fast reader', function (client) { it('works', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []); - var query = client.query(stream); - var result = []; + var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) + var query = client.query(stream) + var result = [] stream.on('readable', function () { - var res = stream.read(); + var res = stream.read() while (res) { if (result.length !== 201) { - assert(res, 'should not return null on evented reader'); + assert(res, 'should not return null on evented reader') } else { // a readable stream will emit a null datum when it finishes being readable // https://nodejs.org/api/stream.html#stream_event_readable - assert.equal(res, null); + assert.equal(res, null) } if (res) { - result.push(res.num); + result.push(res.num) } - res = stream.read(); + res = stream.read() } - }); + }) stream.on('end', function () { var total = result.reduce(function (prev, cur) { - return prev + cur; - }); - assert.equal(total, 20100); - done(); - }); - assert.strictEqual(query.read(2), null); - }); -}); + return prev + cur + }) + assert.equal(total, 20100) + done() + }) + assert.strictEqual(query.read(2), null) + }) +}) diff --git a/packages/pg-query-stream/test/helper.js b/packages/pg-query-stream/test/helper.js index 87bf32377..ad21d6ea2 100644 --- a/packages/pg-query-stream/test/helper.js +++ b/packages/pg-query-stream/test/helper.js @@ -1,17 +1,17 @@ -var pg = require('pg'); +var pg = require('pg') module.exports = function (name, cb) { describe(name, function () { - var client = new pg.Client(); + var client = new pg.Client() before(function (done) { - client.connect(done); - }); + client.connect(done) + }) - cb(client); + cb(client) after(function (done) { - client.end(); - client.on('end', done); - }); - }); -}; + client.end() + client.on('end', done) + }) + }) +} diff --git a/packages/pg-query-stream/test/instant.js b/packages/pg-query-stream/test/instant.js index 984e90038..0939753bb 100644 --- a/packages/pg-query-stream/test/instant.js +++ b/packages/pg-query-stream/test/instant.js @@ -1,17 +1,17 @@ -var assert = require('assert'); -var concat = require('concat-stream'); +var assert = require('assert') +var concat = require('concat-stream') -var QueryStream = require('../'); +var QueryStream = require('../') require('./helper')('instant', function (client) { it('instant', function (done) { - var query = new QueryStream('SELECT pg_sleep(1)', []); - var stream = client.query(query); + var query = new QueryStream('SELECT pg_sleep(1)', []) + var stream = client.query(query) stream.pipe( concat(function (res) { - assert.equal(res.length, 1); - done(); + assert.equal(res.length, 1) + done() }) - ); - }); -}); + ) + }) +}) diff --git a/packages/pg-query-stream/test/issue-3.js b/packages/pg-query-stream/test/issue-3.js index 608f9f715..7b467a3b3 100644 --- a/packages/pg-query-stream/test/issue-3.js +++ b/packages/pg-query-stream/test/issue-3.js @@ -1,32 +1,32 @@ -var pg = require('pg'); -var QueryStream = require('../'); +var pg = require('pg') +var QueryStream = require('../') describe('end semantics race condition', function () { before(function (done) { - var client = new pg.Client(); - client.connect(); - client.on('drain', client.end.bind(client)); - client.on('end', done); - client.query('create table IF NOT EXISTS p(id serial primary key)'); - client.query('create table IF NOT EXISTS c(id int primary key references p)'); - }); + var client = new pg.Client() + client.connect() + client.on('drain', client.end.bind(client)) + client.on('end', done) + client.query('create table IF NOT EXISTS p(id serial primary key)') + client.query('create table IF NOT EXISTS c(id int primary key references p)') + }) it('works', function (done) { - var client1 = new pg.Client(); - client1.connect(); - var client2 = new pg.Client(); - client2.connect(); + var client1 = new pg.Client() + client1.connect() + var client2 = new pg.Client() + client2.connect() - var qr = new QueryStream('INSERT INTO p DEFAULT VALUES RETURNING id'); - client1.query(qr); - var id = null; + var qr = new QueryStream('INSERT INTO p DEFAULT VALUES RETURNING id') + client1.query(qr) + var id = null qr.on('data', function (row) { - id = row.id; - }); + id = row.id + }) qr.on('end', function () { client2.query('INSERT INTO c(id) VALUES ($1)', [id], function (err, rows) { - client1.end(); - client2.end(); - done(err); - }); - }); - }); -}); + client1.end() + client2.end() + done(err) + }) + }) + }) +}) diff --git a/packages/pg-query-stream/test/passing-options.js b/packages/pg-query-stream/test/passing-options.js index bed59272b..858767de2 100644 --- a/packages/pg-query-stream/test/passing-options.js +++ b/packages/pg-query-stream/test/passing-options.js @@ -1,38 +1,38 @@ -var assert = require('assert'); -var helper = require('./helper'); -var QueryStream = require('../'); +var assert = require('assert') +var helper = require('./helper') +var QueryStream = require('../') helper('passing options', function (client) { it('passes row mode array', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { rowMode: 'array' }); - var query = client.query(stream); - var result = []; + var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { rowMode: 'array' }) + var query = client.query(stream) + var result = [] query.on('data', (datum) => { - result.push(datum); - }); + result.push(datum) + }) query.on('end', () => { - const expected = new Array(11).fill(0).map((_, i) => [i]); - assert.deepEqual(result, expected); - done(); - }); - }); + const expected = new Array(11).fill(0).map((_, i) => [i]) + assert.deepEqual(result, expected) + done() + }) + }) it('passes custom types', function (done) { const types = { getTypeParser: () => (string) => string, - }; - var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { types }); - var query = client.query(stream); - var result = []; + } + var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { types }) + var query = client.query(stream) + var result = [] query.on('data', (datum) => { - result.push(datum); - }); + result.push(datum) + }) query.on('end', () => { const expected = new Array(11).fill(0).map((_, i) => ({ num: i.toString(), - })); - assert.deepEqual(result, expected); - done(); - }); - }); -}); + })) + assert.deepEqual(result, expected) + done() + }) + }) +}) diff --git a/packages/pg-query-stream/test/pauses.js b/packages/pg-query-stream/test/pauses.js index 83f290a60..3da9a0b07 100644 --- a/packages/pg-query-stream/test/pauses.js +++ b/packages/pg-query-stream/test/pauses.js @@ -1,23 +1,23 @@ -var concat = require('concat-stream'); -var tester = require('stream-tester'); -var JSONStream = require('JSONStream'); +var concat = require('concat-stream') +var tester = require('stream-tester') +var JSONStream = require('JSONStream') -var QueryStream = require('../'); +var QueryStream = require('../') require('./helper')('pauses', function (client) { it('pauses', function (done) { - this.timeout(5000); - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], { batchSize: 2, highWaterMark: 2 }); - var query = client.query(stream); - var pauser = tester.createPauseStream(0.1, 100); + this.timeout(5000) + var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], { batchSize: 2, highWaterMark: 2 }) + var query = client.query(stream) + var pauser = tester.createPauseStream(0.1, 100) query .pipe(JSONStream.stringify()) .pipe(pauser) .pipe( concat(function (json) { - JSON.parse(json); - done(); + JSON.parse(json) + done() }) - ); - }); -}); + ) + }) +}) diff --git a/packages/pg-query-stream/test/slow-reader.js b/packages/pg-query-stream/test/slow-reader.js index b5524b8f1..3978f3004 100644 --- a/packages/pg-query-stream/test/slow-reader.js +++ b/packages/pg-query-stream/test/slow-reader.js @@ -1,31 +1,31 @@ -var helper = require('./helper'); -var QueryStream = require('../'); -var concat = require('concat-stream'); +var helper = require('./helper') +var QueryStream = require('../') +var concat = require('concat-stream') -var Transform = require('stream').Transform; +var Transform = require('stream').Transform -var mapper = new Transform({ objectMode: true }); +var mapper = new Transform({ objectMode: true }) mapper._transform = function (obj, enc, cb) { - this.push(obj); - setTimeout(cb, 5); -}; + this.push(obj) + setTimeout(cb, 5) +} helper('slow reader', function (client) { it('works', function (done) { - this.timeout(50000); + this.timeout(50000) var stream = new QueryStream('SELECT * FROM generate_series(0, 201) num', [], { highWaterMark: 100, batchSize: 50, - }); + }) stream.on('end', function () { // console.log('stream end') - }); - client.query(stream); + }) + client.query(stream) stream.pipe(mapper).pipe( concat(function (res) { - done(); + done() }) - ); - }); -}); + ) + }) +}) diff --git a/packages/pg-query-stream/test/stream-tester-timestamp.js b/packages/pg-query-stream/test/stream-tester-timestamp.js index ef2182c1d..ce989cc3f 100644 --- a/packages/pg-query-stream/test/stream-tester-timestamp.js +++ b/packages/pg-query-stream/test/stream-tester-timestamp.js @@ -1,25 +1,25 @@ -var QueryStream = require('../'); -var spec = require('stream-spec'); -var assert = require('assert'); +var QueryStream = require('../') +var spec = require('stream-spec') +var assert = require('assert') require('./helper')('stream tester timestamp', function (client) { it('should not warn about max listeners', function (done) { - var sql = "SELECT * FROM generate_series('1983-12-30 00:00'::timestamp, '2013-12-30 00:00', '1 years')"; - var stream = new QueryStream(sql, []); - var ended = false; - var query = client.query(stream); + var sql = "SELECT * FROM generate_series('1983-12-30 00:00'::timestamp, '2013-12-30 00:00', '1 years')" + var stream = new QueryStream(sql, []) + var ended = false + var query = client.query(stream) query.on('end', function () { - ended = true; - }); - spec(query).readable().pausable({ strict: true }).validateOnExit(); + ended = true + }) + spec(query).readable().pausable({ strict: true }).validateOnExit() var checkListeners = function () { - assert(stream.listeners('end').length < 10); + assert(stream.listeners('end').length < 10) if (!ended) { - setImmediate(checkListeners); + setImmediate(checkListeners) } else { - done(); + done() } - }; - checkListeners(); - }); -}); + } + checkListeners() + }) +}) diff --git a/packages/pg-query-stream/test/stream-tester.js b/packages/pg-query-stream/test/stream-tester.js index 0769d7189..f5ab2e372 100644 --- a/packages/pg-query-stream/test/stream-tester.js +++ b/packages/pg-query-stream/test/stream-tester.js @@ -1,12 +1,12 @@ -var spec = require('stream-spec'); +var spec = require('stream-spec') -var QueryStream = require('../'); +var QueryStream = require('../') require('./helper')('stream tester', function (client) { it('passes stream spec', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []); - var query = client.query(stream); - spec(query).readable().pausable({ strict: true }).validateOnExit(); - stream.on('end', done); - }); -}); + var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) + var query = client.query(stream) + spec(query).readable().pausable({ strict: true }).validateOnExit() + stream.on('end', done) + }) +}) diff --git a/packages/pg/bench.js b/packages/pg/bench.js index 4fde9170f..80c07dc19 100644 --- a/packages/pg/bench.js +++ b/packages/pg/bench.js @@ -1,69 +1,69 @@ -const pg = require("./lib"); +const pg = require('./lib') const pool = new pg.Pool() const params = { text: - "select typname, typnamespace, typowner, typlen, typbyval, typcategory, typispreferred, typisdefined, typdelim, typrelid, typelem, typarray from pg_type where typtypmod = $1 and typisdefined = $2", - values: [-1, true] -}; + 'select typname, typnamespace, typowner, typlen, typbyval, typcategory, typispreferred, typisdefined, typdelim, typrelid, typelem, typarray from pg_type where typtypmod = $1 and typisdefined = $2', + values: [-1, true], +} const insert = { text: 'INSERT INTO foobar(name, age) VALUES ($1, $2)', - values: ['brian', 100] + values: ['brian', 100], } const seq = { - text: 'SELECT * FROM generate_series(1, 1000)' + text: 'SELECT * FROM generate_series(1, 1000)', } const exec = async (client, q) => { const result = await client.query({ text: q.text, values: q.values, - rowMode: "array" - }); -}; + rowMode: 'array', + }) +} const bench = async (client, q, time) => { - let start = Date.now(); - let count = 0; + let start = Date.now() + let count = 0 while (true) { - await exec(client, q); - count++; + await exec(client, q) + count++ if (Date.now() - start > time) { - return count; + return count } } -}; +} const run = async () => { - const client = new pg.Client(); - await client.connect(); + const client = new pg.Client() + await client.connect() await client.query('CREATE TEMP TABLE foobar(name TEXT, age NUMERIC)') - await bench(client, params, 1000); - console.log("warmup done"); - const seconds = 5; + await bench(client, params, 1000) + console.log('warmup done') + const seconds = 5 - let queries = await bench(client, params, seconds * 1000); + let queries = await bench(client, params, seconds * 1000) console.log('') - console.log("little queries:", queries); - console.log("qps", queries / seconds); - console.log("on my laptop best so far seen 733 qps") + console.log('little queries:', queries) + console.log('qps', queries / seconds) + console.log('on my laptop best so far seen 733 qps') console.log('') - queries = await bench(client, seq, seconds * 1000); - console.log("sequence queries:", queries); - console.log("qps", queries / seconds); - console.log("on my laptop best so far seen 1309 qps") + queries = await bench(client, seq, seconds * 1000) + console.log('sequence queries:', queries) + console.log('qps', queries / seconds) + console.log('on my laptop best so far seen 1309 qps') console.log('') - queries = await bench(client, insert, seconds * 1000); - console.log("insert queries:", queries); - console.log("qps", queries / seconds); - console.log("on my laptop best so far seen 5799 qps") + queries = await bench(client, insert, seconds * 1000) + console.log('insert queries:', queries) + console.log('qps', queries / seconds) + console.log('on my laptop best so far seen 5799 qps') console.log() - await client.end(); - await client.end(); -}; + await client.end() + await client.end() +} -run().catch(e => console.error(e) || process.exit(-1)); +run().catch((e) => console.error(e) || process.exit(-1)) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index ac7ab4c27..04124f8a0 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -37,7 +37,7 @@ var Client = function (config) { configurable: true, enumerable: false, writable: true, - value: this.connectionParameters.password + value: this.connectionParameters.password, }) this.replication = this.connectionParameters.replication @@ -52,13 +52,15 @@ var Client = function (config) { this._connectionError = false this._queryable = true - this.connection = c.connection || new Connection({ - stream: c.stream, - ssl: this.connectionParameters.ssl, - keepAlive: c.keepAlive || false, - keepAliveInitialDelayMillis: c.keepAliveInitialDelayMillis || 0, - encoding: this.connectionParameters.client_encoding || 'utf8' - }) + this.connection = + c.connection || + new Connection({ + stream: c.stream, + ssl: this.connectionParameters.ssl, + keepAlive: c.keepAlive || false, + keepAliveInitialDelayMillis: c.keepAliveInitialDelayMillis || 0, + encoding: this.connectionParameters.client_encoding || 'utf8', + }) this.queryQueue = [] this.binary = c.binary || defaults.binary this.processID = null @@ -127,9 +129,10 @@ Client.prototype._connect = function (callback) { function checkPgPass(cb) { return function (msg) { if (typeof self.password === 'function') { - self._Promise.resolve() + self._Promise + .resolve() .then(() => self.password()) - .then(pass => { + .then((pass) => { if (pass !== undefined) { if (typeof pass !== 'string') { con.emit('error', new TypeError('Password must be a string')) @@ -140,7 +143,8 @@ Client.prototype._connect = function (callback) { self.connectionParameters.password = self.password = null } cb(msg) - }).catch(err => { + }) + .catch((err) => { con.emit('error', err) }) } else if (self.password !== null) { @@ -157,22 +161,31 @@ Client.prototype._connect = function (callback) { } // password request handling - con.on('authenticationCleartextPassword', checkPgPass(function () { - con.password(self.password) - })) + con.on( + 'authenticationCleartextPassword', + checkPgPass(function () { + con.password(self.password) + }) + ) // password request handling - con.on('authenticationMD5Password', checkPgPass(function (msg) { - con.password(utils.postgresMd5PasswordHash(self.user, self.password, msg.salt)) - })) + con.on( + 'authenticationMD5Password', + checkPgPass(function (msg) { + con.password(utils.postgresMd5PasswordHash(self.user, self.password, msg.salt)) + }) + ) // password request handling (SASL) var saslSession - con.on('authenticationSASL', checkPgPass(function (msg) { - saslSession = sasl.startSession(msg.mechanisms) + con.on( + 'authenticationSASL', + checkPgPass(function (msg) { + saslSession = sasl.startSession(msg.mechanisms) - con.sendSASLInitialResponseMessage(saslSession.mechanism, saslSession.response) - })) + con.sendSASLInitialResponseMessage(saslSession.mechanism, saslSession.response) + }) + ) // password request handling (SASL) con.on('authenticationSASLContinue', function (msg) { @@ -259,9 +272,7 @@ Client.prototype._connect = function (callback) { }) con.once('end', () => { - const error = this._ending - ? new Error('Connection terminated') - : new Error('Connection terminated unexpectedly') + const error = this._ending ? new Error('Connection terminated') : new Error('Connection terminated unexpectedly') clearTimeout(connectionTimeoutHandle) this._errorAllQueries(error) @@ -367,7 +378,7 @@ Client.prototype.getStartupConf = function () { var data = { user: params.user, - database: params.database + database: params.database, } var appName = params.application_name || params.fallback_application_name @@ -422,11 +433,11 @@ Client.prototype.escapeIdentifier = function (str) { // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c Client.prototype.escapeLiteral = function (str) { var hasBackslash = false - var escaped = '\'' + var escaped = "'" for (var i = 0; i < str.length; i++) { var c = str[i] - if (c === '\'') { + if (c === "'") { escaped += c + c } else if (c === '\\') { escaped += c + c @@ -436,7 +447,7 @@ Client.prototype.escapeLiteral = function (str) { } } - escaped += '\'' + escaped += "'" if (hasBackslash === true) { escaped = ' E' + escaped @@ -488,7 +499,7 @@ Client.prototype.query = function (config, values, callback) { query = new Query(config, values, callback) if (!query.callback) { result = new this._Promise((resolve, reject) => { - query.callback = (err, res) => err ? reject(err) : resolve(res) + query.callback = (err, res) => (err ? reject(err) : resolve(res)) }) } } @@ -507,7 +518,7 @@ Client.prototype.query = function (config, values, callback) { // we already returned an error, // just do nothing if query completes - query.callback = () => { } + query.callback = () => {} // Remove from queue var index = this.queryQueue.indexOf(query) diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index 71ef63ba6..acc5c0e8c 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -80,14 +80,18 @@ Connection.prototype.connect = function (port, host) { case 'N': // Server does not support SSL connections self.stream.end() return self.emit('error', new Error('The server does not support SSL connections')) - default: // Any other response byte, including 'E' (ErrorResponse) indicating a server error + default: + // Any other response byte, including 'E' (ErrorResponse) indicating a server error self.stream.end() return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') - const options = Object.assign({ - socket: self.stream - }, self.ssl) + const options = Object.assign( + { + socket: self.stream, + }, + self.ssl + ) if (net.isIP(host) === 0) { options.servername = host } diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index cd6d3b8a9..b34e0df5f 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -22,9 +22,7 @@ var val = function (key, config, envVar) { envVar = process.env[envVar] } - return config[key] || - envVar || - defaults[key] + return config[key] || envVar || defaults[key] } var useSsl = function () { @@ -66,7 +64,7 @@ var ConnectionParameters = function (config) { configurable: true, enumerable: false, writable: true, - value: val('password', config) + value: val('password', config), }) this.binary = val('binary', config) @@ -74,7 +72,7 @@ var ConnectionParameters = function (config) { this.client_encoding = val('client_encoding', config) this.replication = val('replication', config) // a domain socket begins with '/' - this.isDomainSocket = (!(this.host || '').indexOf('/')) + this.isDomainSocket = !(this.host || '').indexOf('/') this.application_name = val('application_name', config, 'PGAPPNAME') this.fallback_application_name = val('fallback_application_name', config, false) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index b7fde90a2..243872c93 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -35,7 +35,7 @@ var Connection = function (config) { this._emitMessage = false this._reader = new Reader({ headerSize: 1, - lengthPadding: -4 + lengthPadding: -4, }) var self = this this.on('newListener', function (eventName) { @@ -88,14 +88,18 @@ Connection.prototype.connect = function (port, host) { case 'N': // Server does not support SSL connections self.stream.end() return self.emit('error', new Error('The server does not support SSL connections')) - default: // Any other response byte, including 'E' (ErrorResponse) indicating a server error + default: + // Any other response byte, including 'E' (ErrorResponse) indicating a server error self.stream.end() return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') - const options = Object.assign({ - socket: self.stream - }, self.ssl) + const options = Object.assign( + { + socket: self.stream, + }, + self.ssl + ) if (net.isIP(host) === 0) { options.servername = host } @@ -127,23 +131,16 @@ Connection.prototype.attachListeners = function (stream) { } Connection.prototype.requestSsl = function () { - var bodyBuffer = this.writer - .addInt16(0x04D2) - .addInt16(0x162F).flush() + var bodyBuffer = this.writer.addInt16(0x04d2).addInt16(0x162f).flush() var length = bodyBuffer.length + 4 - var buffer = new Writer() - .addInt32(length) - .add(bodyBuffer) - .join() + var buffer = new Writer().addInt32(length).add(bodyBuffer).join() this.stream.write(buffer) } Connection.prototype.startup = function (config) { - var writer = this.writer - .addInt16(3) - .addInt16(0) + var writer = this.writer.addInt16(3).addInt16(0) Object.keys(config).forEach(function (key) { var val = config[key] @@ -157,27 +154,16 @@ Connection.prototype.startup = function (config) { var length = bodyBuffer.length + 4 - var buffer = new Writer() - .addInt32(length) - .add(bodyBuffer) - .join() + var buffer = new Writer().addInt32(length).add(bodyBuffer).join() this.stream.write(buffer) } Connection.prototype.cancel = function (processID, secretKey) { - var bodyBuffer = this.writer - .addInt16(1234) - .addInt16(5678) - .addInt32(processID) - .addInt32(secretKey) - .flush() + var bodyBuffer = this.writer.addInt16(1234).addInt16(5678).addInt32(processID).addInt32(secretKey).flush() var length = bodyBuffer.length + 4 - var buffer = new Writer() - .addInt32(length) - .add(bodyBuffer) - .join() + var buffer = new Writer().addInt32(length).add(bodyBuffer).join() this.stream.write(buffer) } @@ -188,18 +174,14 @@ Connection.prototype.password = function (password) { Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) { // 0x70 = 'p' - this.writer - .addCString(mechanism) - .addInt32(Buffer.byteLength(initialResponse)) - .addString(initialResponse) + this.writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse) this._send(0x70) } Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) { // 0x70 = 'p' - this.writer - .addString(additionalData) + this.writer.addString(additionalData) this._send(0x70) } @@ -263,13 +245,17 @@ Connection.prototype.bind = function (config, more) { var values = config.values || [] var len = values.length var useBinary = false - for (var j = 0; j < len; j++) { useBinary |= values[j] instanceof Buffer } - var buffer = this.writer - .addCString(config.portal) - .addCString(config.statement) - if (!useBinary) { buffer.addInt16(0) } else { + for (var j = 0; j < len; j++) { + useBinary |= values[j] instanceof Buffer + } + var buffer = this.writer.addCString(config.portal).addCString(config.statement) + if (!useBinary) { + buffer.addInt16(0) + } else { buffer.addInt16(len) - for (j = 0; j < len; j++) { buffer.addInt16(values[j] instanceof Buffer) } + for (j = 0; j < len; j++) { + buffer.addInt16(values[j] instanceof Buffer) + } } buffer.addInt16(len) for (var i = 0; i < len; i++) { @@ -301,9 +287,7 @@ Connection.prototype.execute = function (config, more) { config = config || {} config.portal = config.portal || '' config.rows = config.rows || '' - this.writer - .addCString(config.portal) - .addInt32(config.rows) + this.writer.addCString(config.portal).addInt32(config.rows) // 0x45 = 'E' this._send(0x45, more) diff --git a/packages/pg/lib/defaults.js b/packages/pg/lib/defaults.js index eb58550d6..394216680 100644 --- a/packages/pg/lib/defaults.js +++ b/packages/pg/lib/defaults.js @@ -70,7 +70,7 @@ module.exports = { keepalives: 1, - keepalives_idle: 0 + keepalives_idle: 0, } var pgTypes = require('pg-types') diff --git a/packages/pg/lib/index.js b/packages/pg/lib/index.js index c73064cf2..975175cd4 100644 --- a/packages/pg/lib/index.js +++ b/packages/pg/lib/index.js @@ -14,7 +14,7 @@ var Pool = require('pg-pool') const poolFactory = (Client) => { return class BoundPool extends Pool { - constructor (options) { + constructor(options) { super(options, Client) } } @@ -54,10 +54,10 @@ if (typeof process.env.NODE_PG_FORCE_NATIVE !== 'undefined') { // overwrite module.exports.native so that getter is never called again Object.defineProperty(module.exports, 'native', { - value: native + value: native, }) return native - } + }, }) } diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index 165147f9b..f45546151 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -22,7 +22,7 @@ assert(semver.gte(Native.version, pkg.minNativeVersion), msg) var NativeQuery = require('./query') -var Client = module.exports = function (config) { +var Client = (module.exports = function (config) { EventEmitter.call(this) config = config || {} @@ -30,7 +30,7 @@ var Client = module.exports = function (config) { this._types = new TypeOverrides(config.types) this.native = new Native({ - types: this._types + types: this._types, }) this._queryQueue = [] @@ -41,7 +41,7 @@ var Client = module.exports = function (config) { // keep these on the object for legacy reasons // for the time being. TODO: deprecate all this jazz - var cp = this.connectionParameters = new ConnectionParameters(config) + var cp = (this.connectionParameters = new ConnectionParameters(config)) this.user = cp.user // "hiding" the password so it doesn't show up in stack traces @@ -50,7 +50,7 @@ var Client = module.exports = function (config) { configurable: true, enumerable: false, writable: true, - value: cp.password + value: cp.password, }) this.database = cp.database this.host = cp.host @@ -58,7 +58,7 @@ var Client = module.exports = function (config) { // a hash to hold named queries this.namedQueries = {} -} +}) Client.Query = NativeQuery @@ -115,7 +115,7 @@ Client.prototype._connect = function (cb) { self.native.on('notification', function (msg) { self.emit('notification', { channel: msg.relname, - payload: msg.extra + payload: msg.extra, }) }) @@ -180,7 +180,7 @@ Client.prototype.query = function (config, values, callback) { resolveOut = resolve rejectOut = reject }) - query.callback = (err, res) => err ? rejectOut(err) : resolveOut(res) + query.callback = (err, res) => (err ? rejectOut(err) : resolveOut(res)) } } @@ -248,7 +248,7 @@ Client.prototype.end = function (cb) { var result if (!cb) { result = new this._Promise(function (resolve, reject) { - cb = (err) => err ? reject(err) : resolve() + cb = (err) => (err ? reject(err) : resolve()) }) } this.native.end(function () { diff --git a/packages/pg/lib/native/query.js b/packages/pg/lib/native/query.js index 0c83e27e3..de443489a 100644 --- a/packages/pg/lib/native/query.js +++ b/packages/pg/lib/native/query.js @@ -11,7 +11,7 @@ var EventEmitter = require('events').EventEmitter var util = require('util') var utils = require('../utils') -var NativeQuery = module.exports = function (config, values, callback) { +var NativeQuery = (module.exports = function (config, values, callback) { EventEmitter.call(this) config = utils.normalizeQueryConfig(config, values, callback) this.text = config.text @@ -27,27 +27,30 @@ var NativeQuery = module.exports = function (config, values, callback) { // this has almost no meaning because libpq // reads all rows into memory befor returning any this._emitRowEvents = false - this.on('newListener', function (event) { - if (event === 'row') this._emitRowEvents = true - }.bind(this)) -} + this.on( + 'newListener', + function (event) { + if (event === 'row') this._emitRowEvents = true + }.bind(this) + ) +}) util.inherits(NativeQuery, EventEmitter) var errorFieldMap = { /* eslint-disable quote-props */ - 'sqlState': 'code', - 'statementPosition': 'position', - 'messagePrimary': 'message', - 'context': 'where', - 'schemaName': 'schema', - 'tableName': 'table', - 'columnName': 'column', - 'dataTypeName': 'dataType', - 'constraintName': 'constraint', - 'sourceFile': 'file', - 'sourceLine': 'line', - 'sourceFunction': 'routine' + sqlState: 'code', + statementPosition: 'position', + messagePrimary: 'message', + context: 'where', + schemaName: 'schema', + tableName: 'table', + columnName: 'column', + dataTypeName: 'dataType', + constraintName: 'constraint', + sourceFile: 'file', + sourceLine: 'line', + sourceFunction: 'routine', } NativeQuery.prototype.handleError = function (err) { @@ -77,10 +80,12 @@ NativeQuery.prototype.catch = function (callback) { NativeQuery.prototype._getPromise = function () { if (this._promise) return this._promise - this._promise = new Promise(function (resolve, reject) { - this._once('end', resolve) - this._once('error', reject) - }.bind(this)) + this._promise = new Promise( + function (resolve, reject) { + this._once('end', resolve) + this._once('error', reject) + }.bind(this) + ) return this._promise } @@ -105,7 +110,7 @@ NativeQuery.prototype.submit = function (client) { if (self._emitRowEvents) { if (results.length > 1) { rows.forEach((rowOfRows, i) => { - rowOfRows.forEach(row => { + rowOfRows.forEach((row) => { self.emit('row', row, results[i]) }) }) diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index 4fcfe391e..2392b710e 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -42,14 +42,22 @@ class Query extends EventEmitter { requiresPreparation() { // named queries must always be prepared - if (this.name) { return true } + if (this.name) { + return true + } // always prepare if there are max number of rows expected per // portal execution - if (this.rows) { return true } + if (this.rows) { + return true + } // don't prepare empty text queries - if (!this.text) { return false } + if (!this.text) { + return false + } // prepare if there are values - if (!this.values) { return false } + if (!this.values) { + return false + } return this.values.length > 0 } @@ -168,10 +176,13 @@ class Query extends EventEmitter { } _getRows(connection, rows) { - connection.execute({ - portal: this.portal, - rows: rows - }, true) + connection.execute( + { + portal: this.portal, + rows: rows, + }, + true + ) connection.flush() } @@ -181,11 +192,14 @@ class Query extends EventEmitter { this.isPreparedStatement = true // TODO refactor this poor encapsulation if (!this.hasBeenParsed(connection)) { - connection.parse({ - text: this.text, - name: this.name, - types: this.types - }, true) + connection.parse( + { + text: this.text, + name: this.name, + types: this.types, + }, + true + ) } if (this.values) { @@ -198,17 +212,23 @@ class Query extends EventEmitter { } // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY - connection.bind({ - portal: this.portal, - statement: this.name, - values: this.values, - binary: this.binary - }, true) - - connection.describe({ - type: 'P', - name: this.portal || '' - }, true) + connection.bind( + { + portal: this.portal, + statement: this.name, + values: this.values, + binary: this.binary, + }, + true + ) + + connection.describe( + { + type: 'P', + name: this.portal || '', + }, + true + ) this._getRows(connection, this.rows) } diff --git a/packages/pg/lib/sasl.js b/packages/pg/lib/sasl.js index 39c24bb33..22abf5c4a 100644 --- a/packages/pg/lib/sasl.js +++ b/packages/pg/lib/sasl.js @@ -1,7 +1,7 @@ 'use strict' const crypto = require('crypto') -function startSession (mechanisms) { +function startSession(mechanisms) { if (mechanisms.indexOf('SCRAM-SHA-256') === -1) { throw new Error('SASL: Only mechanism SCRAM-SHA-256 is currently supported') } @@ -12,11 +12,11 @@ function startSession (mechanisms) { mechanism: 'SCRAM-SHA-256', clientNonce, response: 'n,,n=*,r=' + clientNonce, - message: 'SASLInitialResponse' + message: 'SASLInitialResponse', } } -function continueSession (session, password, serverData) { +function continueSession(session, password, serverData) { if (session.message !== 'SASLInitialResponse') { throw new Error('SASL: Last message was not SASLInitialResponse') } @@ -53,42 +53,46 @@ function continueSession (session, password, serverData) { session.response = clientFinalMessageWithoutProof + ',p=' + clientProof } -function finalizeSession (session, serverData) { +function finalizeSession(session, serverData) { if (session.message !== 'SASLResponse') { throw new Error('SASL: Last message was not SASLResponse') } var serverSignature - String(serverData).split(',').forEach(function (part) { - switch (part[0]) { - case 'v': - serverSignature = part.substr(2) - break - } - }) + String(serverData) + .split(',') + .forEach(function (part) { + switch (part[0]) { + case 'v': + serverSignature = part.substr(2) + break + } + }) if (serverSignature !== session.serverSignature) { throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature does not match') } } -function extractVariablesFromFirstServerMessage (data) { +function extractVariablesFromFirstServerMessage(data) { var nonce, salt, iteration - String(data).split(',').forEach(function (part) { - switch (part[0]) { - case 'r': - nonce = part.substr(2) - break - case 's': - salt = part.substr(2) - break - case 'i': - iteration = parseInt(part.substr(2), 10) - break - } - }) + String(data) + .split(',') + .forEach(function (part) { + switch (part[0]) { + case 'r': + nonce = part.substr(2) + break + case 's': + salt = part.substr(2) + break + case 'i': + iteration = parseInt(part.substr(2), 10) + break + } + }) if (!nonce) { throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing') @@ -105,11 +109,11 @@ function extractVariablesFromFirstServerMessage (data) { return { nonce, salt, - iteration + iteration, } } -function xorBuffers (a, b) { +function xorBuffers(a, b) { if (!Buffer.isBuffer(a)) a = Buffer.from(a) if (!Buffer.isBuffer(b)) b = Buffer.from(b) var res = [] @@ -125,11 +129,11 @@ function xorBuffers (a, b) { return Buffer.from(res) } -function createHMAC (key, msg) { +function createHMAC(key, msg) { return crypto.createHmac('sha256', key).update(msg).digest() } -function Hi (password, saltBytes, iterations) { +function Hi(password, saltBytes, iterations) { var ui1 = createHMAC(password, Buffer.concat([saltBytes, Buffer.from([0, 0, 0, 1])])) var ui = ui1 for (var i = 0; i < iterations - 1; i++) { @@ -143,5 +147,5 @@ function Hi (password, saltBytes, iterations) { module.exports = { startSession, continueSession, - finalizeSession + finalizeSession, } diff --git a/packages/pg/lib/type-overrides.js b/packages/pg/lib/type-overrides.js index 543944062..63bfc83e1 100644 --- a/packages/pg/lib/type-overrides.js +++ b/packages/pg/lib/type-overrides.js @@ -9,7 +9,7 @@ var types = require('pg-types') -function TypeOverrides (userTypes) { +function TypeOverrides(userTypes) { this._types = userTypes || types this.text = {} this.binary = {} @@ -17,9 +17,12 @@ function TypeOverrides (userTypes) { TypeOverrides.prototype.getOverrides = function (format) { switch (format) { - case 'text': return this.text - case 'binary': return this.binary - default: return {} + case 'text': + return this.text + case 'binary': + return this.binary + default: + return {} } } diff --git a/packages/pg/lib/utils.js b/packages/pg/lib/utils.js index 879949f0c..f6da81f47 100644 --- a/packages/pg/lib/utils.js +++ b/packages/pg/lib/utils.js @@ -11,10 +11,8 @@ const crypto = require('crypto') const defaults = require('./defaults') -function escapeElement (elementRepresentation) { - var escaped = elementRepresentation - .replace(/\\/g, '\\\\') - .replace(/"/g, '\\"') +function escapeElement(elementRepresentation) { + var escaped = elementRepresentation.replace(/\\/g, '\\\\').replace(/"/g, '\\"') return '"' + escaped + '"' } @@ -22,7 +20,7 @@ function escapeElement (elementRepresentation) { // convert a JS array to a postgres array literal // uses comma separator so won't work for types like box that use // a different array separator. -function arrayString (val) { +function arrayString(val) { var result = '{' for (var i = 0; i < val.length; i++) { if (i > 0) { @@ -76,7 +74,7 @@ var prepareValue = function (val, seen) { return val.toString() } -function prepareObject (val, seen) { +function prepareObject(val, seen) { if (val && typeof val.toPostgres === 'function') { seen = seen || [] if (seen.indexOf(val) !== -1) { @@ -89,48 +87,66 @@ function prepareObject (val, seen) { return JSON.stringify(val) } -function pad (number, digits) { +function pad(number, digits) { number = '' + number - while (number.length < digits) { number = '0' + number } + while (number.length < digits) { + number = '0' + number + } return number } -function dateToString (date) { +function dateToString(date) { var offset = -date.getTimezoneOffset() var year = date.getFullYear() var isBCYear = year < 1 if (isBCYear) year = Math.abs(year) + 1 // negative years are 1 off their BC representation - var ret = pad(year, 4) + '-' + - pad(date.getMonth() + 1, 2) + '-' + - pad(date.getDate(), 2) + 'T' + - pad(date.getHours(), 2) + ':' + - pad(date.getMinutes(), 2) + ':' + - pad(date.getSeconds(), 2) + '.' + + var ret = + pad(year, 4) + + '-' + + pad(date.getMonth() + 1, 2) + + '-' + + pad(date.getDate(), 2) + + 'T' + + pad(date.getHours(), 2) + + ':' + + pad(date.getMinutes(), 2) + + ':' + + pad(date.getSeconds(), 2) + + '.' + pad(date.getMilliseconds(), 3) if (offset < 0) { ret += '-' offset *= -1 - } else { ret += '+' } + } else { + ret += '+' + } ret += pad(Math.floor(offset / 60), 2) + ':' + pad(offset % 60, 2) if (isBCYear) ret += ' BC' return ret } -function dateToStringUTC (date) { +function dateToStringUTC(date) { var year = date.getUTCFullYear() var isBCYear = year < 1 if (isBCYear) year = Math.abs(year) + 1 // negative years are 1 off their BC representation - var ret = pad(year, 4) + '-' + - pad(date.getUTCMonth() + 1, 2) + '-' + - pad(date.getUTCDate(), 2) + 'T' + - pad(date.getUTCHours(), 2) + ':' + - pad(date.getUTCMinutes(), 2) + ':' + - pad(date.getUTCSeconds(), 2) + '.' + + var ret = + pad(year, 4) + + '-' + + pad(date.getUTCMonth() + 1, 2) + + '-' + + pad(date.getUTCDate(), 2) + + 'T' + + pad(date.getUTCHours(), 2) + + ':' + + pad(date.getUTCMinutes(), 2) + + ':' + + pad(date.getUTCSeconds(), 2) + + '.' + pad(date.getUTCMilliseconds(), 3) ret += '+00:00' @@ -138,9 +154,9 @@ function dateToStringUTC (date) { return ret } -function normalizeQueryConfig (config, values, callback) { +function normalizeQueryConfig(config, values, callback) { // can take in strings or config objects - config = (typeof (config) === 'string') ? { text: config } : config + config = typeof config === 'string' ? { text: config } : config if (values) { if (typeof values === 'function') { config.callback = values @@ -166,12 +182,12 @@ const postgresMd5PasswordHash = function (user, password, salt) { } module.exports = { - prepareValue: function prepareValueWrapper (value) { + prepareValue: function prepareValueWrapper(value) { // this ensures that extra arguments do not get passed into prepareValue // by accident, eg: from calling values.map(utils.prepareValue) return prepareValue(value) }, normalizeQueryConfig, postgresMd5PasswordHash, - md5 + md5, } diff --git a/packages/pg/script/create-test-tables.js b/packages/pg/script/create-test-tables.js index e2110313a..6db5fea7c 100644 --- a/packages/pg/script/create-test-tables.js +++ b/packages/pg/script/create-test-tables.js @@ -3,32 +3,32 @@ var args = require(__dirname + '/../test/cli') var pg = require(__dirname + '/../lib') var people = [ - {name: 'Aaron', age: 10}, - {name: 'Brian', age: 20}, - {name: 'Chris', age: 30}, - {name: 'David', age: 40}, - {name: 'Elvis', age: 50}, - {name: 'Frank', age: 60}, - {name: 'Grace', age: 70}, - {name: 'Haley', age: 80}, - {name: 'Irma', age: 90}, - {name: 'Jenny', age: 100}, - {name: 'Kevin', age: 110}, - {name: 'Larry', age: 120}, - {name: 'Michelle', age: 130}, - {name: 'Nancy', age: 140}, - {name: 'Olivia', age: 150}, - {name: 'Peter', age: 160}, - {name: 'Quinn', age: 170}, - {name: 'Ronda', age: 180}, - {name: 'Shelley', age: 190}, - {name: 'Tobias', age: 200}, - {name: 'Uma', age: 210}, - {name: 'Veena', age: 220}, - {name: 'Wanda', age: 230}, - {name: 'Xavier', age: 240}, - {name: 'Yoyo', age: 250}, - {name: 'Zanzabar', age: 260} + { name: 'Aaron', age: 10 }, + { name: 'Brian', age: 20 }, + { name: 'Chris', age: 30 }, + { name: 'David', age: 40 }, + { name: 'Elvis', age: 50 }, + { name: 'Frank', age: 60 }, + { name: 'Grace', age: 70 }, + { name: 'Haley', age: 80 }, + { name: 'Irma', age: 90 }, + { name: 'Jenny', age: 100 }, + { name: 'Kevin', age: 110 }, + { name: 'Larry', age: 120 }, + { name: 'Michelle', age: 130 }, + { name: 'Nancy', age: 140 }, + { name: 'Olivia', age: 150 }, + { name: 'Peter', age: 160 }, + { name: 'Quinn', age: 170 }, + { name: 'Ronda', age: 180 }, + { name: 'Shelley', age: 190 }, + { name: 'Tobias', age: 200 }, + { name: 'Uma', age: 210 }, + { name: 'Veena', age: 220 }, + { name: 'Wanda', age: 230 }, + { name: 'Xavier', age: 240 }, + { name: 'Yoyo', age: 250 }, + { name: 'Zanzabar', age: 260 }, ] var con = new pg.Client({ @@ -36,7 +36,7 @@ var con = new pg.Client({ port: args.port, user: args.user, password: args.password, - database: args.database + database: args.database, }) con.connect((err) => { @@ -45,8 +45,7 @@ con.connect((err) => { } con.query( - 'DROP TABLE IF EXISTS person;' - + ' CREATE TABLE person (id serial, name varchar(10), age integer)', + 'DROP TABLE IF EXISTS person;' + ' CREATE TABLE person (id serial, name varchar(10), age integer)', (err) => { if (err) { throw err @@ -56,10 +55,8 @@ con.connect((err) => { console.log('Filling it with people') con.query( - 'INSERT INTO person (name, age) VALUES' - + people - .map((person) => ` ('${person.name}', ${person.age})`) - .join(','), + 'INSERT INTO person (name, age) VALUES' + + people.map((person) => ` ('${person.name}', ${person.age})`).join(','), (err, result) => { if (err) { throw err @@ -67,6 +64,8 @@ con.connect((err) => { console.log(`Inserted ${result.rowCount} people`) con.end() - }) - }) + } + ) + } + ) }) diff --git a/packages/pg/script/dump-db-types.js b/packages/pg/script/dump-db-types.js index 2e55969d2..08fe4dc98 100644 --- a/packages/pg/script/dump-db-types.js +++ b/packages/pg/script/dump-db-types.js @@ -2,22 +2,17 @@ var pg = require(__dirname + '/../lib') var args = require(__dirname + '/../test/cli') -var queries = [ - 'select CURRENT_TIMESTAMP', - "select interval '1 day' + interval '1 hour'", - "select TIMESTAMP 'today'"] +var queries = ['select CURRENT_TIMESTAMP', "select interval '1 day' + interval '1 hour'", "select TIMESTAMP 'today'"] queries.forEach(function (query) { var client = new pg.Client({ user: args.user, database: args.database, - password: args.password + password: args.password, }) client.connect() - client - .query(query) - .on('row', function (row) { - console.log(row) - client.end() - }) + client.query(query).on('row', function (row) { + console.log(row) + client.end() + }) }) diff --git a/packages/pg/script/list-db-types.js b/packages/pg/script/list-db-types.js index d281bb90e..c3e75c1ae 100644 --- a/packages/pg/script/list-db-types.js +++ b/packages/pg/script/list-db-types.js @@ -1,7 +1,10 @@ 'use strict' var helper = require(__dirname + '/../test/integration/test-helper') var pg = helper.pg -pg.connect(helper.config, assert.success(function (client) { - var query = client.query('select oid, typname from pg_type where typtype = \'b\' order by oid') - query.on('row', console.log) -})) +pg.connect( + helper.config, + assert.success(function (client) { + var query = client.query("select oid, typname from pg_type where typtype = 'b' order by oid") + query.on('row', console.log) + }) +) diff --git a/packages/pg/test/buffer-list.js b/packages/pg/test/buffer-list.js index e0a9007bf..aea529c10 100644 --- a/packages/pg/test/buffer-list.js +++ b/packages/pg/test/buffer-list.js @@ -10,7 +10,7 @@ p.add = function (buffer, front) { } p.addInt16 = function (val, front) { - return this.add(Buffer.from([(val >>> 8), (val >>> 0)]), front) + return this.add(Buffer.from([val >>> 8, val >>> 0]), front) } p.getByteLength = function (initial) { @@ -20,12 +20,10 @@ p.getByteLength = function (initial) { } p.addInt32 = function (val, first) { - return this.add(Buffer.from([ - (val >>> 24 & 0xFF), - (val >>> 16 & 0xFF), - (val >>> 8 & 0xFF), - (val >>> 0 & 0xFF) - ]), first) + return this.add( + Buffer.from([(val >>> 24) & 0xff, (val >>> 16) & 0xff, (val >>> 8) & 0xff, (val >>> 0) & 0xff]), + first + ) } p.addCString = function (val, front) { diff --git a/packages/pg/test/integration/client/api-tests.js b/packages/pg/test/integration/client/api-tests.js index dab923505..a957c32ae 100644 --- a/packages/pg/test/integration/client/api-tests.js +++ b/packages/pg/test/integration/client/api-tests.js @@ -9,13 +9,15 @@ suite.test('null and undefined are both inserted as NULL', function (done) { pool.connect( assert.calls(function (err, client, release) { assert(!err) - client.query( - 'CREATE TEMP TABLE my_nulls(a varchar(1), b varchar(1), c integer, d integer, e date, f date)' - ) - client.query( - 'INSERT INTO my_nulls(a,b,c,d,e,f) VALUES ($1,$2,$3,$4,$5,$6)', - [null, undefined, null, undefined, null, undefined] - ) + client.query('CREATE TEMP TABLE my_nulls(a varchar(1), b varchar(1), c integer, d integer, e date, f date)') + client.query('INSERT INTO my_nulls(a,b,c,d,e,f) VALUES ($1,$2,$3,$4,$5,$6)', [ + null, + undefined, + null, + undefined, + null, + undefined, + ]) client.query( 'SELECT * FROM my_nulls', assert.calls(function (err, result) { @@ -36,7 +38,7 @@ suite.test('null and undefined are both inserted as NULL', function (done) { ) }) -suite.test('pool callback behavior', done => { +suite.test('pool callback behavior', (done) => { // test weird callback behavior with node-pool const pool = new pg.Pool() pool.connect(function (err) { @@ -50,51 +52,63 @@ suite.test('pool callback behavior', done => { suite.test('query timeout', (cb) => { const pool = new pg.Pool({ query_timeout: 1000 }) pool.connect().then((client) => { - client.query('SELECT pg_sleep(2)', assert.calls(function (err, result) { - assert(err) - assert(err.message === 'Query read timeout') - client.release() - pool.end(cb) - })) + client.query( + 'SELECT pg_sleep(2)', + assert.calls(function (err, result) { + assert(err) + assert(err.message === 'Query read timeout') + client.release() + pool.end(cb) + }) + ) }) }) suite.test('query recover from timeout', (cb) => { const pool = new pg.Pool({ query_timeout: 1000 }) pool.connect().then((client) => { - client.query('SELECT pg_sleep(20)', assert.calls(function (err, result) { - assert(err) - assert(err.message === 'Query read timeout') - client.release(err) - pool.connect().then((client) => { - client.query('SELECT 1', assert.calls(function (err, result) { - assert(!err) - client.release(err) - pool.end(cb) - })) + client.query( + 'SELECT pg_sleep(20)', + assert.calls(function (err, result) { + assert(err) + assert(err.message === 'Query read timeout') + client.release(err) + pool.connect().then((client) => { + client.query( + 'SELECT 1', + assert.calls(function (err, result) { + assert(!err) + client.release(err) + pool.end(cb) + }) + ) + }) }) - })) + ) }) }) suite.test('query no timeout', (cb) => { const pool = new pg.Pool({ query_timeout: 10000 }) pool.connect().then((client) => { - client.query('SELECT pg_sleep(1)', assert.calls(function (err, result) { - assert(!err) - client.release() - pool.end(cb) - })) + client.query( + 'SELECT pg_sleep(1)', + assert.calls(function (err, result) { + assert(!err) + client.release() + pool.end(cb) + }) + ) }) }) -suite.test('callback API', done => { +suite.test('callback API', (done) => { const client = new helper.Client() client.query('CREATE TEMP TABLE peep(name text)') client.query('INSERT INTO peep(name) VALUES ($1)', ['brianc']) const config = { text: 'INSERT INTO peep(name) VALUES ($1)', - values: ['brian'] + values: ['brian'], } client.query(config) client.query('INSERT INTO peep(name) VALUES ($1)', ['aaron']) @@ -104,18 +118,18 @@ suite.test('callback API', done => { assert.equal(res.rowCount, 3) assert.deepEqual(res.rows, [ { - name: 'aaron' + name: 'aaron', }, { - name: 'brian' + name: 'brian', }, { - name: 'brianc' - } + name: 'brianc', + }, ]) done() }) - client.connect(err => { + client.connect((err) => { assert(!err) client.once('drain', () => client.end()) }) @@ -175,8 +189,7 @@ suite.test('query errors are handled and do not bubble if callback is provided', ) }) ) -} -) +}) suite.test('callback is fired once and only once', function (done) { const pool = new pg.Pool() @@ -189,14 +202,10 @@ suite.test('callback is fired once and only once', function (done) { [ "INSERT INTO boom(name) VALUES('hai')", "INSERT INTO boom(name) VALUES('boom')", - "INSERT INTO boom(name) VALUES('zoom')" + "INSERT INTO boom(name) VALUES('zoom')", ].join(';'), function (err, callback) { - assert.equal( - callCount++, - 0, - 'Call count should be 0. More means this callback fired more than once.' - ) + assert.equal(callCount++, 0, 'Call count should be 0. More means this callback fired more than once.') release() pool.end(done) } @@ -213,7 +222,7 @@ suite.test('can provide callback and config object', function (done) { client.query( { name: 'boom', - text: 'select NOW()' + text: 'select NOW()', }, assert.calls(function (err, result) { assert(!err) @@ -232,7 +241,7 @@ suite.test('can provide callback and config and parameters', function (done) { assert.calls(function (err, client, release) { assert(!err) var config = { - text: 'select $1::text as val' + text: 'select $1::text as val', } client.query( config, diff --git a/packages/pg/test/integration/client/appname-tests.js b/packages/pg/test/integration/client/appname-tests.js index e5883908d..dd8de6b39 100644 --- a/packages/pg/test/integration/client/appname-tests.js +++ b/packages/pg/test/integration/client/appname-tests.js @@ -6,24 +6,29 @@ var suite = new helper.Suite() var conInfo = helper.config -function getConInfo (override) { - return Object.assign({}, conInfo, override ) +function getConInfo(override) { + return Object.assign({}, conInfo, override) } -function getAppName (conf, cb) { +function getAppName(conf, cb) { var client = new Client(conf) - client.connect(assert.success(function () { - client.query('SHOW application_name', assert.success(function (res) { - var appName = res.rows[0].application_name - cb(appName) - client.end() - })) - })) + client.connect( + assert.success(function () { + client.query( + 'SHOW application_name', + assert.success(function (res) { + var appName = res.rows[0].application_name + cb(appName) + client.end() + }) + ) + }) + ) } suite.test('No default appliation_name ', function (done) { var conf = getConInfo() - getAppName({ }, function (res) { + getAppName({}, function (res) { assert.strictEqual(res, '') done() }) @@ -32,7 +37,7 @@ suite.test('No default appliation_name ', function (done) { suite.test('fallback_application_name is used', function (done) { var fbAppName = 'this is my app' var conf = getConInfo({ - 'fallback_application_name': fbAppName + fallback_application_name: fbAppName, }) getAppName(conf, function (res) { assert.strictEqual(res, fbAppName) @@ -43,7 +48,7 @@ suite.test('fallback_application_name is used', function (done) { suite.test('application_name is used', function (done) { var appName = 'some wired !@#$% application_name' var conf = getConInfo({ - 'application_name': appName + application_name: appName, }) getAppName(conf, function (res) { assert.strictEqual(res, appName) @@ -55,8 +60,8 @@ suite.test('application_name has precedence over fallback_application_name', fun var appName = 'some wired !@#$% application_name' var fbAppName = 'some other strange $$test$$ appname' var conf = getConInfo({ - 'application_name': appName, - 'fallback_application_name': fbAppName + application_name: appName, + fallback_application_name: fbAppName, }) getAppName(conf, function (res) { assert.strictEqual(res, appName) @@ -82,8 +87,8 @@ suite.test('application_name from connection string', function (done) { // TODO: make the test work for native client too if (!helper.args.native) { suite.test('application_name is read from the env', function (done) { - var appName = process.env.PGAPPNAME = 'testest' - getAppName({ }, function (res) { + var appName = (process.env.PGAPPNAME = 'testest') + getAppName({}, function (res) { delete process.env.PGAPPNAME assert.strictEqual(res, appName) done() diff --git a/packages/pg/test/integration/client/array-tests.js b/packages/pg/test/integration/client/array-tests.js index 84e97f190..f5e62b032 100644 --- a/packages/pg/test/integration/client/array-tests.js +++ b/packages/pg/test/integration/client/array-tests.js @@ -6,172 +6,226 @@ var suite = new helper.Suite() const pool = new pg.Pool() -pool.connect(assert.calls(function (err, client, release) { - assert(!err) - - suite.test('nulls', function (done) { - client.query('SELECT $1::text[] as array', [[null]], assert.success(function (result) { - var array = result.rows[0].array - assert.lengthIs(array, 1) - assert.isNull(array[0]) - done() - })) - }) - - suite.test('elements containing JSON-escaped characters', function (done) { - var param = '\\"\\"' - - for (var i = 1; i <= 0x1f; i++) { - param += String.fromCharCode(i) - } - - client.query('SELECT $1::text[] as array', [[param]], assert.success(function (result) { - var array = result.rows[0].array - assert.lengthIs(array, 1) - assert.equal(array[0], param) - done() - })) - }) - - suite.test('cleanup', () => release()) - - pool.connect(assert.calls(function (err, client, release) { +pool.connect( + assert.calls(function (err, client, release) { assert(!err) - client.query('CREATE TEMP TABLE why(names text[], numbors integer[])') - client.query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')).on('error', console.log) - suite.test('numbers', function (done) { - // client.connection.on('message', console.log) - client.query('SELECT numbors FROM why', assert.success(function (result) { - assert.lengthIs(result.rows[0].numbors, 3) - assert.equal(result.rows[0].numbors[0], 1) - assert.equal(result.rows[0].numbors[1], 2) - assert.equal(result.rows[0].numbors[2], 3) - done() - })) - }) - suite.test('parses string arrays', function (done) { - client.query('SELECT names FROM why', assert.success(function (result) { - var names = result.rows[0].names - assert.lengthIs(names, 3) - assert.equal(names[0], 'aaron') - assert.equal(names[1], 'brian') - assert.equal(names[2], 'a b c') - done() - })) - }) - - suite.test('empty array', function (done) { - client.query("SELECT '{}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names - assert.lengthIs(names, 0) - done() - })) + suite.test('nulls', function (done) { + client.query( + 'SELECT $1::text[] as array', + [[null]], + assert.success(function (result) { + var array = result.rows[0].array + assert.lengthIs(array, 1) + assert.isNull(array[0]) + done() + }) + ) }) - suite.test('element containing comma', function (done) { - client.query("SELECT '{\"joe,bob\",jim}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names - assert.lengthIs(names, 2) - assert.equal(names[0], 'joe,bob') - assert.equal(names[1], 'jim') - done() - })) - }) + suite.test('elements containing JSON-escaped characters', function (done) { + var param = '\\"\\"' - suite.test('bracket in quotes', function (done) { - client.query("SELECT '{\"{\",\"}\"}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names - assert.lengthIs(names, 2) - assert.equal(names[0], '{') - assert.equal(names[1], '}') - done() - })) - }) + for (var i = 1; i <= 0x1f; i++) { + param += String.fromCharCode(i) + } - suite.test('null value', function (done) { - client.query("SELECT '{joe,null,bob,\"NULL\"}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names - assert.lengthIs(names, 4) - assert.equal(names[0], 'joe') - assert.equal(names[1], null) - assert.equal(names[2], 'bob') - assert.equal(names[3], 'NULL') - done() - })) + client.query( + 'SELECT $1::text[] as array', + [[param]], + assert.success(function (result) { + var array = result.rows[0].array + assert.lengthIs(array, 1) + assert.equal(array[0], param) + done() + }) + ) }) - suite.test('element containing quote char', function (done) { - client.query("SELECT ARRAY['joe''', 'jim', 'bob\"'] AS names", assert.success(function (result) { - var names = result.rows[0].names - assert.lengthIs(names, 3) - assert.equal(names[0], 'joe\'') - assert.equal(names[1], 'jim') - assert.equal(names[2], 'bob"') - done() - })) - }) + suite.test('cleanup', () => release()) + + pool.connect( + assert.calls(function (err, client, release) { + assert(!err) + client.query('CREATE TEMP TABLE why(names text[], numbors integer[])') + client + .query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')) + .on('error', console.log) + suite.test('numbers', function (done) { + // client.connection.on('message', console.log) + client.query( + 'SELECT numbors FROM why', + assert.success(function (result) { + assert.lengthIs(result.rows[0].numbors, 3) + assert.equal(result.rows[0].numbors[0], 1) + assert.equal(result.rows[0].numbors[1], 2) + assert.equal(result.rows[0].numbors[2], 3) + done() + }) + ) + }) - suite.test('nested array', function (done) { - client.query("SELECT '{{1,joe},{2,bob}}'::text[] as names", assert.success(function (result) { - var names = result.rows[0].names - assert.lengthIs(names, 2) + suite.test('parses string arrays', function (done) { + client.query( + 'SELECT names FROM why', + assert.success(function (result) { + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0], 'aaron') + assert.equal(names[1], 'brian') + assert.equal(names[2], 'a b c') + done() + }) + ) + }) - assert.lengthIs(names[0], 2) - assert.equal(names[0][0], '1') - assert.equal(names[0][1], 'joe') + suite.test('empty array', function (done) { + client.query( + "SELECT '{}'::text[] as names", + assert.success(function (result) { + var names = result.rows[0].names + assert.lengthIs(names, 0) + done() + }) + ) + }) - assert.lengthIs(names[1], 2) - assert.equal(names[1][0], '2') - assert.equal(names[1][1], 'bob') - done() - })) - }) + suite.test('element containing comma', function (done) { + client.query( + 'SELECT \'{"joe,bob",jim}\'::text[] as names', + assert.success(function (result) { + var names = result.rows[0].names + assert.lengthIs(names, 2) + assert.equal(names[0], 'joe,bob') + assert.equal(names[1], 'jim') + done() + }) + ) + }) - suite.test('integer array', function (done) { - client.query("SELECT '{1,2,3}'::integer[] as names", assert.success(function (result) { - var names = result.rows[0].names - assert.lengthIs(names, 3) - assert.equal(names[0], 1) - assert.equal(names[1], 2) - assert.equal(names[2], 3) - done() - })) - }) + suite.test('bracket in quotes', function (done) { + client.query( + 'SELECT \'{"{","}"}\'::text[] as names', + assert.success(function (result) { + var names = result.rows[0].names + assert.lengthIs(names, 2) + assert.equal(names[0], '{') + assert.equal(names[1], '}') + done() + }) + ) + }) - suite.test('integer nested array', function (done) { - client.query("SELECT '{{1,100},{2,100},{3,100}}'::integer[] as names", assert.success(function (result) { - var names = result.rows[0].names - assert.lengthIs(names, 3) - assert.equal(names[0][0], 1) - assert.equal(names[0][1], 100) + suite.test('null value', function (done) { + client.query( + 'SELECT \'{joe,null,bob,"NULL"}\'::text[] as names', + assert.success(function (result) { + var names = result.rows[0].names + assert.lengthIs(names, 4) + assert.equal(names[0], 'joe') + assert.equal(names[1], null) + assert.equal(names[2], 'bob') + assert.equal(names[3], 'NULL') + done() + }) + ) + }) - assert.equal(names[1][0], 2) - assert.equal(names[1][1], 100) + suite.test('element containing quote char', function (done) { + client.query( + "SELECT ARRAY['joe''', 'jim', 'bob\"'] AS names", + assert.success(function (result) { + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0], "joe'") + assert.equal(names[1], 'jim') + assert.equal(names[2], 'bob"') + done() + }) + ) + }) - assert.equal(names[2][0], 3) - assert.equal(names[2][1], 100) - done() - })) - }) + suite.test('nested array', function (done) { + client.query( + "SELECT '{{1,joe},{2,bob}}'::text[] as names", + assert.success(function (result) { + var names = result.rows[0].names + assert.lengthIs(names, 2) + + assert.lengthIs(names[0], 2) + assert.equal(names[0][0], '1') + assert.equal(names[0][1], 'joe') + + assert.lengthIs(names[1], 2) + assert.equal(names[1][0], '2') + assert.equal(names[1][1], 'bob') + done() + }) + ) + }) - suite.test('JS array parameter', function (done) { - client.query('SELECT $1::integer[] as names', [[[1, 100], [2, 100], [3, 100]]], assert.success(function (result) { - var names = result.rows[0].names - assert.lengthIs(names, 3) - assert.equal(names[0][0], 1) - assert.equal(names[0][1], 100) + suite.test('integer array', function (done) { + client.query( + "SELECT '{1,2,3}'::integer[] as names", + assert.success(function (result) { + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0], 1) + assert.equal(names[1], 2) + assert.equal(names[2], 3) + done() + }) + ) + }) - assert.equal(names[1][0], 2) - assert.equal(names[1][1], 100) + suite.test('integer nested array', function (done) { + client.query( + "SELECT '{{1,100},{2,100},{3,100}}'::integer[] as names", + assert.success(function (result) { + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0][0], 1) + assert.equal(names[0][1], 100) + + assert.equal(names[1][0], 2) + assert.equal(names[1][1], 100) + + assert.equal(names[2][0], 3) + assert.equal(names[2][1], 100) + done() + }) + ) + }) - assert.equal(names[2][0], 3) - assert.equal(names[2][1], 100) - release() - pool.end(() => { - done() + suite.test('JS array parameter', function (done) { + client.query( + 'SELECT $1::integer[] as names', + [ + [ + [1, 100], + [2, 100], + [3, 100], + ], + ], + assert.success(function (result) { + var names = result.rows[0].names + assert.lengthIs(names, 3) + assert.equal(names[0][0], 1) + assert.equal(names[0][1], 100) + + assert.equal(names[1][0], 2) + assert.equal(names[1][1], 100) + + assert.equal(names[2][0], 3) + assert.equal(names[2][1], 100) + release() + pool.end(() => { + done() + }) + }) + ) }) - })) - }) - })) -})) + }) + ) + }) +) diff --git a/packages/pg/test/integration/client/big-simple-query-tests.js b/packages/pg/test/integration/client/big-simple-query-tests.js index 5a15dca36..b0dc252f6 100644 --- a/packages/pg/test/integration/client/big-simple-query-tests.js +++ b/packages/pg/test/integration/client/big-simple-query-tests.js @@ -19,9 +19,19 @@ var big_query_rows_3 = [] // Works suite.test('big simple query 1', function (done) { var client = helper.client() - client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = '' or 1 = 1")) - .on('row', function (row) { big_query_rows_1.push(row) }) - .on('error', function (error) { console.log('big simple query 1 error'); console.log(error) }) + client + .query( + new Query( + "select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = '' or 1 = 1" + ) + ) + .on('row', function (row) { + big_query_rows_1.push(row) + }) + .on('error', function (error) { + console.log('big simple query 1 error') + console.log(error) + }) client.on('drain', () => { client.end() done() @@ -31,9 +41,20 @@ suite.test('big simple query 1', function (done) { // Works suite.test('big simple query 2', function (done) { var client = helper.client() - client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", [''])) - .on('row', function (row) { big_query_rows_2.push(row) }) - .on('error', function (error) { console.log('big simple query 2 error'); console.log(error) }) + client + .query( + new Query( + "select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", + [''] + ) + ) + .on('row', function (row) { + big_query_rows_2.push(row) + }) + .on('error', function (error) { + console.log('big simple query 2 error') + console.log(error) + }) client.on('drain', () => { client.end() done() @@ -44,9 +65,20 @@ suite.test('big simple query 2', function (done) { // If test 1 and 2 are commented out it works suite.test('big simple query 3', function (done) { var client = helper.client() - client.query(new Query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", [''])) - .on('row', function (row) { big_query_rows_3.push(row) }) - .on('error', function (error) { console.log('big simple query 3 error'); console.log(error) }) + client + .query( + new Query( + "select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", + [''] + ) + ) + .on('row', function (row) { + big_query_rows_3.push(row) + }) + .on('error', function (error) { + console.log('big simple query 3 error') + console.log(error) + }) client.on('drain', () => { client.end() done() @@ -61,13 +93,17 @@ process.on('exit', function () { var runBigQuery = function (client) { var rows = [] - var q = client.query("select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", [''], function (err, result) { - if (err != null) { - console.log(err) - throw Err + var q = client.query( + "select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", + [''], + function (err, result) { + if (err != null) { + console.log(err) + throw Err + } + assert.lengthIs(result.rows, 26) } - assert.lengthIs(result.rows, 26) - }) + ) } suite.test('many times', function (done) { diff --git a/packages/pg/test/integration/client/configuration-tests.js b/packages/pg/test/integration/client/configuration-tests.js index a6756ddee..0737a79c3 100644 --- a/packages/pg/test/integration/client/configuration-tests.js +++ b/packages/pg/test/integration/client/configuration-tests.js @@ -25,7 +25,7 @@ suite.test('default values are used in new clients', function () { ssl: false, application_name: undefined, fallback_application_name: undefined, - parseInputDatesAsUTC: false + parseInputDatesAsUTC: false, }) var client = new pg.Client() @@ -33,7 +33,7 @@ suite.test('default values are used in new clients', function () { user: process.env.USER, database: process.env.USER, password: null, - port: 5432 + port: 5432, }) }) @@ -50,7 +50,7 @@ suite.test('modified values are passed to created clients', function () { password: 'zap', database: 'pow', port: 1234, - host: 'blam' + host: 'blam', }) }) diff --git a/packages/pg/test/integration/client/connection-timeout-tests.js b/packages/pg/test/integration/client/connection-timeout-tests.js index 35e418858..843fa95bb 100644 --- a/packages/pg/test/integration/client/connection-timeout-tests.js +++ b/packages/pg/test/integration/client/connection-timeout-tests.js @@ -10,26 +10,26 @@ const options = { port: 54321, connectionTimeoutMillis: 2000, user: 'not', - database: 'existing' + database: 'existing', } const serverWithConnectionTimeout = (timeout, callback) => { const sockets = new Set() - const server = net.createServer(socket => { + const server = net.createServer((socket) => { sockets.add(socket) socket.once('end', () => sockets.delete(socket)) - socket.on('data', data => { + socket.on('data', (data) => { // deny request for SSL if (data.length === 8) { socket.write(Buffer.from('N', 'utf8')) - // consider all authentication requests as good + // consider all authentication requests as good } else if (!data[0]) { socket.write(buffers.authenticationOk()) // send ReadyForQuery `timeout` ms after authentication setTimeout(() => socket.write(buffers.readyForQuery()), timeout).unref() - // respond with our canned response + // respond with our canned response } else { socket.write(buffers.readyForQuery()) } @@ -37,7 +37,7 @@ const serverWithConnectionTimeout = (timeout, callback) => { }) let closing = false - const closeServer = done => { + const closeServer = (done) => { if (closing) return closing = true @@ -50,32 +50,34 @@ const serverWithConnectionTimeout = (timeout, callback) => { server.listen(options.port, options.host, () => callback(closeServer)) } -suite.test('successful connection', done => { - serverWithConnectionTimeout(0, closeServer => { +suite.test('successful connection', (done) => { + serverWithConnectionTimeout(0, (closeServer) => { const timeoutId = setTimeout(() => { throw new Error('Client should have connected successfully but it did not.') }, 3000) const client = new helper.Client(options) - client.connect() + client + .connect() .then(() => client.end()) .then(() => closeServer(done)) - .catch(err => closeServer(() => done(err))) + .catch((err) => closeServer(() => done(err))) .then(() => clearTimeout(timeoutId)) }) }) -suite.test('expired connection timeout', done => { - serverWithConnectionTimeout(options.connectionTimeoutMillis * 2, closeServer => { +suite.test('expired connection timeout', (done) => { + serverWithConnectionTimeout(options.connectionTimeoutMillis * 2, (closeServer) => { const timeoutId = setTimeout(() => { throw new Error('Client should have emitted an error but it did not.') }, 3000) const client = new helper.Client(options) - client.connect() + client + .connect() .then(() => client.end()) .then(() => closeServer(() => done(new Error('Connection timeout should have expired but it did not.')))) - .catch(err => { + .catch((err) => { assert(err instanceof Error) assert(/timeout expired\s*/.test(err.message)) closeServer(done) diff --git a/packages/pg/test/integration/client/custom-types-tests.js b/packages/pg/test/integration/client/custom-types-tests.js index 2b50fef08..d1dd2eec0 100644 --- a/packages/pg/test/integration/client/custom-types-tests.js +++ b/packages/pg/test/integration/client/custom-types-tests.js @@ -4,19 +4,21 @@ const Client = helper.pg.Client const suite = new helper.Suite() const customTypes = { - getTypeParser: () => () => 'okay!' + getTypeParser: () => () => 'okay!', } suite.test('custom type parser in client config', (done) => { const client = new Client({ types: customTypes }) - client.connect() - .then(() => { - client.query('SELECT NOW() as val', assert.success(function (res) { + client.connect().then(() => { + client.query( + 'SELECT NOW() as val', + assert.success(function (res) { assert.equal(res.rows[0].val, 'okay!') client.end().then(done) - })) - }) + }) + ) + }) }) // Custom type-parsers per query are not supported in native @@ -24,15 +26,17 @@ if (!helper.args.native) { suite.test('custom type parser in query', (done) => { const client = new Client() - client.connect() - .then(() => { - client.query({ + client.connect().then(() => { + client.query( + { text: 'SELECT NOW() as val', - types: customTypes - }, assert.success(function (res) { + types: customTypes, + }, + assert.success(function (res) { assert.equal(res.rows[0].val, 'okay!') client.end().then(done) - })) - }) + }) + ) + }) }) } diff --git a/packages/pg/test/integration/client/empty-query-tests.js b/packages/pg/test/integration/client/empty-query-tests.js index 975dc0f66..d887885c7 100644 --- a/packages/pg/test/integration/client/empty-query-tests.js +++ b/packages/pg/test/integration/client/empty-query-tests.js @@ -7,7 +7,7 @@ suite.test('empty query message handling', function (done) { assert.emits(client, 'drain', function () { client.end(done) }) - client.query({text: ''}) + client.query({ text: '' }) }) suite.test('callback supported', function (done) { diff --git a/packages/pg/test/integration/client/error-handling-tests.js b/packages/pg/test/integration/client/error-handling-tests.js index 97b0ce83f..93959e02b 100644 --- a/packages/pg/test/integration/client/error-handling-tests.js +++ b/packages/pg/test/integration/client/error-handling-tests.js @@ -33,7 +33,7 @@ suite.test('sending non-array argument as values causes an error callback', (don suite.test('re-using connections results in error callback', (done) => { const client = new Client() client.connect(() => { - client.connect(err => { + client.connect((err) => { assert(err instanceof Error) client.end(done) }) @@ -43,7 +43,7 @@ suite.test('re-using connections results in error callback', (done) => { suite.test('re-using connections results in promise rejection', (done) => { const client = new Client() client.connect().then(() => { - client.connect().catch(err => { + client.connect().catch((err) => { assert(err instanceof Error) client.end().then(done) }) @@ -53,33 +53,43 @@ suite.test('re-using connections results in promise rejection', (done) => { suite.test('using a client after closing it results in error', (done) => { const client = new Client() client.connect(() => { - client.end(assert.calls(() => { - client.query('SELECT 1', assert.calls((err) => { - assert.equal(err.message, 'Client was closed and is not queryable') - done() - })) - })) + client.end( + assert.calls(() => { + client.query( + 'SELECT 1', + assert.calls((err) => { + assert.equal(err.message, 'Client was closed and is not queryable') + done() + }) + ) + }) + ) }) }) suite.test('query receives error on client shutdown', function (done) { var client = new Client() - client.connect(assert.success(function () { - const config = { - text: 'select pg_sleep(5)', - name: 'foobar' - } - let queryError - client.query(new pg.Query(config), assert.calls(function (err, res) { - assert(err instanceof Error) - queryError = err - })) - setTimeout(() => client.end(), 50) - client.once('end', () => { - assert(queryError instanceof Error) - done() + client.connect( + assert.success(function () { + const config = { + text: 'select pg_sleep(5)', + name: 'foobar', + } + let queryError + client.query( + new pg.Query(config), + assert.calls(function (err, res) { + assert(err instanceof Error) + queryError = err + }) + ) + setTimeout(() => client.end(), 50) + client.once('end', () => { + assert(queryError instanceof Error) + done() + }) }) - })) + ) }) var ensureFuture = function (testClient, done) { @@ -95,11 +105,13 @@ suite.test('when query is parsing', (done) => { var q = client.query({ text: 'CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);' }) - // this query wont parse since there isn't a table named bang - var query = client.query(new pg.Query({ - text: 'select * from bang where name = $1', - values: ['0'] - })) + // this query wont parse since there isn't a table named bang + var query = client.query( + new pg.Query({ + text: 'select * from bang where name = $1', + values: ['0'], + }) + ) assert.emits(query, 'error', function (err) { ensureFuture(client, done) @@ -111,10 +123,12 @@ suite.test('when a query is binding', function (done) { var q = client.query({ text: 'CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);' }) - var query = client.query(new pg.Query({ - text: 'select * from boom where age = $1', - values: ['asldkfjasdf'] - })) + var query = client.query( + new pg.Query({ + text: 'select * from boom where age = $1', + values: ['asldkfjasdf'], + }) + ) assert.emits(query, 'error', function (err) { assert.equal(err.severity, 'ERROR') @@ -124,12 +138,14 @@ suite.test('when a query is binding', function (done) { suite.test('non-query error with callback', function (done) { var client = new Client({ - user: 'asldkfjsadlfkj' + user: 'asldkfjsadlfkj', }) - client.connect(assert.calls(function (error, client) { - assert(error instanceof Error) - done() - })) + client.connect( + assert.calls(function (error, client) { + assert(error instanceof Error) + done() + }) + ) }) suite.test('non-error calls supplied callback', function (done) { @@ -138,18 +154,20 @@ suite.test('non-error calls supplied callback', function (done) { password: helper.args.password, host: helper.args.host, port: helper.args.port, - database: helper.args.database + database: helper.args.database, }) - client.connect(assert.calls(function (err) { - assert.ifError(err) - client.end(done) - })) + client.connect( + assert.calls(function (err) { + assert.ifError(err) + client.end(done) + }) + ) }) suite.test('when connecting to an invalid host with callback', function (done) { var client = new Client({ - user: 'very invalid username' + user: 'very invalid username', }) client.on('error', () => { assert.fail('unexpected error event when connecting') @@ -162,7 +180,7 @@ suite.test('when connecting to an invalid host with callback', function (done) { suite.test('when connecting to invalid host with promise', function (done) { var client = new Client({ - user: 'very invalid username' + user: 'very invalid username', }) client.on('error', () => { assert.fail('unexpected error event when connecting') @@ -172,13 +190,12 @@ suite.test('when connecting to invalid host with promise', function (done) { suite.test('non-query error', function (done) { var client = new Client({ - user: 'asldkfjsadlfkj' + user: 'asldkfjsadlfkj', + }) + client.connect().catch((e) => { + assert(e instanceof Error) + done() }) - client.connect() - .catch(e => { - assert(e instanceof Error) - done() - }) }) suite.test('within a simple query', (done) => { @@ -199,7 +216,7 @@ suite.test('connected, idle client error', (done) => { throw new Error('Should not receive error callback after connection') } setImmediate(() => { - (client.connection || client.native).emit('error', new Error('expected')) + ;(client.connection || client.native).emit('error', new Error('expected')) }) }) client.on('error', (err) => { @@ -211,9 +228,9 @@ suite.test('connected, idle client error', (done) => { suite.test('cannot pass non-string values to query as text', (done) => { const client = new Client() client.connect() - client.query({ text: { } }, (err) => { + client.query({ text: {} }, (err) => { assert(err) - client.query({ }, (err) => { + client.query({}, (err) => { client.on('drain', () => { client.end(done) }) diff --git a/packages/pg/test/integration/client/huge-numeric-tests.js b/packages/pg/test/integration/client/huge-numeric-tests.js index 111adf200..bdbfac261 100644 --- a/packages/pg/test/integration/client/huge-numeric-tests.js +++ b/packages/pg/test/integration/client/huge-numeric-tests.js @@ -2,21 +2,26 @@ var helper = require('./test-helper') const pool = new helper.pg.Pool() -pool.connect(assert.success(function (client, done) { - var types = require('pg-types') - // 1231 = numericOID - types.setTypeParser(1700, function () { - return 'yes' +pool.connect( + assert.success(function (client, done) { + var types = require('pg-types') + // 1231 = numericOID + types.setTypeParser(1700, function () { + return 'yes' + }) + types.setTypeParser(1700, 'binary', function () { + return 'yes' + }) + var bignum = '294733346389144765940638005275322203805' + client.query('CREATE TEMP TABLE bignumz(id numeric)') + client.query('INSERT INTO bignumz(id) VALUES ($1)', [bignum]) + client.query( + 'SELECT * FROM bignumz', + assert.success(function (result) { + assert.equal(result.rows[0].id, 'yes') + done() + pool.end() + }) + ) }) - types.setTypeParser(1700, 'binary', function () { - return 'yes' - }) - var bignum = '294733346389144765940638005275322203805' - client.query('CREATE TEMP TABLE bignumz(id numeric)') - client.query('INSERT INTO bignumz(id) VALUES ($1)', [bignum]) - client.query('SELECT * FROM bignumz', assert.success(function (result) { - assert.equal(result.rows[0].id, 'yes') - done() - pool.end() - })) -})) +) diff --git a/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js b/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js index 18162f545..f970faaf2 100644 --- a/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js +++ b/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js @@ -6,38 +6,54 @@ var suite = new helper.Suite() var conInfo = helper.config -function getConInfo (override) { - return Object.assign({}, conInfo, override ) +function getConInfo(override) { + return Object.assign({}, conInfo, override) } function testClientVersion(cb) { var client = new Client({}) - client.connect(assert.success(function () { - helper.versionGTE(client, 100000, assert.success(function(isGreater) { - return client.end(assert.success(function () { - if (!isGreater) { - console.log('skip idle_in_transaction_session_timeout at client-level is only available in v10 and above'); - return; - } - cb(); - })) - })) - })) + client.connect( + assert.success(function () { + helper.versionGTE( + client, + 100000, + assert.success(function (isGreater) { + return client.end( + assert.success(function () { + if (!isGreater) { + console.log( + 'skip idle_in_transaction_session_timeout at client-level is only available in v10 and above' + ) + return + } + cb() + }) + ) + }) + ) + }) + ) } -function getIdleTransactionSessionTimeout (conf, cb) { +function getIdleTransactionSessionTimeout(conf, cb) { var client = new Client(conf) - client.connect(assert.success(function () { - client.query('SHOW idle_in_transaction_session_timeout', assert.success(function (res) { - var timeout = res.rows[0].idle_in_transaction_session_timeout - cb(timeout) - client.end() - })) - })) + client.connect( + assert.success(function () { + client.query( + 'SHOW idle_in_transaction_session_timeout', + assert.success(function (res) { + var timeout = res.rows[0].idle_in_transaction_session_timeout + cb(timeout) + client.end() + }) + ) + }) + ) } -if (!helper.args.native) { // idle_in_transaction_session_timeout is not supported with the native client - testClientVersion(function(){ +if (!helper.args.native) { + // idle_in_transaction_session_timeout is not supported with the native client + testClientVersion(function () { suite.test('No default idle_in_transaction_session_timeout ', function (done) { getConInfo() getIdleTransactionSessionTimeout({}, function (res) { @@ -48,7 +64,7 @@ if (!helper.args.native) { // idle_in_transaction_session_timeout is not support suite.test('idle_in_transaction_session_timeout integer is used', function (done) { var conf = getConInfo({ - 'idle_in_transaction_session_timeout': 3000 + idle_in_transaction_session_timeout: 3000, }) getIdleTransactionSessionTimeout(conf, function (res) { assert.strictEqual(res, '3s') @@ -58,7 +74,7 @@ if (!helper.args.native) { // idle_in_transaction_session_timeout is not support suite.test('idle_in_transaction_session_timeout float is used', function (done) { var conf = getConInfo({ - 'idle_in_transaction_session_timeout': 3000.7 + idle_in_transaction_session_timeout: 3000.7, }) getIdleTransactionSessionTimeout(conf, function (res) { assert.strictEqual(res, '3s') @@ -68,7 +84,7 @@ if (!helper.args.native) { // idle_in_transaction_session_timeout is not support suite.test('idle_in_transaction_session_timeout string is used', function (done) { var conf = getConInfo({ - 'idle_in_transaction_session_timeout': '3000' + idle_in_transaction_session_timeout: '3000', }) getIdleTransactionSessionTimeout(conf, function (res) { assert.strictEqual(res, '3s') diff --git a/packages/pg/test/integration/client/json-type-parsing-tests.js b/packages/pg/test/integration/client/json-type-parsing-tests.js index 58cbc3f31..ba7696020 100644 --- a/packages/pg/test/integration/client/json-type-parsing-tests.js +++ b/packages/pg/test/integration/client/json-type-parsing-tests.js @@ -3,26 +3,35 @@ var helper = require('./test-helper') var assert = require('assert') const pool = new helper.pg.Pool() -pool.connect(assert.success(function (client, done) { - helper.versionGTE(client, 90200, assert.success(function (jsonSupported) { - if (!jsonSupported) { - console.log('skip json test on older versions of postgres') - done() - return pool.end() - } - client.query('CREATE TEMP TABLE stuff(id SERIAL PRIMARY KEY, data JSON)') - var value = { name: 'Brian', age: 250, alive: true, now: new Date() } - client.query('INSERT INTO stuff (data) VALUES ($1)', [value]) - client.query('SELECT * FROM stuff', assert.success(function (result) { - assert.equal(result.rows.length, 1) - assert.equal(typeof result.rows[0].data, 'object') - var row = result.rows[0].data - assert.strictEqual(row.name, value.name) - assert.strictEqual(row.age, value.age) - assert.strictEqual(row.alive, value.alive) - assert.equal(JSON.stringify(row.now), JSON.stringify(value.now)) - done() - pool.end() - })) - })) -})) +pool.connect( + assert.success(function (client, done) { + helper.versionGTE( + client, + 90200, + assert.success(function (jsonSupported) { + if (!jsonSupported) { + console.log('skip json test on older versions of postgres') + done() + return pool.end() + } + client.query('CREATE TEMP TABLE stuff(id SERIAL PRIMARY KEY, data JSON)') + var value = { name: 'Brian', age: 250, alive: true, now: new Date() } + client.query('INSERT INTO stuff (data) VALUES ($1)', [value]) + client.query( + 'SELECT * FROM stuff', + assert.success(function (result) { + assert.equal(result.rows.length, 1) + assert.equal(typeof result.rows[0].data, 'object') + var row = result.rows[0].data + assert.strictEqual(row.name, value.name) + assert.strictEqual(row.age, value.age) + assert.strictEqual(row.alive, value.alive) + assert.equal(JSON.stringify(row.now), JSON.stringify(value.now)) + done() + pool.end() + }) + ) + }) + ) + }) +) diff --git a/packages/pg/test/integration/client/multiple-results-tests.js b/packages/pg/test/integration/client/multiple-results-tests.js index 01dd9eaed..addca9b68 100644 --- a/packages/pg/test/integration/client/multiple-results-tests.js +++ b/packages/pg/test/integration/client/multiple-results-tests.js @@ -6,64 +6,73 @@ const helper = require('./test-helper') const suite = new helper.Suite('multiple result sets') -suite.test('two select results work', co.wrap(function * () { - const client = new helper.Client() - yield client.connect() +suite.test( + 'two select results work', + co.wrap(function* () { + const client = new helper.Client() + yield client.connect() - const results = yield client.query(`SELECT 'foo'::text as name; SELECT 'bar'::text as baz`) - assert(Array.isArray(results)) + const results = yield client.query(`SELECT 'foo'::text as name; SELECT 'bar'::text as baz`) + assert(Array.isArray(results)) - assert.equal(results[0].fields[0].name, 'name') - assert.deepEqual(results[0].rows, [{ name: 'foo' }]) + assert.equal(results[0].fields[0].name, 'name') + assert.deepEqual(results[0].rows, [{ name: 'foo' }]) - assert.equal(results[1].fields[0].name, 'baz') - assert.deepEqual(results[1].rows, [{ baz: 'bar' }]) + assert.equal(results[1].fields[0].name, 'baz') + assert.deepEqual(results[1].rows, [{ baz: 'bar' }]) - return client.end() -})) + return client.end() + }) +) -suite.test('multiple selects work', co.wrap(function * () { - const client = new helper.Client() - yield client.connect() +suite.test( + 'multiple selects work', + co.wrap(function* () { + const client = new helper.Client() + yield client.connect() - const text = ` + const text = ` SELECT * FROM generate_series(2, 4) as foo; SELECT * FROM generate_series(8, 10) as bar; SELECT * FROM generate_series(20, 22) as baz; ` - const results = yield client.query(text) - assert(Array.isArray(results)) + const results = yield client.query(text) + assert(Array.isArray(results)) - assert.equal(results[0].fields[0].name, 'foo') - assert.deepEqual(results[0].rows, [{ foo: 2 }, { foo: 3 }, { foo: 4 }]) + assert.equal(results[0].fields[0].name, 'foo') + assert.deepEqual(results[0].rows, [{ foo: 2 }, { foo: 3 }, { foo: 4 }]) - assert.equal(results[1].fields[0].name, 'bar') - assert.deepEqual(results[1].rows, [{ bar: 8 }, { bar: 9 }, { bar: 10 }]) + assert.equal(results[1].fields[0].name, 'bar') + assert.deepEqual(results[1].rows, [{ bar: 8 }, { bar: 9 }, { bar: 10 }]) - assert.equal(results[2].fields[0].name, 'baz') - assert.deepEqual(results[2].rows, [{ baz: 20 }, { baz: 21 }, { baz: 22 }]) + assert.equal(results[2].fields[0].name, 'baz') + assert.deepEqual(results[2].rows, [{ baz: 20 }, { baz: 21 }, { baz: 22 }]) - assert.equal(results.length, 3) + assert.equal(results.length, 3) - return client.end() -})) + return client.end() + }) +) -suite.test('mixed queries and statements', co.wrap(function * () { - const client = new helper.Client() - yield client.connect() +suite.test( + 'mixed queries and statements', + co.wrap(function* () { + const client = new helper.Client() + yield client.connect() - const text = ` + const text = ` CREATE TEMP TABLE weather(type text); INSERT INTO weather(type) VALUES ('rain'); SELECT * FROM weather; ` - const results = yield client.query(text) - assert(Array.isArray(results)) - assert.equal(results[0].command, 'CREATE') - assert.equal(results[1].command, 'INSERT') - assert.equal(results[2].command, 'SELECT') + const results = yield client.query(text) + assert(Array.isArray(results)) + assert.equal(results[0].command, 'CREATE') + assert.equal(results[1].command, 'INSERT') + assert.equal(results[2].command, 'SELECT') - return client.end() -})) + return client.end() + }) +) diff --git a/packages/pg/test/integration/client/network-partition-tests.js b/packages/pg/test/integration/client/network-partition-tests.js index 8eaf5d0d7..993396401 100644 --- a/packages/pg/test/integration/client/network-partition-tests.js +++ b/packages/pg/test/integration/client/network-partition-tests.js @@ -16,29 +16,34 @@ Server.prototype.start = function (cb) { // it responds with our specified response immediatley after receiving every buffer // this is sufficient into convincing the client its connectet to a valid backend // if we respond with a readyForQuery message - this.server = net.createServer(function (socket) { - this.socket = socket - if (this.response) { - this.socket.on('data', function (data) { - // deny request for SSL - if (data.length == 8) { - this.socket.write(Buffer.from('N', 'utf8')) - // consider all authentication requests as good - } else if (!data[0]) { - this.socket.write(buffers.authenticationOk()) - // respond with our canned response - } else { - this.socket.write(this.response) - } - }.bind(this)) - } - }.bind(this)) + this.server = net.createServer( + function (socket) { + this.socket = socket + if (this.response) { + this.socket.on( + 'data', + function (data) { + // deny request for SSL + if (data.length == 8) { + this.socket.write(Buffer.from('N', 'utf8')) + // consider all authentication requests as good + } else if (!data[0]) { + this.socket.write(buffers.authenticationOk()) + // respond with our canned response + } else { + this.socket.write(this.response) + } + }.bind(this) + ) + } + }.bind(this) + ) var port = 54321 var options = { host: 'localhost', - port: port + port: port, } this.server.listen(options.port, options.host, function () { cb(options) @@ -58,12 +63,11 @@ var testServer = function (server, cb) { server.start(function (options) { // connect a client to it var client = new helper.Client(options) - client.connect() - .catch((err) => { - assert(err instanceof Error) - clearTimeout(timeoutId) - server.close(cb) - }) + client.connect().catch((err) => { + assert(err instanceof Error) + clearTimeout(timeoutId) + server.close(cb) + }) server.server.on('connection', () => { // after 50 milliseconds, drop the client diff --git a/packages/pg/test/integration/client/no-data-tests.js b/packages/pg/test/integration/client/no-data-tests.js index 46ea45662..ad0f22be3 100644 --- a/packages/pg/test/integration/client/no-data-tests.js +++ b/packages/pg/test/integration/client/no-data-tests.js @@ -7,33 +7,39 @@ suite.test('noData message handling', function () { var q = client.query({ name: 'boom', - text: 'create temp table boom(id serial, size integer)' + text: 'create temp table boom(id serial, size integer)', }) - client.query({ - name: 'insert', - text: 'insert into boom(size) values($1)', - values: [100] - }, function (err, result) { - if (err) { - console.log(err) - throw err + client.query( + { + name: 'insert', + text: 'insert into boom(size) values($1)', + values: [100], + }, + function (err, result) { + if (err) { + console.log(err) + throw err + } } - }) + ) client.query({ name: 'insert', - values: [101] + values: [101], }) - var query = client.query({ - name: 'fetch', - text: 'select size from boom where size < $1', - values: [101] - }, (err, res) => { - var row = res.rows[0] - assert.strictEqual(row.size, 100) - }) + var query = client.query( + { + name: 'fetch', + text: 'select size from boom where size < $1', + values: [101], + }, + (err, res) => { + var row = res.rows[0] + assert.strictEqual(row.size, 100) + } + ) client.on('drain', client.end.bind(client)) }) diff --git a/packages/pg/test/integration/client/no-row-result-tests.js b/packages/pg/test/integration/client/no-row-result-tests.js index e52d113d8..6e8f52cf0 100644 --- a/packages/pg/test/integration/client/no-row-result-tests.js +++ b/packages/pg/test/integration/client/no-row-result-tests.js @@ -15,11 +15,13 @@ suite.test('can access results when no rows are returned', function (done) { pool.connect( assert.success(function (client, release) { const q = new pg.Query('select $1::text as val limit 0', ['hi']) - var query = client.query(q, assert.success(function (result) { - checkResult(result) - release() - pool.end(done) - }) + var query = client.query( + q, + assert.success(function (result) { + checkResult(result) + release() + pool.end(done) + }) ) assert.emits(query, 'end', checkResult) diff --git a/packages/pg/test/integration/client/notice-tests.js b/packages/pg/test/integration/client/notice-tests.js index a6fc8a56f..b5d4f3d5e 100644 --- a/packages/pg/test/integration/client/notice-tests.js +++ b/packages/pg/test/integration/client/notice-tests.js @@ -5,31 +5,40 @@ const suite = new helper.Suite() suite.test('emits notify message', function (done) { const client = helper.client() - client.query('LISTEN boom', assert.calls(function () { - const otherClient = helper.client() - let bothEmitted = -1 - otherClient.query('LISTEN boom', assert.calls(function () { - assert.emits(client, 'notification', function (msg) { - // make sure PQfreemem doesn't invalidate string pointers - setTimeout(function () { - assert.equal(msg.channel, 'boom') - assert.ok(msg.payload == 'omg!' /* 9.x */ || msg.payload == '' /* 8.x */, 'expected blank payload or correct payload but got ' + msg.message) - client.end(++bothEmitted ? done : undefined) - }, 100) - }) - assert.emits(otherClient, 'notification', function (msg) { - assert.equal(msg.channel, 'boom') - otherClient.end(++bothEmitted ? done : undefined) - }) + client.query( + 'LISTEN boom', + assert.calls(function () { + const otherClient = helper.client() + let bothEmitted = -1 + otherClient.query( + 'LISTEN boom', + assert.calls(function () { + assert.emits(client, 'notification', function (msg) { + // make sure PQfreemem doesn't invalidate string pointers + setTimeout(function () { + assert.equal(msg.channel, 'boom') + assert.ok( + msg.payload == 'omg!' /* 9.x */ || msg.payload == '' /* 8.x */, + 'expected blank payload or correct payload but got ' + msg.message + ) + client.end(++bothEmitted ? done : undefined) + }, 100) + }) + assert.emits(otherClient, 'notification', function (msg) { + assert.equal(msg.channel, 'boom') + otherClient.end(++bothEmitted ? done : undefined) + }) - client.query("NOTIFY boom, 'omg!'", function (err, q) { - if (err) { - // notify not supported with payload on 8.x - client.query('NOTIFY boom') - } - }) - })) - })) + client.query("NOTIFY boom, 'omg!'", function (err, q) { + if (err) { + // notify not supported with payload on 8.x + client.query('NOTIFY boom') + } + }) + }) + ) + }) + ) }) // this test fails on travis due to their config diff --git a/packages/pg/test/integration/client/parse-int-8-tests.js b/packages/pg/test/integration/client/parse-int-8-tests.js index 193689045..9f251de69 100644 --- a/packages/pg/test/integration/client/parse-int-8-tests.js +++ b/packages/pg/test/integration/client/parse-int-8-tests.js @@ -7,23 +7,31 @@ const suite = new helper.Suite() const pool = new pg.Pool(helper.config) suite.test('ability to turn on and off parser', function () { if (helper.args.binary) return false - pool.connect(assert.success(function (client, done) { - pg.defaults.parseInt8 = true - client.query('CREATE TEMP TABLE asdf(id SERIAL PRIMARY KEY)') - client.query('SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', assert.success(function (res) { - assert.strictEqual(0, res.rows[0].count) - assert.strictEqual(1, res.rows[0].array[0]) - assert.strictEqual(2, res.rows[0].array[1]) - assert.strictEqual(3, res.rows[0].array[2]) - pg.defaults.parseInt8 = false - client.query('SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', assert.success(function (res) { - done() - assert.strictEqual('0', res.rows[0].count) - assert.strictEqual('1', res.rows[0].array[0]) - assert.strictEqual('2', res.rows[0].array[1]) - assert.strictEqual('3', res.rows[0].array[2]) - pool.end() - })) - })) - })) + pool.connect( + assert.success(function (client, done) { + pg.defaults.parseInt8 = true + client.query('CREATE TEMP TABLE asdf(id SERIAL PRIMARY KEY)') + client.query( + 'SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', + assert.success(function (res) { + assert.strictEqual(0, res.rows[0].count) + assert.strictEqual(1, res.rows[0].array[0]) + assert.strictEqual(2, res.rows[0].array[1]) + assert.strictEqual(3, res.rows[0].array[2]) + pg.defaults.parseInt8 = false + client.query( + 'SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', + assert.success(function (res) { + done() + assert.strictEqual('0', res.rows[0].count) + assert.strictEqual('1', res.rows[0].array[0]) + assert.strictEqual('2', res.rows[0].array[1]) + assert.strictEqual('3', res.rows[0].array[2]) + pool.end() + }) + ) + }) + ) + }) + ) }) diff --git a/packages/pg/test/integration/client/prepared-statement-tests.js b/packages/pg/test/integration/client/prepared-statement-tests.js index 76654eaa3..48d12f899 100644 --- a/packages/pg/test/integration/client/prepared-statement-tests.js +++ b/packages/pg/test/integration/client/prepared-statement-tests.js @@ -12,11 +12,13 @@ var suite = new helper.Suite() var parseCount = 0 suite.test('first named prepared statement', function (done) { - var query = client.query(new Query({ - text: 'select name from person where age <= $1 and name LIKE $2', - values: [20, 'Bri%'], - name: queryName - })) + var query = client.query( + new Query({ + text: 'select name from person where age <= $1 and name LIKE $2', + values: [20, 'Bri%'], + name: queryName, + }) + ) assert.emits(query, 'row', function (row) { assert.equal(row.name, 'Brian') @@ -26,11 +28,13 @@ var suite = new helper.Suite() }) suite.test('second named prepared statement with same name & text', function (done) { - var cachedQuery = client.query(new Query({ - text: 'select name from person where age <= $1 and name LIKE $2', - name: queryName, - values: [10, 'A%'] - })) + var cachedQuery = client.query( + new Query({ + text: 'select name from person where age <= $1 and name LIKE $2', + name: queryName, + values: [10, 'A%'], + }) + ) assert.emits(cachedQuery, 'row', function (row) { assert.equal(row.name, 'Aaron') @@ -40,10 +44,12 @@ var suite = new helper.Suite() }) suite.test('with same name, but without query text', function (done) { - var q = client.query(new Query({ - name: queryName, - values: [30, '%n%'] - })) + var q = client.query( + new Query({ + name: queryName, + values: [30, '%n%'], + }) + ) assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Aaron') @@ -58,17 +64,22 @@ var suite = new helper.Suite() }) suite.test('with same name, but with different text', function (done) { - client.query(new Query({ - text: 'select name from person where age >= $1 and name LIKE $2', - name: queryName, - values: [30, '%n%'] - }), assert.calls(err => { - assert.equal(err.message, `Prepared statements must be unique - '${queryName}' was used for a different statement`) - done() - })) + client.query( + new Query({ + text: 'select name from person where age >= $1 and name LIKE $2', + name: queryName, + values: [30, '%n%'], + }), + assert.calls((err) => { + assert.equal( + err.message, + `Prepared statements must be unique - '${queryName}' was used for a different statement` + ) + done() + }) + ) }) })() - ;(function () { var statementName = 'differ' var statement1 = 'select count(*)::int4 as count from person' @@ -78,22 +89,27 @@ var suite = new helper.Suite() var client2 = helper.client() suite.test('client 1 execution', function (done) { - var query = client1.query({ - name: statementName, - text: statement1 - }, (err, res) => { - assert(!err) - assert.equal(res.rows[0].count, 26) - done() - }) + var query = client1.query( + { + name: statementName, + text: statement1, + }, + (err, res) => { + assert(!err) + assert.equal(res.rows[0].count, 26) + done() + } + ) }) suite.test('client 2 execution', function (done) { - var query = client2.query(new Query({ - name: statementName, - text: statement2, - values: [11] - })) + var query = client2.query( + new Query({ + name: statementName, + text: statement2, + values: [11], + }) + ) assert.emits(query, 'row', function (row) { assert.equal(row.count, 1) @@ -108,7 +124,6 @@ var suite = new helper.Suite() return client1.end().then(() => client2.end()) }) })() - ;(function () { var client = helper.client() client.query('CREATE TEMP TABLE zoom(name varchar(100));') @@ -131,21 +146,31 @@ var suite = new helper.Suite() } suite.test('with small row count', function (done) { - var query = client.query(new Query({ - name: 'get names', - text: 'SELECT name FROM zoom ORDER BY name COLLATE "C"', - rows: 1 - }, done)) + var query = client.query( + new Query( + { + name: 'get names', + text: 'SELECT name FROM zoom ORDER BY name COLLATE "C"', + rows: 1, + }, + done + ) + ) checkForResults(query) }) suite.test('with large row count', function (done) { - var query = client.query(new Query({ - name: 'get names', - text: 'SELECT name FROM zoom ORDER BY name COLLATE "C"', - rows: 1000 - }, done)) + var query = client.query( + new Query( + { + name: 'get names', + text: 'SELECT name FROM zoom ORDER BY name COLLATE "C"', + rows: 1000, + }, + done + ) + ) checkForResults(query) }) diff --git a/packages/pg/test/integration/client/promise-api-tests.js b/packages/pg/test/integration/client/promise-api-tests.js index 80337c4ae..1d6e504f2 100644 --- a/packages/pg/test/integration/client/promise-api-tests.js +++ b/packages/pg/test/integration/client/promise-api-tests.js @@ -7,43 +7,37 @@ const suite = new helper.Suite() suite.test('valid connection completes promise', () => { const client = new pg.Client() - return client.connect() - .then(() => { - return client.end() - .then(() => { }) - }) + return client.connect().then(() => { + return client.end().then(() => {}) + }) }) suite.test('valid connection completes promise', () => { const client = new pg.Client() - return client.connect() - .then(() => { - return client.end() - .then(() => { }) - }) + return client.connect().then(() => { + return client.end().then(() => {}) + }) }) suite.test('invalid connection rejects promise', (done) => { const client = new pg.Client({ host: 'alksdjflaskdfj' }) - return client.connect() - .catch(e => { - assert(e instanceof Error) - done() - }) + return client.connect().catch((e) => { + assert(e instanceof Error) + done() + }) }) suite.test('connected client does not reject promise after connection', (done) => { const client = new pg.Client() - return client.connect() - .then(() => { - setTimeout(() => { - client.on('error', (e) => { - assert(e instanceof Error) - client.end() - done() - }) - // manually kill the connection - client.emit('error', new Error('something bad happened...but not really')) - }, 50) - }) + return client.connect().then(() => { + setTimeout(() => { + client.on('error', (e) => { + assert(e instanceof Error) + client.end() + done() + }) + // manually kill the connection + client.emit('error', new Error('something bad happened...but not really')) + }, 50) + }) }) diff --git a/packages/pg/test/integration/client/query-as-promise-tests.js b/packages/pg/test/integration/client/query-as-promise-tests.js index 803b89099..46365c6c0 100644 --- a/packages/pg/test/integration/client/query-as-promise-tests.js +++ b/packages/pg/test/integration/client/query-as-promise-tests.js @@ -13,22 +13,21 @@ const suite = new helper.Suite() suite.test('promise API', (cb) => { const pool = new pg.Pool() pool.connect().then((client) => { - client.query('SELECT $1::text as name', ['foo']) + client + .query('SELECT $1::text as name', ['foo']) .then(function (result) { assert.equal(result.rows[0].name, 'foo') return client }) .then(function (client) { - client.query('ALKJSDF') - .catch(function (e) { - assert(e instanceof Error) - client.query('SELECT 1 as num') - .then(function (result) { - assert.equal(result.rows[0].num, 1) - client.release() - pool.end(cb) - }) + client.query('ALKJSDF').catch(function (e) { + assert(e instanceof Error) + client.query('SELECT 1 as num').then(function (result) { + assert.equal(result.rows[0].num, 1) + client.release() + pool.end(cb) }) + }) }) }) }) @@ -52,4 +51,4 @@ suite.test('promise API with configurable promise type', (cb) => { throw error }) }) -}); +}) diff --git a/packages/pg/test/integration/client/query-column-names-tests.js b/packages/pg/test/integration/client/query-column-names-tests.js index cc5a42b56..6b32881e5 100644 --- a/packages/pg/test/integration/client/query-column-names-tests.js +++ b/packages/pg/test/integration/client/query-column-names-tests.js @@ -4,12 +4,17 @@ var pg = helper.pg new helper.Suite().test('support for complex column names', function () { const pool = new pg.Pool() - pool.connect(assert.success(function (client, done) { - client.query("CREATE TEMP TABLE t ( \"complex''column\" TEXT )") - client.query('SELECT * FROM t', assert.success(function (res) { - done() - assert.strictEqual(res.fields[0].name, "complex''column") - pool.end() - })) - })) + pool.connect( + assert.success(function (client, done) { + client.query('CREATE TEMP TABLE t ( "complex\'\'column" TEXT )') + client.query( + 'SELECT * FROM t', + assert.success(function (res) { + done() + assert.strictEqual(res.fields[0].name, "complex''column") + pool.end() + }) + ) + }) + ) }) diff --git a/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js b/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js index 9ba7567e2..adef58d16 100644 --- a/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -7,57 +7,79 @@ var suite = new helper.Suite() suite.test('client end during query execution of prepared statement', function (done) { var client = new Client() - client.connect(assert.success(function () { - var sleepQuery = 'select pg_sleep($1)' + client.connect( + assert.success(function () { + var sleepQuery = 'select pg_sleep($1)' + + var queryConfig = { + name: 'sleep query', + text: sleepQuery, + values: [5], + } - var queryConfig = { - name: 'sleep query', - text: sleepQuery, - values: [5] - } + var queryInstance = new Query( + queryConfig, + assert.calls(function (err, result) { + assert.equal(err.message, 'Connection terminated') + done() + }) + ) - var queryInstance = new Query(queryConfig, assert.calls(function (err, result) { - assert.equal(err.message, 'Connection terminated') - done() - })) + var query1 = client.query(queryInstance) - var query1 = client.query(queryInstance) + query1.on('error', function (err) { + assert.fail('Prepared statement should not emit error') + }) - query1.on('error', function (err) { - assert.fail('Prepared statement should not emit error') - }) + query1.on('row', function (row) { + assert.fail('Prepared statement should not emit row') + }) - query1.on('row', function (row) { - assert.fail('Prepared statement should not emit row') - }) + query1.on('end', function (err) { + assert.fail('Prepared statement when executed should not return before being killed') + }) - query1.on('end', function (err) { - assert.fail('Prepared statement when executed should not return before being killed') + client.end() }) - - client.end() - })) + ) }) -function killIdleQuery (targetQuery, cb) { +function killIdleQuery(targetQuery, cb) { var client2 = new Client(helper.args) var pidColName = 'procpid' var queryColName = 'current_query' - client2.connect(assert.success(function () { - helper.versionGTE(client2, 90200, assert.success(function (isGreater) { - if (isGreater) { - pidColName = 'pid' - queryColName = 'query' - } - var killIdleQuery = 'SELECT ' + pidColName + ', (SELECT pg_terminate_backend(' + pidColName + ')) AS killed FROM pg_stat_activity WHERE ' + queryColName + ' = $1' - client2.query(killIdleQuery, [targetQuery], assert.calls(function (err, res) { - assert.ifError(err) - assert.equal(res.rows.length, 1) - client2.end(cb) - assert.emits(client2, 'end') - })) - })) - })) + client2.connect( + assert.success(function () { + helper.versionGTE( + client2, + 90200, + assert.success(function (isGreater) { + if (isGreater) { + pidColName = 'pid' + queryColName = 'query' + } + var killIdleQuery = + 'SELECT ' + + pidColName + + ', (SELECT pg_terminate_backend(' + + pidColName + + ')) AS killed FROM pg_stat_activity WHERE ' + + queryColName + + ' = $1' + client2.query( + killIdleQuery, + [targetQuery], + assert.calls(function (err, res) { + assert.ifError(err) + assert.equal(res.rows.length, 1) + client2.end(cb) + assert.emits(client2, 'end') + }) + ) + }) + ) + }) + ) } suite.test('query killed during query execution of prepared statement', function (done) { @@ -65,34 +87,39 @@ suite.test('query killed during query execution of prepared statement', function return done() } var client = new Client(helper.args) - client.connect(assert.success(function () { - var sleepQuery = 'select pg_sleep($1)' + client.connect( + assert.success(function () { + var sleepQuery = 'select pg_sleep($1)' + + const queryConfig = { + name: 'sleep query', + text: sleepQuery, + values: [5], + } - const queryConfig = { - name: 'sleep query', - text: sleepQuery, - values: [5] - } + // client should emit an error because it is unexpectedly disconnected + assert.emits(client, 'error') - // client should emit an error because it is unexpectedly disconnected - assert.emits(client, 'error') + var query1 = client.query( + new Query(queryConfig), + assert.calls(function (err, result) { + assert.equal(err.message, 'terminating connection due to administrator command') + }) + ) - var query1 = client.query(new Query(queryConfig), assert.calls(function (err, result) { - assert.equal(err.message, 'terminating connection due to administrator command') - })) + query1.on('error', function (err) { + assert.fail('Prepared statement should not emit error') + }) - query1.on('error', function (err) { - assert.fail('Prepared statement should not emit error') - }) + query1.on('row', function (row) { + assert.fail('Prepared statement should not emit row') + }) - query1.on('row', function (row) { - assert.fail('Prepared statement should not emit row') - }) + query1.on('end', function (err) { + assert.fail('Prepared statement when executed should not return before being killed') + }) - query1.on('end', function (err) { - assert.fail('Prepared statement when executed should not return before being killed') + killIdleQuery(sleepQuery, done) }) - - killIdleQuery(sleepQuery, done) - })) + ) }) diff --git a/packages/pg/test/integration/client/query-error-handling-tests.js b/packages/pg/test/integration/client/query-error-handling-tests.js index 67ac5d699..34eab8f65 100644 --- a/packages/pg/test/integration/client/query-error-handling-tests.js +++ b/packages/pg/test/integration/client/query-error-handling-tests.js @@ -1,88 +1,115 @@ -"use strict"; -var helper = require('./test-helper'); -var util = require('util'); -var Query = helper.pg.Query; +'use strict' +var helper = require('./test-helper') +var util = require('util') +var Query = helper.pg.Query -test('error during query execution', function() { - var client = new Client(helper.args); - client.connect(assert.success(function() { - var queryText = 'select pg_sleep(10)' - var sleepQuery = new Query(queryText); - var pidColName = 'procpid' - var queryColName = 'current_query'; - helper.versionGTE(client, 90200, assert.success(function(isGreater) { - if(isGreater) { - pidColName = 'pid'; - queryColName = 'query'; - } - var query1 = client.query(sleepQuery, assert.calls(function(err, result) { - assert(err); - client.end(); - })); - //ensure query1 does not emit an 'end' event - //because it was killed and received an error - //https://github.com/brianc/node-postgres/issues/547 - query1.on('end', function() { - assert.fail('Query with an error should not emit "end" event') - }) - setTimeout(function() { - var client2 = new Client(helper.args); - client2.connect(assert.success(function() { - var killIdleQuery = `SELECT ${pidColName}, (SELECT pg_cancel_backend(${pidColName})) AS killed FROM pg_stat_activity WHERE ${queryColName} LIKE $1`; - client2.query(killIdleQuery, [queryText], assert.calls(function(err, res) { - assert.ifError(err); - assert(res.rows.length > 0); - client2.end(); - assert.emits(client2, 'end'); - })); - })); - }, 300) - })); - })); -}); +test('error during query execution', function () { + var client = new Client(helper.args) + client.connect( + assert.success(function () { + var queryText = 'select pg_sleep(10)' + var sleepQuery = new Query(queryText) + var pidColName = 'procpid' + var queryColName = 'current_query' + helper.versionGTE( + client, + 90200, + assert.success(function (isGreater) { + if (isGreater) { + pidColName = 'pid' + queryColName = 'query' + } + var query1 = client.query( + sleepQuery, + assert.calls(function (err, result) { + assert(err) + client.end() + }) + ) + //ensure query1 does not emit an 'end' event + //because it was killed and received an error + //https://github.com/brianc/node-postgres/issues/547 + query1.on('end', function () { + assert.fail('Query with an error should not emit "end" event') + }) + setTimeout(function () { + var client2 = new Client(helper.args) + client2.connect( + assert.success(function () { + var killIdleQuery = `SELECT ${pidColName}, (SELECT pg_cancel_backend(${pidColName})) AS killed FROM pg_stat_activity WHERE ${queryColName} LIKE $1` + client2.query( + killIdleQuery, + [queryText], + assert.calls(function (err, res) { + assert.ifError(err) + assert(res.rows.length > 0) + client2.end() + assert.emits(client2, 'end') + }) + ) + }) + ) + }, 300) + }) + ) + }) + ) +}) if (helper.config.native) { return } -test('9.3 column error fields', function() { - var client = new Client(helper.args); - client.connect(assert.success(function() { - helper.versionGTE(client, 90300, assert.success(function(isGreater) { - if(!isGreater) { - return client.end(); - } +test('9.3 column error fields', function () { + var client = new Client(helper.args) + client.connect( + assert.success(function () { + helper.versionGTE( + client, + 90300, + assert.success(function (isGreater) { + if (!isGreater) { + return client.end() + } - client.query('CREATE TEMP TABLE column_err_test(a int NOT NULL)'); - client.query('INSERT INTO column_err_test(a) VALUES (NULL)', function (err) { - assert.equal(err.severity, 'ERROR'); - assert.equal(err.code, '23502'); - assert.equal(err.table, 'column_err_test'); - assert.equal(err.column, 'a'); - return client.end(); - }); - })); - })); -}); + client.query('CREATE TEMP TABLE column_err_test(a int NOT NULL)') + client.query('INSERT INTO column_err_test(a) VALUES (NULL)', function (err) { + assert.equal(err.severity, 'ERROR') + assert.equal(err.code, '23502') + assert.equal(err.table, 'column_err_test') + assert.equal(err.column, 'a') + return client.end() + }) + }) + ) + }) + ) +}) -test('9.3 constraint error fields', function() { - var client = new Client(helper.args); - client.connect(assert.success(function() { - helper.versionGTE(client, 90300, assert.success(function(isGreater) { - if(!isGreater) { - console.log('skip 9.3 error field on older versions of postgres'); - return client.end(); - } +test('9.3 constraint error fields', function () { + var client = new Client(helper.args) + client.connect( + assert.success(function () { + helper.versionGTE( + client, + 90300, + assert.success(function (isGreater) { + if (!isGreater) { + console.log('skip 9.3 error field on older versions of postgres') + return client.end() + } - client.query('CREATE TEMP TABLE constraint_err_test(a int PRIMARY KEY)'); - client.query('INSERT INTO constraint_err_test(a) VALUES (1)'); - client.query('INSERT INTO constraint_err_test(a) VALUES (1)', function (err) { - assert.equal(err.severity, 'ERROR'); - assert.equal(err.code, '23505'); - assert.equal(err.table, 'constraint_err_test'); - assert.equal(err.constraint, 'constraint_err_test_pkey'); - return client.end(); - }); - })); - })); -}); + client.query('CREATE TEMP TABLE constraint_err_test(a int PRIMARY KEY)') + client.query('INSERT INTO constraint_err_test(a) VALUES (1)') + client.query('INSERT INTO constraint_err_test(a) VALUES (1)', function (err) { + assert.equal(err.severity, 'ERROR') + assert.equal(err.code, '23505') + assert.equal(err.table, 'constraint_err_test') + assert.equal(err.constraint, 'constraint_err_test_pkey') + return client.end() + }) + }) + ) + }) + ) +}) diff --git a/packages/pg/test/integration/client/result-metadata-tests.js b/packages/pg/test/integration/client/result-metadata-tests.js index 074a1598d..66d9ac4ae 100644 --- a/packages/pg/test/integration/client/result-metadata-tests.js +++ b/packages/pg/test/integration/client/result-metadata-tests.js @@ -4,29 +4,44 @@ var pg = helper.pg const pool = new pg.Pool() new helper.Suite().test('should return insert metadata', function () { - pool.connect(assert.calls(function (err, client, done) { - assert(!err) + pool.connect( + assert.calls(function (err, client, done) { + assert(!err) - helper.versionGTE(client, 90000, assert.success(function (hasRowCount) { - client.query('CREATE TEMP TABLE zugzug(name varchar(10))', assert.calls(function (err, result) { - assert(!err) - assert.equal(result.oid, null) - assert.equal(result.command, 'CREATE') + helper.versionGTE( + client, + 90000, + assert.success(function (hasRowCount) { + client.query( + 'CREATE TEMP TABLE zugzug(name varchar(10))', + assert.calls(function (err, result) { + assert(!err) + assert.equal(result.oid, null) + assert.equal(result.command, 'CREATE') - var q = client.query("INSERT INTO zugzug(name) VALUES('more work?')", assert.calls(function (err, result) { - assert(!err) - assert.equal(result.command, 'INSERT') - assert.equal(result.rowCount, 1) + var q = client.query( + "INSERT INTO zugzug(name) VALUES('more work?')", + assert.calls(function (err, result) { + assert(!err) + assert.equal(result.command, 'INSERT') + assert.equal(result.rowCount, 1) - client.query('SELECT * FROM zugzug', assert.calls(function (err, result) { - assert(!err) - if (hasRowCount) assert.equal(result.rowCount, 1) - assert.equal(result.command, 'SELECT') - done() - process.nextTick(pool.end.bind(pool)) - })) - })) - })) - })) - })) + client.query( + 'SELECT * FROM zugzug', + assert.calls(function (err, result) { + assert(!err) + if (hasRowCount) assert.equal(result.rowCount, 1) + assert.equal(result.command, 'SELECT') + done() + process.nextTick(pool.end.bind(pool)) + }) + ) + }) + ) + }) + ) + }) + ) + }) + ) }) diff --git a/packages/pg/test/integration/client/results-as-array-tests.js b/packages/pg/test/integration/client/results-as-array-tests.js index b6b00ef71..5ebb2a9d5 100644 --- a/packages/pg/test/integration/client/results-as-array-tests.js +++ b/packages/pg/test/integration/client/results-as-array-tests.js @@ -16,16 +16,21 @@ test('returns results as array', function () { assert.strictEqual(row[2], 'hai') assert.strictEqual(row[3], null) } - client.connect(assert.success(function () { - var config = { - text: 'SELECT NOW(), 1::int, $1::text, null', - values: ['hai'], - rowMode: 'array' - } - var query = client.query(config, assert.success(function (result) { - assert.equal(result.rows.length, 1) - checkRow(result.rows[0]) - client.end() - })) - })) + client.connect( + assert.success(function () { + var config = { + text: 'SELECT NOW(), 1::int, $1::text, null', + values: ['hai'], + rowMode: 'array', + } + var query = client.query( + config, + assert.success(function (result) { + assert.equal(result.rows.length, 1) + checkRow(result.rows[0]) + client.end() + }) + ) + }) + ) }) diff --git a/packages/pg/test/integration/client/row-description-on-results-tests.js b/packages/pg/test/integration/client/row-description-on-results-tests.js index 108e51977..688b96e6c 100644 --- a/packages/pg/test/integration/client/row-description-on-results-tests.js +++ b/packages/pg/test/integration/client/row-description-on-results-tests.js @@ -19,20 +19,32 @@ var checkResult = function (result) { test('row descriptions on result object', function () { var client = new Client(conInfo) - client.connect(assert.success(function () { - client.query('SELECT NOW() as now, 1::int as num, $1::text as texty', ['hello'], assert.success(function (result) { - checkResult(result) - client.end() - })) - })) + client.connect( + assert.success(function () { + client.query( + 'SELECT NOW() as now, 1::int as num, $1::text as texty', + ['hello'], + assert.success(function (result) { + checkResult(result) + client.end() + }) + ) + }) + ) }) test('row description on no rows', function () { var client = new Client(conInfo) - client.connect(assert.success(function () { - client.query('SELECT NOW() as now, 1::int as num, $1::text as texty LIMIT 0', ['hello'], assert.success(function (result) { - checkResult(result) - client.end() - })) - })) + client.connect( + assert.success(function () { + client.query( + 'SELECT NOW() as now, 1::int as num, $1::text as texty LIMIT 0', + ['hello'], + assert.success(function (result) { + checkResult(result) + client.end() + }) + ) + }) + ) }) diff --git a/packages/pg/test/integration/client/simple-query-tests.js b/packages/pg/test/integration/client/simple-query-tests.js index 0c4575c5b..d22d74742 100644 --- a/packages/pg/test/integration/client/simple-query-tests.js +++ b/packages/pg/test/integration/client/simple-query-tests.js @@ -22,7 +22,11 @@ test('simple query interface', function () { columnCount++ } if ('length' in row) { - assert.lengthIs(row, columnCount, 'Iterating through the columns gives a different length from calling .length.') + assert.lengthIs( + row, + columnCount, + 'Iterating through the columns gives a different length from calling .length.' + ) } }) }) @@ -65,7 +69,7 @@ test('prepared statements do not mutate params', function () { test('multiple simple queries', function () { var client = helper.client() - client.query({ text: "create temp table bang(id serial, name varchar(5));insert into bang(name) VALUES('boom');"}) + client.query({ text: "create temp table bang(id serial, name varchar(5));insert into bang(name) VALUES('boom');" }) client.query("insert into bang(name) VALUES ('yes');") var query = client.query(new Query('select name from bang')) assert.emits(query, 'row', function (row) { @@ -79,9 +83,11 @@ test('multiple simple queries', function () { test('multiple select statements', function () { var client = helper.client() - client.query('create temp table boom(age integer); insert into boom(age) values(1); insert into boom(age) values(2); insert into boom(age) values(3)') - client.query({text: "create temp table bang(name varchar(5)); insert into bang(name) values('zoom');"}) - var result = client.query(new Query({text: 'select age from boom where age < 2; select name from bang'})) + client.query( + 'create temp table boom(age integer); insert into boom(age) values(1); insert into boom(age) values(2); insert into boom(age) values(3)' + ) + client.query({ text: "create temp table bang(name varchar(5)); insert into bang(name) values('zoom');" }) + var result = client.query(new Query({ text: 'select age from boom where age < 2; select name from bang' })) assert.emits(result, 'row', function (row) { assert.strictEqual(row['age'], 1) assert.emits(result, 'row', function (row) { diff --git a/packages/pg/test/integration/client/ssl-tests.js b/packages/pg/test/integration/client/ssl-tests.js index bd864d1e1..1d3c5015b 100644 --- a/packages/pg/test/integration/client/ssl-tests.js +++ b/packages/pg/test/integration/client/ssl-tests.js @@ -4,12 +4,18 @@ var config = require(__dirname + '/test-helper').config test('can connect with ssl', function () { return false config.ssl = { - rejectUnauthorized: false + rejectUnauthorized: false, } - pg.connect(config, assert.success(function (client) { - return false - client.query('SELECT NOW()', assert.success(function () { - pg.end() - })) - })) + pg.connect( + config, + assert.success(function (client) { + return false + client.query( + 'SELECT NOW()', + assert.success(function () { + pg.end() + }) + ) + }) + ) }) diff --git a/packages/pg/test/integration/client/statement_timeout-tests.js b/packages/pg/test/integration/client/statement_timeout-tests.js index 393e82a19..e0898ccee 100644 --- a/packages/pg/test/integration/client/statement_timeout-tests.js +++ b/packages/pg/test/integration/client/statement_timeout-tests.js @@ -6,22 +6,28 @@ var suite = new helper.Suite() var conInfo = helper.config -function getConInfo (override) { - return Object.assign({}, conInfo, override ) +function getConInfo(override) { + return Object.assign({}, conInfo, override) } -function getStatementTimeout (conf, cb) { +function getStatementTimeout(conf, cb) { var client = new Client(conf) - client.connect(assert.success(function () { - client.query('SHOW statement_timeout', assert.success(function (res) { - var statementTimeout = res.rows[0].statement_timeout - cb(statementTimeout) - client.end() - })) - })) + client.connect( + assert.success(function () { + client.query( + 'SHOW statement_timeout', + assert.success(function (res) { + var statementTimeout = res.rows[0].statement_timeout + cb(statementTimeout) + client.end() + }) + ) + }) + ) } -if (!helper.args.native) { // statement_timeout is not supported with the native client +if (!helper.args.native) { + // statement_timeout is not supported with the native client suite.test('No default statement_timeout ', function (done) { getConInfo() getStatementTimeout({}, function (res) { @@ -32,7 +38,7 @@ if (!helper.args.native) { // statement_timeout is not supported with the native suite.test('statement_timeout integer is used', function (done) { var conf = getConInfo({ - 'statement_timeout': 3000 + statement_timeout: 3000, }) getStatementTimeout(conf, function (res) { assert.strictEqual(res, '3s') @@ -42,7 +48,7 @@ if (!helper.args.native) { // statement_timeout is not supported with the native suite.test('statement_timeout float is used', function (done) { var conf = getConInfo({ - 'statement_timeout': 3000.7 + statement_timeout: 3000.7, }) getStatementTimeout(conf, function (res) { assert.strictEqual(res, '3s') @@ -52,7 +58,7 @@ if (!helper.args.native) { // statement_timeout is not supported with the native suite.test('statement_timeout string is used', function (done) { var conf = getConInfo({ - 'statement_timeout': '3000' + statement_timeout: '3000', }) getStatementTimeout(conf, function (res) { assert.strictEqual(res, '3s') @@ -62,16 +68,17 @@ if (!helper.args.native) { // statement_timeout is not supported with the native suite.test('statement_timeout actually cancels long running queries', function (done) { var conf = getConInfo({ - 'statement_timeout': '10' // 10ms to keep tests running fast + statement_timeout: '10', // 10ms to keep tests running fast }) var client = new Client(conf) - client.connect(assert.success(function () { - client.query('SELECT pg_sleep( 1 )', function ( error ) { - client.end() - assert.strictEqual( error.code, '57014' ) // query_cancelled - done() + client.connect( + assert.success(function () { + client.query('SELECT pg_sleep( 1 )', function (error) { + client.end() + assert.strictEqual(error.code, '57014') // query_cancelled + done() + }) }) - })) + ) }) - } diff --git a/packages/pg/test/integration/client/transaction-tests.js b/packages/pg/test/integration/client/transaction-tests.js index 560067ba4..18f8ff095 100644 --- a/packages/pg/test/integration/client/transaction-tests.js +++ b/packages/pg/test/integration/client/transaction-tests.js @@ -4,73 +4,96 @@ const suite = new helper.Suite() const pg = helper.pg const client = new pg.Client() -client.connect(assert.success(function () { - client.query('begin') +client.connect( + assert.success(function () { + client.query('begin') - var getZed = { - text: 'SELECT * FROM person WHERE name = $1', - values: ['Zed'] - } + var getZed = { + text: 'SELECT * FROM person WHERE name = $1', + values: ['Zed'], + } - suite.test('name should not exist in the database', function (done) { - client.query(getZed, assert.calls(function (err, result) { - assert(!err) - assert.empty(result.rows) - done() - })) - }) + suite.test('name should not exist in the database', function (done) { + client.query( + getZed, + assert.calls(function (err, result) { + assert(!err) + assert.empty(result.rows) + done() + }) + ) + }) - suite.test('can insert name', (done) => { - client.query('INSERT INTO person(name, age) VALUES($1, $2)', ['Zed', 270], assert.calls(function (err, result) { - assert(!err) - done() - })) - }) + suite.test('can insert name', (done) => { + client.query( + 'INSERT INTO person(name, age) VALUES($1, $2)', + ['Zed', 270], + assert.calls(function (err, result) { + assert(!err) + done() + }) + ) + }) - suite.test('name should exist in the database', function (done) { - client.query(getZed, assert.calls(function (err, result) { - assert(!err) - assert.equal(result.rows[0].name, 'Zed') - done() - })) - }) + suite.test('name should exist in the database', function (done) { + client.query( + getZed, + assert.calls(function (err, result) { + assert(!err) + assert.equal(result.rows[0].name, 'Zed') + done() + }) + ) + }) - suite.test('rollback', (done) => { - client.query('rollback', done) - }) + suite.test('rollback', (done) => { + client.query('rollback', done) + }) - suite.test('name should not exist in the database', function (done) { - client.query(getZed, assert.calls(function (err, result) { - assert(!err) - assert.empty(result.rows) - client.end(done) - })) + suite.test('name should not exist in the database', function (done) { + client.query( + getZed, + assert.calls(function (err, result) { + assert(!err) + assert.empty(result.rows) + client.end(done) + }) + ) + }) }) -})) +) suite.test('gh#36', function (cb) { const pool = new pg.Pool() - pool.connect(assert.success(function (client, done) { - client.query('BEGIN') - client.query({ - name: 'X', - text: 'SELECT $1::INTEGER', - values: [0] - }, assert.calls(function (err, result) { - if (err) throw err - assert.equal(result.rows.length, 1) - })) - client.query({ - name: 'X', - text: 'SELECT $1::INTEGER', - values: [0] - }, assert.calls(function (err, result) { - if (err) throw err - assert.equal(result.rows.length, 1) - })) - client.query('COMMIT', function () { - done() - pool.end(cb) + pool.connect( + assert.success(function (client, done) { + client.query('BEGIN') + client.query( + { + name: 'X', + text: 'SELECT $1::INTEGER', + values: [0], + }, + assert.calls(function (err, result) { + if (err) throw err + assert.equal(result.rows.length, 1) + }) + ) + client.query( + { + name: 'X', + text: 'SELECT $1::INTEGER', + values: [0], + }, + assert.calls(function (err, result) { + if (err) throw err + assert.equal(result.rows.length, 1) + }) + ) + client.query('COMMIT', function () { + done() + pool.end(cb) + }) }) - })) + ) }) diff --git a/packages/pg/test/integration/client/type-coercion-tests.js b/packages/pg/test/integration/client/type-coercion-tests.js index d0d740e45..96f57b08c 100644 --- a/packages/pg/test/integration/client/type-coercion-tests.js +++ b/packages/pg/test/integration/client/type-coercion-tests.js @@ -9,102 +9,130 @@ var testForTypeCoercion = function (type) { suite.test(`test type coercion ${type.name}`, (cb) => { pool.connect(function (err, client, done) { assert(!err) - client.query('create temp table test_type(col ' + type.name + ')', assert.calls(function (err, result) { - assert(!err) - - type.values.forEach(function (val) { - var insertQuery = client.query('insert into test_type(col) VALUES($1)', [val], assert.calls(function (err, result) { - assert(!err) - })) - - var query = client.query(new pg.Query({ - name: 'get type ' + type.name, - text: 'select col from test_type' - })) - - query.on('error', function (err) { - console.log(err) - throw err + client.query( + 'create temp table test_type(col ' + type.name + ')', + assert.calls(function (err, result) { + assert(!err) + + type.values.forEach(function (val) { + var insertQuery = client.query( + 'insert into test_type(col) VALUES($1)', + [val], + assert.calls(function (err, result) { + assert(!err) + }) + ) + + var query = client.query( + new pg.Query({ + name: 'get type ' + type.name, + text: 'select col from test_type', + }) + ) + + query.on('error', function (err) { + console.log(err) + throw err + }) + + assert.emits( + query, + 'row', + function (row) { + var expected = val + ' (' + typeof val + ')' + var returned = row.col + ' (' + typeof row.col + ')' + assert.strictEqual(row.col, val, 'expected ' + type.name + ' of ' + expected + ' but got ' + returned) + }, + 'row should have been called for ' + type.name + ' of ' + val + ) + + client.query('delete from test_type') }) - assert.emits(query, 'row', function (row) { - var expected = val + ' (' + typeof val + ')' - var returned = row.col + ' (' + typeof row.col + ')' - assert.strictEqual(row.col, val, 'expected ' + type.name + ' of ' + expected + ' but got ' + returned) - }, 'row should have been called for ' + type.name + ' of ' + val) - - client.query('delete from test_type') - }) - - client.query('drop table test_type', function () { - done() - pool.end(cb) + client.query('drop table test_type', function () { + done() + pool.end(cb) + }) }) - })) + ) }) }) } -var types = [{ - name: 'integer', - values: [-2147483648, -1, 0, 1, 2147483647, null] -}, { - name: 'smallint', - values: [-32768, -1, 0, 1, 32767, null] -}, { - name: 'bigint', - values: [ - '-9223372036854775808', - '-9007199254740992', - '0', - '9007199254740992', - '72057594037928030', - '9223372036854775807', - null - ] -}, { - name: 'varchar(5)', - values: ['yo', '', 'zomg!', null] -}, { - name: 'oid', - values: [0, 204410, null] -}, { - name: 'bool', - values: [true, false, null] -}, { - name: 'numeric', - values: [ - '-12.34', - '0', - '12.34', - '-3141592653589793238462643383279502.1618033988749894848204586834365638', - '3141592653589793238462643383279502.1618033988749894848204586834365638', - null - ] -}, { - name: 'real', - values: [-101.3, -1.2, 0, 1.2, 101.1, null] -}, { - name: 'double precision', - values: [-101.3, -1.2, 0, 1.2, 101.1, null] -}, { - name: 'timestamptz', - values: [null] -}, { - name: 'timestamp', - values: [null] -}, { - name: 'timetz', - values: ['13:11:12.1234-05:30', null] -}, { - name: 'time', - values: ['13:12:12.321', null] -}] +var types = [ + { + name: 'integer', + values: [-2147483648, -1, 0, 1, 2147483647, null], + }, + { + name: 'smallint', + values: [-32768, -1, 0, 1, 32767, null], + }, + { + name: 'bigint', + values: [ + '-9223372036854775808', + '-9007199254740992', + '0', + '9007199254740992', + '72057594037928030', + '9223372036854775807', + null, + ], + }, + { + name: 'varchar(5)', + values: ['yo', '', 'zomg!', null], + }, + { + name: 'oid', + values: [0, 204410, null], + }, + { + name: 'bool', + values: [true, false, null], + }, + { + name: 'numeric', + values: [ + '-12.34', + '0', + '12.34', + '-3141592653589793238462643383279502.1618033988749894848204586834365638', + '3141592653589793238462643383279502.1618033988749894848204586834365638', + null, + ], + }, + { + name: 'real', + values: [-101.3, -1.2, 0, 1.2, 101.1, null], + }, + { + name: 'double precision', + values: [-101.3, -1.2, 0, 1.2, 101.1, null], + }, + { + name: 'timestamptz', + values: [null], + }, + { + name: 'timestamp', + values: [null], + }, + { + name: 'timetz', + values: ['13:11:12.1234-05:30', null], + }, + { + name: 'time', + values: ['13:12:12.321', null], + }, +] // ignore some tests in binary mode if (helper.config.binary) { types = types.filter(function (type) { - return !(type.name in { 'real': 1, 'timetz': 1, 'time': 1, 'numeric': 1, 'bigint': 1 }) + return !(type.name in { real: 1, timetz: 1, time: 1, numeric: 1, bigint: 1 }) }) } @@ -121,13 +149,15 @@ suite.test('timestampz round trip', function (cb) { client.query({ text: 'insert into date_tests(name, tstz)VALUES($1, $2)', name: 'add date', - values: ['now', now] + values: ['now', now], }) - var result = client.query(new pg.Query({ - name: 'get date', - text: 'select * from date_tests where name = $1', - values: ['now'] - })) + var result = client.query( + new pg.Query({ + name: 'get date', + text: 'select * from date_tests where name = $1', + values: ['now'], + }) + ) assert.emits(result, 'row', function (row) { var date = row.tstz @@ -145,21 +175,26 @@ suite.test('timestampz round trip', function (cb) { }) }) -suite.test('selecting nulls', cb => { +suite.test('selecting nulls', (cb) => { const pool = new pg.Pool() - pool.connect(assert.calls(function (err, client, done) { - assert.ifError(err) - client.query('select null as res;', assert.calls(function (err, res) { - assert(!err) - assert.strictEqual(res.rows[0].res, null) - })) - client.query('select 7 <> $1 as res;', [null], function (err, res) { - assert(!err) - assert.strictEqual(res.rows[0].res, null) - done() - pool.end(cb) + pool.connect( + assert.calls(function (err, client, done) { + assert.ifError(err) + client.query( + 'select null as res;', + assert.calls(function (err, res) { + assert(!err) + assert.strictEqual(res.rows[0].res, null) + }) + ) + client.query('select 7 <> $1 as res;', [null], function (err, res) { + assert(!err) + assert.strictEqual(res.rows[0].res, null) + done() + pool.end(cb) + }) }) - })) + ) }) suite.test('date range extremes', function (done) { @@ -169,25 +204,40 @@ suite.test('date range extremes', function (done) { // otherwise (if server's timezone is ahead of GMT) in // textParsers.js::parseDate() the timezone offest is added to the date; // in the case of "275760-09-13 00:00:00 GMT" the timevalue overflows. - client.query('SET TIMEZONE TO GMT', assert.success(function (res) { - // PostgreSQL supports date range of 4713 BCE to 294276 CE - // http://www.postgresql.org/docs/9.2/static/datatype-datetime.html - // ECMAScript supports date range of Apr 20 271821 BCE to Sep 13 275760 CE - // http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1 - client.query('SELECT $1::TIMESTAMPTZ as when', ['275760-09-13 00:00:00 GMT'], assert.success(function (res) { - assert.equal(res.rows[0].when.getFullYear(), 275760) - })) - - client.query('SELECT $1::TIMESTAMPTZ as when', ['4713-12-31 12:31:59 BC GMT'], assert.success(function (res) { - assert.equal(res.rows[0].when.getFullYear(), -4712) - })) - - client.query('SELECT $1::TIMESTAMPTZ as when', ['275760-09-13 00:00:00 -15:00'], assert.success(function (res) { - assert(isNaN(res.rows[0].when.getTime())) - })) - - client.on('drain', () => { - client.end(done) + client.query( + 'SET TIMEZONE TO GMT', + assert.success(function (res) { + // PostgreSQL supports date range of 4713 BCE to 294276 CE + // http://www.postgresql.org/docs/9.2/static/datatype-datetime.html + // ECMAScript supports date range of Apr 20 271821 BCE to Sep 13 275760 CE + // http://ecma-international.org/ecma-262/5.1/#sec-15.9.1.1 + client.query( + 'SELECT $1::TIMESTAMPTZ as when', + ['275760-09-13 00:00:00 GMT'], + assert.success(function (res) { + assert.equal(res.rows[0].when.getFullYear(), 275760) + }) + ) + + client.query( + 'SELECT $1::TIMESTAMPTZ as when', + ['4713-12-31 12:31:59 BC GMT'], + assert.success(function (res) { + assert.equal(res.rows[0].when.getFullYear(), -4712) + }) + ) + + client.query( + 'SELECT $1::TIMESTAMPTZ as when', + ['275760-09-13 00:00:00 -15:00'], + assert.success(function (res) { + assert(isNaN(res.rows[0].when.getTime())) + }) + ) + + client.on('drain', () => { + client.end(done) + }) }) - })) + ) }) diff --git a/packages/pg/test/integration/client/type-parser-override-tests.js b/packages/pg/test/integration/client/type-parser-override-tests.js index e806a3907..42c3dafba 100644 --- a/packages/pg/test/integration/client/type-parser-override-tests.js +++ b/packages/pg/test/integration/client/type-parser-override-tests.js @@ -1,37 +1,44 @@ 'use strict' var helper = require('./test-helper') -function testTypeParser (client, expectedResult, done) { +function testTypeParser(client, expectedResult, done) { var boolValue = true client.query('CREATE TEMP TABLE parserOverrideTest(id bool)') client.query('INSERT INTO parserOverrideTest(id) VALUES ($1)', [boolValue]) - client.query('SELECT * FROM parserOverrideTest', assert.success(function (result) { - assert.equal(result.rows[0].id, expectedResult) - done() - })) + client.query( + 'SELECT * FROM parserOverrideTest', + assert.success(function (result) { + assert.equal(result.rows[0].id, expectedResult) + done() + }) + ) } const pool = new helper.pg.Pool(helper.config) -pool.connect(assert.success(function (client1, done1) { - pool.connect(assert.success(function (client2, done2) { - var boolTypeOID = 16 - client1.setTypeParser(boolTypeOID, function () { - return 'first client' - }) - client2.setTypeParser(boolTypeOID, function () { - return 'second client' - }) +pool.connect( + assert.success(function (client1, done1) { + pool.connect( + assert.success(function (client2, done2) { + var boolTypeOID = 16 + client1.setTypeParser(boolTypeOID, function () { + return 'first client' + }) + client2.setTypeParser(boolTypeOID, function () { + return 'second client' + }) - client1.setTypeParser(boolTypeOID, 'binary', function () { - return 'first client binary' - }) - client2.setTypeParser(boolTypeOID, 'binary', function () { - return 'second client binary' - }) + client1.setTypeParser(boolTypeOID, 'binary', function () { + return 'first client binary' + }) + client2.setTypeParser(boolTypeOID, 'binary', function () { + return 'second client binary' + }) - testTypeParser(client1, 'first client', () => { - done1() - testTypeParser(client2, 'second client', () => done2(), pool.end()) - }) - })) -})) + testTypeParser(client1, 'first client', () => { + done1() + testTypeParser(client2, 'second client', () => done2(), pool.end()) + }) + }) + ) + }) +) diff --git a/packages/pg/test/integration/connection-pool/error-tests.js b/packages/pg/test/integration/connection-pool/error-tests.js index 9fe760431..f3f9cdcaa 100644 --- a/packages/pg/test/integration/connection-pool/error-tests.js +++ b/packages/pg/test/integration/connection-pool/error-tests.js @@ -6,99 +6,135 @@ const native = helper.args.native const suite = new helper.Suite() suite.test('connecting to invalid port', (cb) => { const pool = new pg.Pool({ port: 13801 }) - pool.connect().catch(e => cb()) + pool.connect().catch((e) => cb()) }) suite.test('errors emitted on checked-out clients', (cb) => { // make pool hold 2 clients const pool = new pg.Pool({ max: 2 }) // get first client - pool.connect(assert.success(function (client, done) { - client.query('SELECT NOW()', function () { - pool.connect(assert.success(function (client2, done2) { - var pidColName = 'procpid' - helper.versionGTE(client2, 90200, assert.success(function (isGreater) { - var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1' - var params = ['idle'] - if (!isGreater) { - killIdleQuery = 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE $1' - params = ['%IDLE%'] - } + pool.connect( + assert.success(function (client, done) { + client.query('SELECT NOW()', function () { + pool.connect( + assert.success(function (client2, done2) { + var pidColName = 'procpid' + helper.versionGTE( + client2, + 90200, + assert.success(function (isGreater) { + var killIdleQuery = + 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1' + var params = ['idle'] + if (!isGreater) { + killIdleQuery = + 'SELECT procpid, (SELECT pg_terminate_backend(procpid)) AS killed FROM pg_stat_activity WHERE current_query LIKE $1' + params = ['%IDLE%'] + } - client.once('error', (err) => { - client.on('error', (err) => {}) - done(err) - cb() - }) + client.once('error', (err) => { + client.on('error', (err) => {}) + done(err) + cb() + }) - // kill the connection from client - client2.query(killIdleQuery, params, assert.success(function (res) { - // check to make sure client connection actually was killed - // return client2 to the pool - done2() - pool.end() - })) - })) - })) + // kill the connection from client + client2.query( + killIdleQuery, + params, + assert.success(function (res) { + // check to make sure client connection actually was killed + // return client2 to the pool + done2() + pool.end() + }) + ) + }) + ) + }) + ) + }) }) - })) + ) }) suite.test('connection-level errors cause queued queries to fail', (cb) => { const pool = new pg.Pool() - pool.connect(assert.success((client, done) => { - client.query('SELECT pg_terminate_backend(pg_backend_pid())', assert.calls((err) => { - if (helper.args.native) { - assert.ok(err) - } else { - assert.equal(err.code, '57P01') - } - })) + pool.connect( + assert.success((client, done) => { + client.query( + 'SELECT pg_terminate_backend(pg_backend_pid())', + assert.calls((err) => { + if (helper.args.native) { + assert.ok(err) + } else { + assert.equal(err.code, '57P01') + } + }) + ) - client.once('error', assert.calls((err) => { - client.on('error', (err) => {}) - })) + client.once( + 'error', + assert.calls((err) => { + client.on('error', (err) => {}) + }) + ) - client.query('SELECT 1', assert.calls((err) => { - if (helper.args.native) { - assert.equal(err.message, 'terminating connection due to administrator command') - } else { - assert.equal(err.message, 'Connection terminated unexpectedly') - } + client.query( + 'SELECT 1', + assert.calls((err) => { + if (helper.args.native) { + assert.equal(err.message, 'terminating connection due to administrator command') + } else { + assert.equal(err.message, 'Connection terminated unexpectedly') + } - done(err) - pool.end() - cb() - })) - })) + done(err) + pool.end() + cb() + }) + ) + }) + ) }) suite.test('connection-level errors cause future queries to fail', (cb) => { const pool = new pg.Pool() - pool.connect(assert.success((client, done) => { - client.query('SELECT pg_terminate_backend(pg_backend_pid())', assert.calls((err) => { - if (helper.args.native) { - assert.ok(err) - } else { - assert.equal(err.code, '57P01') - } - })) + pool.connect( + assert.success((client, done) => { + client.query( + 'SELECT pg_terminate_backend(pg_backend_pid())', + assert.calls((err) => { + if (helper.args.native) { + assert.ok(err) + } else { + assert.equal(err.code, '57P01') + } + }) + ) - client.once('error', assert.calls((err) => { - client.on('error', (err) => {}) - client.query('SELECT 1', assert.calls((err) => { - if (helper.args.native) { - assert.equal(err.message, 'terminating connection due to administrator command') - } else { - assert.equal(err.message, 'Client has encountered a connection error and is not queryable') - } + client.once( + 'error', + assert.calls((err) => { + client.on('error', (err) => {}) + client.query( + 'SELECT 1', + assert.calls((err) => { + if (helper.args.native) { + assert.equal(err.message, 'terminating connection due to administrator command') + } else { + assert.equal(err.message, 'Client has encountered a connection error and is not queryable') + } - done(err) - pool.end() - cb() - })) - })) - })) + done(err) + pool.end() + cb() + }) + ) + }) + ) + }) + ) }) suite.test('handles socket error during pool.query and destroys it immediately', (cb) => { diff --git a/packages/pg/test/integration/connection-pool/idle-timeout-tests.js b/packages/pg/test/integration/connection-pool/idle-timeout-tests.js index c48f712ea..f36b6938e 100644 --- a/packages/pg/test/integration/connection-pool/idle-timeout-tests.js +++ b/packages/pg/test/integration/connection-pool/idle-timeout-tests.js @@ -4,9 +4,11 @@ var helper = require('./test-helper') new helper.Suite().test('idle timeout', function () { const config = Object.assign({}, helper.config, { idleTimeoutMillis: 50 }) const pool = new helper.pg.Pool(config) - pool.connect(assert.calls(function (err, client, done) { - assert(!err) - client.query('SELECT NOW()') - done() - })) + pool.connect( + assert.calls(function (err, client, done) { + assert(!err) + client.query('SELECT NOW()') + done() + }) + ) }) diff --git a/packages/pg/test/integration/connection-pool/native-instance-tests.js b/packages/pg/test/integration/connection-pool/native-instance-tests.js index 5347677a9..a981503e8 100644 --- a/packages/pg/test/integration/connection-pool/native-instance-tests.js +++ b/packages/pg/test/integration/connection-pool/native-instance-tests.js @@ -5,12 +5,14 @@ var native = helper.args.native var pool = new pg.Pool() -pool.connect(assert.calls(function (err, client, done) { - if (native) { - assert(client.native) - } else { - assert(!client.native) - } - done() - pool.end() -})) +pool.connect( + assert.calls(function (err, client, done) { + if (native) { + assert(client.native) + } else { + assert(!client.native) + } + done() + pool.end() + }) +) diff --git a/packages/pg/test/integration/connection-pool/yield-support-tests.js b/packages/pg/test/integration/connection-pool/yield-support-tests.js index 08d89b308..00508f5d6 100644 --- a/packages/pg/test/integration/connection-pool/yield-support-tests.js +++ b/packages/pg/test/integration/connection-pool/yield-support-tests.js @@ -3,18 +3,21 @@ var helper = require('./test-helper') var co = require('co') const pool = new helper.pg.Pool() -new helper.Suite().test('using coroutines works with promises', co.wrap(function * () { - var client = yield pool.connect() - var res = yield client.query('SELECT $1::text as name', ['foo']) - assert.equal(res.rows[0].name, 'foo') +new helper.Suite().test( + 'using coroutines works with promises', + co.wrap(function* () { + var client = yield pool.connect() + var res = yield client.query('SELECT $1::text as name', ['foo']) + assert.equal(res.rows[0].name, 'foo') - var threw = false - try { - yield client.query('SELECT LKDSJDSLKFJ') - } catch (e) { - threw = true - } - assert(threw) - client.release() - yield pool.end() -})) + var threw = false + try { + yield client.query('SELECT LKDSJDSLKFJ') + } catch (e) { + threw = true + } + assert(threw) + client.release() + yield pool.end() + }) +) diff --git a/packages/pg/test/integration/connection/bound-command-tests.js b/packages/pg/test/integration/connection/bound-command-tests.js index c6cf84e11..a707bc4b1 100644 --- a/packages/pg/test/integration/connection/bound-command-tests.js +++ b/packages/pg/test/integration/connection/bound-command-tests.js @@ -5,7 +5,7 @@ var helper = require(__dirname + '/test-helper') test('flushing once', function () { helper.connect(function (con) { con.parse({ - text: 'select * from ids' + text: 'select * from ids', }) con.bind() @@ -50,7 +50,7 @@ test('sending many flushes', function () { }) con.parse({ - text: 'select * from ids order by id' + text: 'select * from ids order by id', }) con.flush() diff --git a/packages/pg/test/integration/connection/copy-tests.js b/packages/pg/test/integration/connection/copy-tests.js index c11632c37..1b7d06ed1 100644 --- a/packages/pg/test/integration/connection/copy-tests.js +++ b/packages/pg/test/integration/connection/copy-tests.js @@ -8,13 +8,17 @@ test('COPY FROM events check', function () { con.on('copyInResponse', function () { con.endCopyFrom() }) - assert.emits(con, 'copyInResponse', + assert.emits( + con, + 'copyInResponse', function () { con.endCopyFrom() }, 'backend should emit copyInResponse after COPY FROM query' ) - assert.emits(con, 'commandComplete', + assert.emits( + con, + 'commandComplete', function () { con.end() }, @@ -25,17 +29,11 @@ test('COPY FROM events check', function () { test('COPY TO events check', function () { helper.connect(function (con) { var stdoutStream = con.query('COPY person TO STDOUT') - assert.emits(con, 'copyOutResponse', - function () { - }, - 'backend should emit copyOutResponse after COPY TO query' - ) - assert.emits(con, 'copyData', - function () { - }, - 'backend should emit copyData on every data row' - ) - assert.emits(con, 'copyDone', + assert.emits(con, 'copyOutResponse', function () {}, 'backend should emit copyOutResponse after COPY TO query') + assert.emits(con, 'copyData', function () {}, 'backend should emit copyData on every data row') + assert.emits( + con, + 'copyDone', function () { con.end() }, diff --git a/packages/pg/test/integration/connection/dynamic-password-tests.js b/packages/pg/test/integration/connection/dynamic-password-tests.js index 20b509533..3ab39d0bc 100644 --- a/packages/pg/test/integration/connection/dynamic-password-tests.js +++ b/packages/pg/test/integration/connection/dynamic-password-tests.js @@ -3,116 +3,117 @@ const assert = require('assert') const helper = require('./../test-helper') const suite = new helper.Suite() const pg = require('../../../lib/index') -const Client = pg.Client; +const Client = pg.Client const password = process.env.PGPASSWORD || null -const sleep = millis => new Promise(resolve => setTimeout(resolve, millis)) +const sleep = (millis) => new Promise((resolve) => setTimeout(resolve, millis)) if (!password) { - // skip these tests; no password will be requested - return + // skip these tests; no password will be requested + return } suite.testAsync('Get password from a sync function', () => { - let wasCalled = false - function getPassword() { - wasCalled = true - return password - } - const client = new Client({ - password: getPassword, - }) - return client.connect() - .then(() => { - assert.ok(wasCalled, 'Our password function should have been called') - return client.end() - }) + let wasCalled = false + function getPassword() { + wasCalled = true + return password + } + const client = new Client({ + password: getPassword, + }) + return client.connect().then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + return client.end() + }) }) suite.testAsync('Throw error from a sync function', () => { - let wasCalled = false - const myError = new Error('Oops!') - function getPassword() { - wasCalled = true - throw myError - } - const client = new Client({ - password: getPassword, + let wasCalled = false + const myError = new Error('Oops!') + function getPassword() { + wasCalled = true + throw myError + } + const client = new Client({ + password: getPassword, + }) + let wasThrown = false + return client + .connect() + .catch((err) => { + assert.equal(err, myError, 'Our sync error should have been thrown') + wasThrown = true + }) + .then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + assert.ok(wasThrown, 'Our error should have been thrown') + return client.end() }) - let wasThrown = false - return client.connect() - .catch(err => { - assert.equal(err, myError, 'Our sync error should have been thrown') - wasThrown = true - }) - .then(() => { - assert.ok(wasCalled, 'Our password function should have been called') - assert.ok(wasThrown, 'Our error should have been thrown') - return client.end() - }) }) suite.testAsync('Get password from a function asynchronously', () => { - let wasCalled = false - function getPassword() { - wasCalled = true - return sleep(100).then(() => password) - } - const client = new Client({ - password: getPassword, - }) - return client.connect() - .then(() => { - assert.ok(wasCalled, 'Our password function should have been called') - return client.end() - }) + let wasCalled = false + function getPassword() { + wasCalled = true + return sleep(100).then(() => password) + } + const client = new Client({ + password: getPassword, + }) + return client.connect().then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + return client.end() + }) }) suite.testAsync('Throw error from an async function', () => { - let wasCalled = false - const myError = new Error('Oops!') - function getPassword() { - wasCalled = true - return sleep(100).then(() => { - throw myError - }) - } - const client = new Client({ - password: getPassword, + let wasCalled = false + const myError = new Error('Oops!') + function getPassword() { + wasCalled = true + return sleep(100).then(() => { + throw myError + }) + } + const client = new Client({ + password: getPassword, + }) + let wasThrown = false + return client + .connect() + .catch((err) => { + assert.equal(err, myError, 'Our async error should have been thrown') + wasThrown = true + }) + .then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + assert.ok(wasThrown, 'Our error should have been thrown') + return client.end() }) - let wasThrown = false - return client.connect() - .catch(err => { - assert.equal(err, myError, 'Our async error should have been thrown') - wasThrown = true - }) - .then(() => { - assert.ok(wasCalled, 'Our password function should have been called') - assert.ok(wasThrown, 'Our error should have been thrown') - return client.end() - }) }) suite.testAsync('Password function must return a string', () => { - let wasCalled = false - function getPassword() { - wasCalled = true - // Return a password that is not a string - return 12345 - } - const client = new Client({ - password: getPassword, + let wasCalled = false + function getPassword() { + wasCalled = true + // Return a password that is not a string + return 12345 + } + const client = new Client({ + password: getPassword, + }) + let wasThrown = false + return client + .connect() + .catch((err) => { + assert.ok(err instanceof TypeError, 'A TypeError should have been thrown') + assert.equal(err.message, 'Password must be a string') + wasThrown = true + }) + .then(() => { + assert.ok(wasCalled, 'Our password function should have been called') + assert.ok(wasThrown, 'Our error should have been thrown') + return client.end() }) - let wasThrown = false - return client.connect() - .catch(err => { - assert.ok(err instanceof TypeError, 'A TypeError should have been thrown') - assert.equal(err.message, 'Password must be a string') - wasThrown = true - }) - .then(() => { - assert.ok(wasCalled, 'Our password function should have been called') - assert.ok(wasThrown, 'Our error should have been thrown') - return client.end() - }) }) diff --git a/packages/pg/test/integration/connection/test-helper.js b/packages/pg/test/integration/connection/test-helper.js index 99661a469..ca978af4f 100644 --- a/packages/pg/test/integration/connection/test-helper.js +++ b/packages/pg/test/integration/connection/test-helper.js @@ -6,7 +6,7 @@ var utils = require(__dirname + '/../../../lib/utils') var connect = function (callback) { var username = helper.args.user var database = helper.args.database - var con = new Connection({stream: new net.Stream()}) + var con = new Connection({ stream: new net.Stream() }) con.on('error', function (error) { console.log(error) throw new Error('Connection error') @@ -15,13 +15,13 @@ var connect = function (callback) { con.once('connect', function () { con.startup({ user: username, - database: database + database: database, }) con.once('authenticationCleartextPassword', function () { con.password(helper.args.password) }) con.once('authenticationMD5Password', function (msg) { - con.password(utils.postgresMd5PasswordHash(helper.args.user, helper.args.password, msg.salt)); + con.password(utils.postgresMd5PasswordHash(helper.args.user, helper.args.password, msg.salt)) }) con.once('readyForQuery', function () { con.query('create temp table ids(id integer)') @@ -36,5 +36,5 @@ var connect = function (callback) { } module.exports = { - connect: connect + connect: connect, } diff --git a/packages/pg/test/integration/domain-tests.js b/packages/pg/test/integration/domain-tests.js index a02f3942a..ce46eb8a4 100644 --- a/packages/pg/test/integration/domain-tests.js +++ b/packages/pg/test/integration/domain-tests.js @@ -10,11 +10,13 @@ const Pool = helper.pg.Pool suite.test('no domain', function (cb) { assert(!process.domain) const pool = new Pool() - pool.connect(assert.success(function (client, done) { - assert(!process.domain) - done() - pool.end(cb) - })) + pool.connect( + assert.success(function (client, done) { + assert(!process.domain) + done() + pool.end(cb) + }) + ) }) suite.test('with domain', function (cb) { @@ -24,17 +26,22 @@ suite.test('with domain', function (cb) { domain.run(function () { var startingDomain = process.domain assert(startingDomain) - pool.connect(assert.success(function (client, done) { - assert(process.domain, 'no domain exists in connect callback') - assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') - var query = client.query('SELECT NOW()', assert.success(function () { - assert(process.domain, 'no domain exists in query callback') + pool.connect( + assert.success(function (client, done) { + assert(process.domain, 'no domain exists in connect callback') assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') - done(true) - process.domain.exit() - pool.end(cb) - })) - })) + var query = client.query( + 'SELECT NOW()', + assert.success(function () { + assert(process.domain, 'no domain exists in query callback') + assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') + done(true) + process.domain.exit() + pool.end(cb) + }) + ) + }) + ) }) }) @@ -45,9 +52,11 @@ suite.test('error on domain', function (cb) { pool.end(cb) }) domain.run(function () { - pool.connect(assert.success(function (client, done) { - client.query(new Query('SELECT SLDKJFLSKDJF')) - client.on('drain', done) - })) + pool.connect( + assert.success(function (client, done) { + client.query(new Query('SELECT SLDKJFLSKDJF')) + client.on('drain', done) + }) + ) }) }) diff --git a/packages/pg/test/integration/gh-issues/130-tests.js b/packages/pg/test/integration/gh-issues/130-tests.js index db3aeacd5..8b097b99b 100644 --- a/packages/pg/test/integration/gh-issues/130-tests.js +++ b/packages/pg/test/integration/gh-issues/130-tests.js @@ -18,8 +18,11 @@ pool.connect(function (err, client, done) { if (helper.args.host) psql = psql + ' -h ' + helper.args.host if (helper.args.port) psql = psql + ' -p ' + helper.args.port if (helper.args.user) psql = psql + ' -U ' + helper.args.user - exec(psql + ' -c "select pg_terminate_backend(' + pid + ')" template1', assert.calls(function (error, stdout, stderr) { - assert.ifError(error) - })) + exec( + psql + ' -c "select pg_terminate_backend(' + pid + ')" template1', + assert.calls(function (error, stdout, stderr) { + assert.ifError(error) + }) + ) }) }) diff --git a/packages/pg/test/integration/gh-issues/131-tests.js b/packages/pg/test/integration/gh-issues/131-tests.js index 87a7b241f..5838067fc 100644 --- a/packages/pg/test/integration/gh-issues/131-tests.js +++ b/packages/pg/test/integration/gh-issues/131-tests.js @@ -6,17 +6,28 @@ var suite = new helper.Suite() suite.test('parsing array decimal results', function (done) { const pool = new pg.Pool() - pool.connect(assert.calls(function (err, client, release) { - assert(!err) - client.query('CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])') - client.query(new pg.Query('INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')')).on('error', console.log) - client.query('SELECT decimals FROM why', assert.success(function (result) { - assert.lengthIs(result.rows[0].decimals, 3) - assert.equal(result.rows[0].decimals[0], 0.1) - assert.equal(result.rows[0].decimals[1], 0.05) - assert.equal(result.rows[0].decimals[2], 3.654) - release() - pool.end(done) - })) - })) + pool.connect( + assert.calls(function (err, client, release) { + assert(!err) + client.query('CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])') + client + .query( + new pg.Query( + 'INSERT INTO why(names, numbors, decimals) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\', \'{.1, 0.05, 3.654}\')' + ) + ) + .on('error', console.log) + client.query( + 'SELECT decimals FROM why', + assert.success(function (result) { + assert.lengthIs(result.rows[0].decimals, 3) + assert.equal(result.rows[0].decimals[0], 0.1) + assert.equal(result.rows[0].decimals[1], 0.05) + assert.equal(result.rows[0].decimals[2], 3.654) + release() + pool.end(done) + }) + ) + }) + ) }) diff --git a/packages/pg/test/integration/gh-issues/1382-tests.js b/packages/pg/test/integration/gh-issues/1382-tests.js index 3cbc31cf1..e80924c64 100644 --- a/packages/pg/test/integration/gh-issues/1382-tests.js +++ b/packages/pg/test/integration/gh-issues/1382-tests.js @@ -1,4 +1,4 @@ -"use strict" +'use strict' var helper = require('./../test-helper') const suite = new helper.Suite() diff --git a/packages/pg/test/integration/gh-issues/1542-tests.js b/packages/pg/test/integration/gh-issues/1542-tests.js index 4d30d6020..f65aa3fb6 100644 --- a/packages/pg/test/integration/gh-issues/1542-tests.js +++ b/packages/pg/test/integration/gh-issues/1542-tests.js @@ -1,15 +1,12 @@ - -"use strict" +'use strict' const helper = require('./../test-helper') const assert = require('assert') const suite = new helper.Suite() suite.testAsync('BoundPool can be subclassed', async () => { - const Pool = helper.pg.Pool; - class SubPool extends Pool { - - } + const Pool = helper.pg.Pool + class SubPool extends Pool {} const subPool = new SubPool() const client = await subPool.connect() client.release() @@ -18,7 +15,7 @@ suite.testAsync('BoundPool can be subclassed', async () => { }) suite.test('calling pg.Pool without new throws', () => { - const Pool = helper.pg.Pool; + const Pool = helper.pg.Pool assert.throws(() => { const pool = Pool() }) diff --git a/packages/pg/test/integration/gh-issues/1854-tests.js b/packages/pg/test/integration/gh-issues/1854-tests.js index 8dbe37ab5..92ac6ec35 100644 --- a/packages/pg/test/integration/gh-issues/1854-tests.js +++ b/packages/pg/test/integration/gh-issues/1854-tests.js @@ -1,4 +1,4 @@ -"use strict" +'use strict' var helper = require('./../test-helper') const suite = new helper.Suite() @@ -10,17 +10,17 @@ suite.test('Parameter serialization errors should not cause query to hang', (don } const client = new helper.pg.Client() const expectedErr = new Error('Serialization error') - client.connect() + client + .connect() .then(() => { const obj = { toPostgres: function () { throw expectedErr - } + }, } - return client.query('SELECT $1::text', [obj]) - .then(() => { - throw new Error('Expected a serialization error to be thrown but no error was thrown') - }) + return client.query('SELECT $1::text', [obj]).then(() => { + throw new Error('Expected a serialization error to be thrown but no error was thrown') + }) }) .catch((err) => { client.end(() => {}) diff --git a/packages/pg/test/integration/gh-issues/199-tests.js b/packages/pg/test/integration/gh-issues/199-tests.js index bb93d4260..2710020c5 100644 --- a/packages/pg/test/integration/gh-issues/199-tests.js +++ b/packages/pg/test/integration/gh-issues/199-tests.js @@ -5,7 +5,8 @@ var client = helper.client() client.query('CREATE TEMP TABLE arrtest (n integer, s varchar)') client.query("INSERT INTO arrtest VALUES (4, 'foo'), (5, 'bar'), (6, 'baz');") -var qText = "SELECT \ +var qText = + "SELECT \ ARRAY[1, 2, 3] AS b,\ ARRAY['xx', 'yy', 'zz'] AS c,\ ARRAY(SELECT n FROM arrtest) AS d,\ diff --git a/packages/pg/test/integration/gh-issues/1992-tests.js b/packages/pg/test/integration/gh-issues/1992-tests.js index 1832f5f8a..abb2167af 100644 --- a/packages/pg/test/integration/gh-issues/1992-tests.js +++ b/packages/pg/test/integration/gh-issues/1992-tests.js @@ -1,5 +1,4 @@ - -"use strict" +'use strict' const helper = require('./../test-helper') const assert = require('assert') diff --git a/packages/pg/test/integration/gh-issues/2056-tests.js b/packages/pg/test/integration/gh-issues/2056-tests.js index e025a1adc..2a12678b9 100644 --- a/packages/pg/test/integration/gh-issues/2056-tests.js +++ b/packages/pg/test/integration/gh-issues/2056-tests.js @@ -1,11 +1,9 @@ - -"use strict" +'use strict' var helper = require('./../test-helper') var assert = require('assert') const suite = new helper.Suite() - suite.test('All queries should return a result array', (done) => { const client = new helper.pg.Client() client.connect() @@ -13,8 +11,8 @@ suite.test('All queries should return a result array', (done) => { promises.push(client.query('CREATE TEMP TABLE foo(bar TEXT)')) promises.push(client.query('INSERT INTO foo(bar) VALUES($1)', ['qux'])) promises.push(client.query('SELECT * FROM foo WHERE bar = $1', ['foo'])) - Promise.all(promises).then(results => { - results.forEach(res => { + Promise.all(promises).then((results) => { + results.forEach((res) => { assert(Array.isArray(res.fields)) assert(Array.isArray(res.rows)) }) diff --git a/packages/pg/test/integration/gh-issues/2064-tests.js b/packages/pg/test/integration/gh-issues/2064-tests.js index 64c150bd0..6118ca2f4 100644 --- a/packages/pg/test/integration/gh-issues/2064-tests.js +++ b/packages/pg/test/integration/gh-issues/2064-tests.js @@ -1,5 +1,4 @@ - -"use strict" +'use strict' const helper = require('./../test-helper') const assert = require('assert') const util = require('util') @@ -11,22 +10,22 @@ const password = 'FAIL THIS TEST' suite.test('Password should not exist in toString() output', () => { const pool = new helper.pg.Pool({ password }) const client = new helper.pg.Client({ password }) - assert(pool.toString().indexOf(password) === -1); - assert(client.toString().indexOf(password) === -1); + assert(pool.toString().indexOf(password) === -1) + assert(client.toString().indexOf(password) === -1) }) suite.test('Password should not exist in util.inspect output', () => { const pool = new helper.pg.Pool({ password }) const client = new helper.pg.Client({ password }) - const depth = 20; - assert(util.inspect(pool, { depth }).indexOf(password) === -1); - assert(util.inspect(client, { depth }).indexOf(password) === -1); + const depth = 20 + assert(util.inspect(pool, { depth }).indexOf(password) === -1) + assert(util.inspect(client, { depth }).indexOf(password) === -1) }) suite.test('Password should not exist in json.stringfy output', () => { const pool = new helper.pg.Pool({ password }) const client = new helper.pg.Client({ password }) - const depth = 20; - assert(JSON.stringify(pool).indexOf(password) === -1); - assert(JSON.stringify(client).indexOf(password) === -1); + const depth = 20 + assert(JSON.stringify(pool).indexOf(password) === -1) + assert(JSON.stringify(client).indexOf(password) === -1) }) diff --git a/packages/pg/test/integration/gh-issues/2079-tests.js b/packages/pg/test/integration/gh-issues/2079-tests.js index bec8e481f..be2485794 100644 --- a/packages/pg/test/integration/gh-issues/2079-tests.js +++ b/packages/pg/test/integration/gh-issues/2079-tests.js @@ -1,5 +1,4 @@ - -"use strict" +'use strict' var helper = require('./../test-helper') var assert = require('assert') @@ -7,7 +6,7 @@ const suite = new helper.Suite() // makes a backend server that responds with a non 'S' ssl response buffer let makeTerminatingBackend = (byte) => { - const { createServer } = require('net') + const { createServer } = require('net') const server = createServer((socket) => { // attach a listener so the socket can drain @@ -42,7 +41,6 @@ suite.test('SSL connection error allows event loop to exit', (done) => { }) }) - suite.test('Non "S" response code allows event loop to exit', (done) => { const port = makeTerminatingBackend('X') const client = new helper.pg.Client({ ssl: 'require', port }) @@ -53,4 +51,3 @@ suite.test('Non "S" response code allows event loop to exit', (done) => { done() }) }) - diff --git a/packages/pg/test/integration/gh-issues/2085-tests.js b/packages/pg/test/integration/gh-issues/2085-tests.js index 8ccdca150..23fd71d07 100644 --- a/packages/pg/test/integration/gh-issues/2085-tests.js +++ b/packages/pg/test/integration/gh-issues/2085-tests.js @@ -1,15 +1,15 @@ - - -"use strict" +'use strict' var helper = require('./../test-helper') var assert = require('assert') const suite = new helper.Suite() suite.testAsync('it should connect over ssl', async () => { - const ssl = helper.args.native ? 'require' : { - rejectUnauthorized: false - } + const ssl = helper.args.native + ? 'require' + : { + rejectUnauthorized: false, + } const client = new helper.pg.Client({ ssl }) await client.connect() const { rows } = await client.query('SELECT NOW()') @@ -18,12 +18,12 @@ suite.testAsync('it should connect over ssl', async () => { }) suite.testAsync('it should fail with self-signed cert error w/o rejectUnauthorized being passed', async () => { - const ssl = helper.args.native ? 'verify-ca' : { } + const ssl = helper.args.native ? 'verify-ca' : {} const client = new helper.pg.Client({ ssl }) try { await client.connect() } catch (e) { - return; + return } throw new Error('this test should have thrown an error due to self-signed cert') }) diff --git a/packages/pg/test/integration/gh-issues/2108-tests.js b/packages/pg/test/integration/gh-issues/2108-tests.js index 9832dae37..cbf2caabd 100644 --- a/packages/pg/test/integration/gh-issues/2108-tests.js +++ b/packages/pg/test/integration/gh-issues/2108-tests.js @@ -1,4 +1,4 @@ -"use strict" +'use strict' var helper = require('./../test-helper') const suite = new helper.Suite() diff --git a/packages/pg/test/integration/gh-issues/507-tests.js b/packages/pg/test/integration/gh-issues/507-tests.js index dadc1c83f..9c3409199 100644 --- a/packages/pg/test/integration/gh-issues/507-tests.js +++ b/packages/pg/test/integration/gh-issues/507-tests.js @@ -4,14 +4,16 @@ var pg = helper.pg new helper.Suite().test('parsing array results', function (cb) { const pool = new pg.Pool() - pool.connect(assert.success(function (client, done) { - client.query('CREATE TEMP TABLE test_table(bar integer, "baz\'s" integer)') - client.query('INSERT INTO test_table(bar, "baz\'s") VALUES(1, 1), (2, 2)') - client.query('SELECT * FROM test_table', function (err, res) { - assert.equal(res.rows[0]["baz's"], 1) - assert.equal(res.rows[1]["baz's"], 2) - done() - pool.end(cb) + pool.connect( + assert.success(function (client, done) { + client.query('CREATE TEMP TABLE test_table(bar integer, "baz\'s" integer)') + client.query('INSERT INTO test_table(bar, "baz\'s") VALUES(1, 1), (2, 2)') + client.query('SELECT * FROM test_table', function (err, res) { + assert.equal(res.rows[0]["baz's"], 1) + assert.equal(res.rows[1]["baz's"], 2) + done() + pool.end(cb) + }) }) - })) + ) }) diff --git a/packages/pg/test/integration/gh-issues/600-tests.js b/packages/pg/test/integration/gh-issues/600-tests.js index ea6154e3f..af679ee8e 100644 --- a/packages/pg/test/integration/gh-issues/600-tests.js +++ b/packages/pg/test/integration/gh-issues/600-tests.js @@ -5,40 +5,46 @@ const suite = new helper.Suite() var db = helper.client() -function createTableFoo (callback) { +function createTableFoo(callback) { db.query('create temp table foo(column1 int, column2 int)', callback) } -function createTableBar (callback) { +function createTableBar(callback) { db.query('create temp table bar(column1 text, column2 text)', callback) } -function insertDataFoo (callback) { - db.query({ - name: 'insertFoo', - text: 'insert into foo values($1,$2)', - values: ['one', 'two'] - }, callback) +function insertDataFoo(callback) { + db.query( + { + name: 'insertFoo', + text: 'insert into foo values($1,$2)', + values: ['one', 'two'], + }, + callback + ) } -function insertDataBar (callback) { - db.query({ - name: 'insertBar', - text: 'insert into bar values($1,$2)', - values: ['one', 'two'] - }, callback) +function insertDataBar(callback) { + db.query( + { + name: 'insertBar', + text: 'insert into bar values($1,$2)', + values: ['one', 'two'], + }, + callback + ) } -function startTransaction (callback) { +function startTransaction(callback) { db.query('BEGIN', callback) } -function endTransaction (callback) { +function endTransaction(callback) { db.query('COMMIT', callback) } -function doTransaction (callback) { - // The transaction runs startTransaction, then all queries, then endTransaction, - // no matter if there has been an error in a query in the middle. +function doTransaction(callback) { + // The transaction runs startTransaction, then all queries, then endTransaction, + // no matter if there has been an error in a query in the middle. startTransaction(function () { insertDataFoo(function () { insertDataBar(function () { @@ -48,18 +54,16 @@ function doTransaction (callback) { }) } -var steps = [ - createTableFoo, - createTableBar, - doTransaction, - insertDataBar -] +var steps = [createTableFoo, createTableBar, doTransaction, insertDataBar] suite.test('test if query fails', function (done) { - async.series(steps, assert.success(function () { - db.end() - done() - })) + async.series( + steps, + assert.success(function () { + db.end() + done() + }) + ) }) suite.test('test if prepare works but bind fails', function (done) { @@ -67,14 +71,20 @@ suite.test('test if prepare works but bind fails', function (done) { var q = { text: 'SELECT $1::int as name', values: ['brian'], - name: 'test' + name: 'test', } - client.query(q, assert.calls(function (err, res) { - q.values = [1] - client.query(q, assert.calls(function (err, res) { - assert.ifError(err) - client.end() - done() - })) - })) + client.query( + q, + assert.calls(function (err, res) { + q.values = [1] + client.query( + q, + assert.calls(function (err, res) { + assert.ifError(err) + client.end() + done() + }) + ) + }) + ) }) diff --git a/packages/pg/test/integration/gh-issues/699-tests.js b/packages/pg/test/integration/gh-issues/699-tests.js index d4c9eab75..c9be63bfa 100644 --- a/packages/pg/test/integration/gh-issues/699-tests.js +++ b/packages/pg/test/integration/gh-issues/699-tests.js @@ -1,31 +1,31 @@ -"use strict"; -var helper = require('../test-helper'); -var assert = require('assert'); -var copyFrom = require('pg-copy-streams').from; +'use strict' +var helper = require('../test-helper') +var assert = require('assert') +var copyFrom = require('pg-copy-streams').from -if(helper.args.native) return; +if (helper.args.native) return const pool = new helper.pg.Pool() pool.connect(function (err, client, done) { - if (err) throw err; + if (err) throw err - var c = 'CREATE TEMP TABLE employee (id integer, fname varchar(400), lname varchar(400))'; + var c = 'CREATE TEMP TABLE employee (id integer, fname varchar(400), lname varchar(400))' client.query(c, function (err) { - if (err) throw err; + if (err) throw err - var stream = client.query(copyFrom("COPY employee FROM STDIN")); + var stream = client.query(copyFrom('COPY employee FROM STDIN')) stream.on('end', function () { - done(); + done() setTimeout(() => { pool.end() }, 50) - }); + }) for (var i = 1; i <= 5; i++) { - var line = ['1\ttest', i, '\tuser', i, '\n']; - stream.write(line.join('')); + var line = ['1\ttest', i, '\tuser', i, '\n'] + stream.write(line.join('')) } - stream.end(); - }); -}); + stream.end() + }) +}) diff --git a/packages/pg/test/integration/gh-issues/787-tests.js b/packages/pg/test/integration/gh-issues/787-tests.js index 456c86463..9a3198f52 100644 --- a/packages/pg/test/integration/gh-issues/787-tests.js +++ b/packages/pg/test/integration/gh-issues/787-tests.js @@ -4,8 +4,9 @@ const pool = new helper.pg.Pool() pool.connect(function (err, client) { var q = { - name: 'This is a super long query name just so I can test that an error message is properly spit out to console.error without throwing an exception or anything', - text: 'SELECT NOW()' + name: + 'This is a super long query name just so I can test that an error message is properly spit out to console.error without throwing an exception or anything', + text: 'SELECT NOW()', } client.query(q, function () { client.end() diff --git a/packages/pg/test/integration/gh-issues/882-tests.js b/packages/pg/test/integration/gh-issues/882-tests.js index 6b4a3e2e6..4a8ef6474 100644 --- a/packages/pg/test/integration/gh-issues/882-tests.js +++ b/packages/pg/test/integration/gh-issues/882-tests.js @@ -2,7 +2,7 @@ // client should not hang on an empty query var helper = require('../test-helper') var client = helper.client() -client.query({ name: 'foo1', text: null}) +client.query({ name: 'foo1', text: null }) client.query({ name: 'foo2', text: ' ' }) client.query({ name: 'foo3', text: '' }, function (err, res) { client.end() diff --git a/packages/pg/test/integration/gh-issues/981-tests.js b/packages/pg/test/integration/gh-issues/981-tests.js index 6348d05a9..998adea3a 100644 --- a/packages/pg/test/integration/gh-issues/981-tests.js +++ b/packages/pg/test/integration/gh-issues/981-tests.js @@ -1,9 +1,9 @@ -"use strict"; -var helper = require('./../test-helper'); +'use strict' +var helper = require('./../test-helper') //native bindings are only installed for native tests if (!helper.args.native) { - return; + return } var assert = require('assert') @@ -13,26 +13,25 @@ var native = require('../../../lib').native var JsClient = require('../../../lib/client') var NativeClient = require('../../../lib/native') -assert(pg.Client === JsClient); -assert(native.Client === NativeClient); +assert(pg.Client === JsClient) +assert(native.Client === NativeClient) const jsPool = new pg.Pool() const nativePool = new native.Pool() const suite = new helper.Suite() -suite.test('js pool returns js client', cb => { +suite.test('js pool returns js client', (cb) => { jsPool.connect(function (err, client, done) { - assert(client instanceof JsClient); + assert(client instanceof JsClient) done() jsPool.end(cb) }) - }) -suite.test('native pool returns native client', cb => { +suite.test('native pool returns native client', (cb) => { nativePool.connect(function (err, client, done) { - assert(client instanceof NativeClient); + assert(client instanceof NativeClient) done() nativePool.end(cb) - }); + }) }) diff --git a/packages/pg/test/integration/test-helper.js b/packages/pg/test/integration/test-helper.js index fb9ac6dac..9b8b58c60 100644 --- a/packages/pg/test/integration/test-helper.js +++ b/packages/pg/test/integration/test-helper.js @@ -15,11 +15,14 @@ helper.client = function (cb) { } helper.versionGTE = function (client, testVersion, callback) { - client.query('SHOW server_version_num', assert.calls(function (err, result) { - if (err) return callback(err) - var version = parseInt(result.rows[0].server_version_num, 10) - return callback(null, version >= testVersion) - })) + client.query( + 'SHOW server_version_num', + assert.calls(function (err, result) { + if (err) return callback(err) + var version = parseInt(result.rows[0].server_version_num, 10) + return callback(null, version >= testVersion) + }) + ) } // export parent helper stuffs diff --git a/packages/pg/test/native/callback-api-tests.js b/packages/pg/test/native/callback-api-tests.js index a7fff1181..80fdcdf56 100644 --- a/packages/pg/test/native/callback-api-tests.js +++ b/packages/pg/test/native/callback-api-tests.js @@ -7,16 +7,23 @@ const suite = new helper.Suite() suite.test('fires callback with results', function (done) { var client = new Client(helper.config) client.connect() - client.query('SELECT 1 as num', assert.calls(function (err, result) { - assert(!err) - assert.equal(result.rows[0].num, 1) - assert.strictEqual(result.rowCount, 1) - client.query('SELECT * FROM person WHERE name = $1', ['Brian'], assert.calls(function (err, result) { + client.query( + 'SELECT 1 as num', + assert.calls(function (err, result) { assert(!err) - assert.equal(result.rows[0].name, 'Brian') - client.end(done) - })) - })) + assert.equal(result.rows[0].num, 1) + assert.strictEqual(result.rowCount, 1) + client.query( + 'SELECT * FROM person WHERE name = $1', + ['Brian'], + assert.calls(function (err, result) { + assert(!err) + assert.equal(result.rows[0].name, 'Brian') + client.end(done) + }) + ) + }) + ) }) suite.test('preserves domain', function (done) { diff --git a/packages/pg/test/native/evented-api-tests.js b/packages/pg/test/native/evented-api-tests.js index 4fac0415b..ba0496eff 100644 --- a/packages/pg/test/native/evented-api-tests.js +++ b/packages/pg/test/native/evented-api-tests.js @@ -24,7 +24,7 @@ test('multiple results', function () { }) assert.emits(q, 'end', function () { test('query with config', function () { - var q2 = client.query(new Query({text: 'SELECT 1 as num'})) + var q2 = client.query(new Query({ text: 'SELECT 1 as num' })) assert.emits(q2, 'row', function (row) { assert.strictEqual(row.num, 1) assert.emits(q2, 'end', function () { @@ -50,10 +50,12 @@ test('parameterized queries', function () { test('with object config for query', function () { var client = setupClient() - var q = client.query(new Query({ - text: 'SELECT name FROM boom WHERE name = $1', - values: ['Brian'] - })) + var q = client.query( + new Query({ + text: 'SELECT name FROM boom WHERE name = $1', + values: ['Brian'], + }) + ) assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Brian') }) @@ -64,7 +66,9 @@ test('parameterized queries', function () { test('multiple parameters', function () { var client = setupClient() - var q = client.query(new Query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name COLLATE "C"', ['Aaron', 'Brian'])) + var q = client.query( + new Query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name COLLATE "C"', ['Aaron', 'Brian']) + ) assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Aaron') assert.emits(q, 'row', function (row) { diff --git a/packages/pg/test/suite.js b/packages/pg/test/suite.js index 4161ddc0a..7d19edbb0 100644 --- a/packages/pg/test/suite.js +++ b/packages/pg/test/suite.js @@ -3,13 +3,13 @@ const async = require('async') class Test { - constructor (name, cb) { + constructor(name, cb) { this.name = name this.action = cb this.timeout = 5000 } - run (cb) { + run(cb) { try { this._run(cb) } catch (e) { @@ -17,7 +17,7 @@ class Test { } } - _run (cb) { + _run(cb) { if (!this.action) { console.log(`${this.name} skipped`) return cb() @@ -27,9 +27,7 @@ class Test { if (!(result || 0).then) { return cb() } - result - .then(() => cb()) - .catch(err => cb(err || new Error('Unhandled promise rejection'))) + result.then(() => cb()).catch((err) => cb(err || new Error('Unhandled promise rejection'))) } else { this.action.call(this, cb) } @@ -37,13 +35,13 @@ class Test { } class Suite { - constructor (name) { + constructor(name) { console.log('') this._queue = async.queue(this.run.bind(this), 1) - this._queue.drain = () => { } + this._queue.drain = () => {} } - run (test, cb) { + run(test, cb) { process.stdout.write(' ' + test.name + ' ') if (!test.action) { process.stdout.write('? - SKIPPED\n') @@ -68,7 +66,7 @@ class Suite { }) } - test (name, cb) { + test(name, cb) { const test = new Test(name, cb) this._queue.push(test) } @@ -78,8 +76,8 @@ class Suite { * successfully then the test will pass. If the Promise rejects with an * error then the test will be considered failed. */ - testAsync (name, action) { - const test = new Test(name, cb => { + testAsync(name, action) { + const test = new Test(name, (cb) => { Promise.resolve() .then(action) .then(() => cb(null), cb) diff --git a/packages/pg/test/test-buffers.js b/packages/pg/test/test-buffers.js index 60a549492..9fdd889d4 100644 --- a/packages/pg/test/test-buffers.js +++ b/packages/pg/test/test-buffers.js @@ -4,21 +4,15 @@ require(__dirname + '/test-helper') var buffers = {} buffers.readyForQuery = function () { - return new BufferList() - .add(Buffer.from('I')) - .join(true, 'Z') + return new BufferList().add(Buffer.from('I')).join(true, 'Z') } buffers.authenticationOk = function () { - return new BufferList() - .addInt32(0) - .join(true, 'R') + return new BufferList().addInt32(0).join(true, 'R') } buffers.authenticationCleartextPassword = function () { - return new BufferList() - .addInt32(3) - .join(true, 'R') + return new BufferList().addInt32(3).join(true, 'R') } buffers.authenticationMD5Password = function () { @@ -29,45 +23,27 @@ buffers.authenticationMD5Password = function () { } buffers.authenticationSASL = function () { - return new BufferList() - .addInt32(10) - .addCString('SCRAM-SHA-256') - .addCString('') - .join(true, 'R') + return new BufferList().addInt32(10).addCString('SCRAM-SHA-256').addCString('').join(true, 'R') } buffers.authenticationSASLContinue = function () { - return new BufferList() - .addInt32(11) - .addString('data') - .join(true, 'R') + return new BufferList().addInt32(11).addString('data').join(true, 'R') } buffers.authenticationSASLFinal = function () { - return new BufferList() - .addInt32(12) - .addString('data') - .join(true, 'R') + return new BufferList().addInt32(12).addString('data').join(true, 'R') } buffers.parameterStatus = function (name, value) { - return new BufferList() - .addCString(name) - .addCString(value) - .join(true, 'S') + return new BufferList().addCString(name).addCString(value).join(true, 'S') } buffers.backendKeyData = function (processID, secretKey) { - return new BufferList() - .addInt32(processID) - .addInt32(secretKey) - .join(true, 'K') + return new BufferList().addInt32(processID).addInt32(secretKey).join(true, 'K') } buffers.commandComplete = function (string) { - return new BufferList() - .addCString(string) - .join(true, 'C') + return new BufferList().addCString(string).join(true, 'C') } buffers.rowDescription = function (fields) { @@ -75,7 +51,8 @@ buffers.rowDescription = function (fields) { var buf = new BufferList() buf.addInt16(fields.length) fields.forEach(function (field) { - buf.addCString(field.name) + buf + .addCString(field.name) .addInt32(field.tableID || 0) .addInt16(field.attributeNumber || 0) .addInt32(field.dataTypeID || 0) @@ -117,7 +94,7 @@ var errorOrNotice = function (fields) { buf.addChar(field.type) buf.addCString(field.value) }) - return buf.add(Buffer.from([0]))// terminator + return buf.add(Buffer.from([0])) // terminator } buffers.parseComplete = function () { @@ -129,11 +106,7 @@ buffers.bindComplete = function () { } buffers.notification = function (id, channel, payload) { - return new BufferList() - .addInt32(id) - .addCString(channel) - .addCString(payload) - .join(true, 'A') + return new BufferList().addInt32(id).addCString(channel).addCString(payload).join(true, 'A') } buffers.emptyQuery = function () { diff --git a/packages/pg/test/test-helper.js b/packages/pg/test/test-helper.js index 4c14b8578..8159e387c 100644 --- a/packages/pg/test/test-helper.js +++ b/packages/pg/test/test-helper.js @@ -39,8 +39,10 @@ assert.emits = function (item, eventName, callback, message) { item.once(eventName, function () { if (eventName === 'error') { // belt and braces test to ensure all error events return an error - assert.ok(arguments[0] instanceof Error, - 'Expected error events to throw instances of Error but found: ' + sys.inspect(arguments[0])) + assert.ok( + arguments[0] instanceof Error, + 'Expected error events to throw instances of Error but found: ' + sys.inspect(arguments[0]) + ) } called = true clearTimeout(id) @@ -131,12 +133,15 @@ var expect = function (callback, timeout) { var executed = false timeout = timeout || parseInt(process.env.TEST_TIMEOUT) || 5000 var id = setTimeout(function () { - assert.ok(executed, - 'Expected execution of function to be fired within ' + timeout + - ' milliseconds ' + - ' (hint: export TEST_TIMEOUT=' + - ' to change timeout globally)' + - callback.toString()) + assert.ok( + executed, + 'Expected execution of function to be fired within ' + + timeout + + ' milliseconds ' + + ' (hint: export TEST_TIMEOUT=' + + ' to change timeout globally)' + + callback.toString() + ) }, timeout) if (callback.length < 3) { @@ -173,7 +178,7 @@ const getMode = () => { } global.test = function (name, action) { - test.testCount ++ + test.testCount++ test[name] = action var result = test[name]() if (result === false) { @@ -223,14 +228,16 @@ var Sink = function (expected, timeout, callback) { assert.equal(internalCount, expected) callback() } - } + }, } } var getTimezoneOffset = Date.prototype.getTimezoneOffset var setTimezoneOffset = function (minutesOffset) { - Date.prototype.getTimezoneOffset = function () { return minutesOffset } + Date.prototype.getTimezoneOffset = function () { + return minutesOffset + } } var resetTimezoneOffset = function () { @@ -246,5 +253,5 @@ module.exports = { sys: sys, Client: Client, setTimezoneOffset: setTimezoneOffset, - resetTimezoneOffset: resetTimezoneOffset + resetTimezoneOffset: resetTimezoneOffset, } diff --git a/packages/pg/test/unit/client/configuration-tests.js b/packages/pg/test/unit/client/configuration-tests.js index 9c1fadc80..e6cbc0dcc 100644 --- a/packages/pg/test/unit/client/configuration-tests.js +++ b/packages/pg/test/unit/client/configuration-tests.js @@ -23,7 +23,7 @@ test('client settings', function () { database: database, port: 321, password: password, - ssl: true + ssl: true, }) assert.equal(client.user, user) @@ -48,7 +48,7 @@ test('client settings', function () { process.env.PGSSLMODE = 'prefer' var client = new Client({ - ssl: false + ssl: false, }) process.env.PGSSLMODE = old @@ -59,7 +59,7 @@ test('client settings', function () { test('initializing from a config string', function () { test('uses connectionString property', function () { var client = new Client({ - connectionString: 'postgres://brian:pass@host1:333/databasename' + connectionString: 'postgres://brian:pass@host1:333/databasename', }) assert.equal(client.user, 'brian') assert.equal(client.password, 'pass') diff --git a/packages/pg/test/unit/client/early-disconnect-tests.js b/packages/pg/test/unit/client/early-disconnect-tests.js index 35a587d99..494482845 100644 --- a/packages/pg/test/unit/client/early-disconnect-tests.js +++ b/packages/pg/test/unit/client/early-disconnect-tests.js @@ -11,7 +11,9 @@ var server = net.createServer(function (c) { server.listen(7777, function () { var client = new pg.Client('postgres://localhost:7777') - client.connect(assert.calls(function (err) { - assert(err) - })) + client.connect( + assert.calls(function (err) { + assert(err) + }) + ) }) diff --git a/packages/pg/test/unit/client/escape-tests.js b/packages/pg/test/unit/client/escape-tests.js index 8229a3a37..7f96a832d 100644 --- a/packages/pg/test/unit/client/escape-tests.js +++ b/packages/pg/test/unit/client/escape-tests.js @@ -1,7 +1,7 @@ 'use strict' var helper = require(__dirname + '/test-helper') -function createClient (callback) { +function createClient(callback) { var client = new Client(helper.config) client.connect(function (err) { return callback(client) @@ -24,50 +24,42 @@ var testIdent = function (testName, input, expected) { }) } -testLit('escapeLiteral: no special characters', - 'hello world', "'hello world'") +testLit('escapeLiteral: no special characters', 'hello world', "'hello world'") -testLit('escapeLiteral: contains double quotes only', - 'hello " world', "'hello \" world'") +testLit('escapeLiteral: contains double quotes only', 'hello " world', "'hello \" world'") -testLit('escapeLiteral: contains single quotes only', - 'hello \' world', "'hello \'\' world'") +testLit('escapeLiteral: contains single quotes only', "hello ' world", "'hello '' world'") -testLit('escapeLiteral: contains backslashes only', - 'hello \\ world', " E'hello \\\\ world'") +testLit('escapeLiteral: contains backslashes only', 'hello \\ world', " E'hello \\\\ world'") -testLit('escapeLiteral: contains single quotes and double quotes', - 'hello \' " world', "'hello '' \" world'") +testLit('escapeLiteral: contains single quotes and double quotes', 'hello \' " world', "'hello '' \" world'") -testLit('escapeLiteral: contains double quotes and backslashes', - 'hello \\ " world', " E'hello \\\\ \" world'") +testLit('escapeLiteral: contains double quotes and backslashes', 'hello \\ " world', " E'hello \\\\ \" world'") -testLit('escapeLiteral: contains single quotes and backslashes', - 'hello \\ \' world', " E'hello \\\\ '' world'") +testLit('escapeLiteral: contains single quotes and backslashes', "hello \\ ' world", " E'hello \\\\ '' world'") -testLit('escapeLiteral: contains single quotes, double quotes, and backslashes', - 'hello \\ \' " world', " E'hello \\\\ '' \" world'") +testLit( + 'escapeLiteral: contains single quotes, double quotes, and backslashes', + 'hello \\ \' " world', + " E'hello \\\\ '' \" world'" +) -testIdent('escapeIdentifier: no special characters', - 'hello world', '"hello world"') +testIdent('escapeIdentifier: no special characters', 'hello world', '"hello world"') -testIdent('escapeIdentifier: contains double quotes only', - 'hello " world', '"hello "" world"') +testIdent('escapeIdentifier: contains double quotes only', 'hello " world', '"hello "" world"') -testIdent('escapeIdentifier: contains single quotes only', - 'hello \' world', '"hello \' world"') +testIdent('escapeIdentifier: contains single quotes only', "hello ' world", '"hello \' world"') -testIdent('escapeIdentifier: contains backslashes only', - 'hello \\ world', '"hello \\ world"') +testIdent('escapeIdentifier: contains backslashes only', 'hello \\ world', '"hello \\ world"') -testIdent('escapeIdentifier: contains single quotes and double quotes', - 'hello \' " world', '"hello \' "" world"') +testIdent('escapeIdentifier: contains single quotes and double quotes', 'hello \' " world', '"hello \' "" world"') -testIdent('escapeIdentifier: contains double quotes and backslashes', - 'hello \\ " world', '"hello \\ "" world"') +testIdent('escapeIdentifier: contains double quotes and backslashes', 'hello \\ " world', '"hello \\ "" world"') -testIdent('escapeIdentifier: contains single quotes and backslashes', - 'hello \\ \' world', '"hello \\ \' world"') +testIdent('escapeIdentifier: contains single quotes and backslashes', "hello \\ ' world", '"hello \\ \' world"') -testIdent('escapeIdentifier: contains single quotes, double quotes, and backslashes', - 'hello \\ \' " world', '"hello \\ \' "" world"') +testIdent( + 'escapeIdentifier: contains single quotes, double quotes, and backslashes', + 'hello \\ \' " world', + '"hello \\ \' "" world"' +) diff --git a/packages/pg/test/unit/client/md5-password-tests.js b/packages/pg/test/unit/client/md5-password-tests.js index 85b357ae7..a55e955bc 100644 --- a/packages/pg/test/unit/client/md5-password-tests.js +++ b/packages/pg/test/unit/client/md5-password-tests.js @@ -6,15 +6,14 @@ test('md5 authentication', function () { var client = helper.createClient() client.password = '!' var salt = Buffer.from([1, 2, 3, 4]) - client.connection.emit('authenticationMD5Password', {salt: salt}) + client.connection.emit('authenticationMD5Password', { salt: salt }) test('responds', function () { assert.lengthIs(client.connection.stream.packets, 1) test('should have correct encrypted data', function () { var password = utils.postgresMd5PasswordHash(client.user, client.password, salt) // how do we want to test this? - assert.equalBuffers(client.connection.stream.packets[0], new BufferList() - .addCString(password).join(true, 'p')) + assert.equalBuffers(client.connection.stream.packets[0], new BufferList().addCString(password).join(true, 'p')) }) }) }) diff --git a/packages/pg/test/unit/client/prepared-statement-tests.js b/packages/pg/test/unit/client/prepared-statement-tests.js index 08db8860b..2499808f7 100644 --- a/packages/pg/test/unit/client/prepared-statement-tests.js +++ b/packages/pg/test/unit/client/prepared-statement-tests.js @@ -38,8 +38,7 @@ con.describe = function (arg) { } var syncCalled = false -con.flush = function () { -} +con.flush = function () {} con.sync = function () { syncCalled = true process.nextTick(function () { @@ -51,10 +50,12 @@ test('bound command', function () { test('simple, unnamed bound command', function () { assert.ok(client.connection.emit('readyForQuery')) - var query = client.query(new Query({ - text: 'select * from X where name = $1', - values: ['hi'] - })) + var query = client.query( + new Query({ + text: 'select * from X where name = $1', + values: ['hi'], + }) + ) assert.emits(query, 'end', function () { test('parse argument', function () { @@ -122,8 +123,7 @@ portalCon.describe = function (arg) { }) } -portalCon.flush = function () { -} +portalCon.flush = function () {} portalCon.sync = function () { process.nextTick(function () { portalCon.emit('readyForQuery') @@ -133,11 +133,13 @@ portalCon.sync = function () { test('prepared statement with explicit portal', function () { assert.ok(portalClient.connection.emit('readyForQuery')) - var query = portalClient.query(new Query({ - text: 'select * from X where name = $1', - portal: 'myportal', - values: ['hi'] - })) + var query = portalClient.query( + new Query({ + text: 'select * from X where name = $1', + portal: 'myportal', + values: ['hi'], + }) + ) assert.emits(query, 'end', function () { test('bind argument', function () { diff --git a/packages/pg/test/unit/client/query-queue-tests.js b/packages/pg/test/unit/client/query-queue-tests.js index 62069c011..9364ce822 100644 --- a/packages/pg/test/unit/client/query-queue-tests.js +++ b/packages/pg/test/unit/client/query-queue-tests.js @@ -3,13 +3,12 @@ var helper = require(__dirname + '/test-helper') var Connection = require(__dirname + '/../../../lib/connection') test('drain', function () { - var con = new Connection({stream: 'NO'}) - var client = new Client({connection: con}) + var con = new Connection({ stream: 'NO' }) + var client = new Client({ connection: con }) con.connect = function () { con.emit('connect') } - con.query = function () { - } + con.query = function () {} client.connect() var raisedDrain = false diff --git a/packages/pg/test/unit/client/result-metadata-tests.js b/packages/pg/test/unit/client/result-metadata-tests.js index 276892e92..f3e005949 100644 --- a/packages/pg/test/unit/client/result-metadata-tests.js +++ b/packages/pg/test/unit/client/result-metadata-tests.js @@ -6,14 +6,17 @@ var testForTag = function (tagText, callback) { var client = helper.client() client.connection.emit('readyForQuery') - var query = client.query('whatever', assert.calls((err, result) => { - assert.ok(result != null, 'should pass something to this event') - callback(result) - })) + var query = client.query( + 'whatever', + assert.calls((err, result) => { + assert.ok(result != null, 'should pass something to this event') + callback(result) + }) + ) assert.lengthIs(client.connection.queries, 1) client.connection.emit('commandComplete', { - text: tagText + text: tagText, }) client.connection.emit('readyForQuery') diff --git a/packages/pg/test/unit/client/sasl-scram-tests.js b/packages/pg/test/unit/client/sasl-scram-tests.js index 9987c6cfa..f60c8c4c9 100644 --- a/packages/pg/test/unit/client/sasl-scram-tests.js +++ b/packages/pg/test/unit/client/sasl-scram-tests.js @@ -1,18 +1,19 @@ 'use strict' -require('./test-helper'); +require('./test-helper') var sasl = require('../../../lib/sasl') test('sasl/scram', function () { - test('startSession', function () { - test('fails when mechanisms does not include SCRAM-SHA-256', function () { - assert.throws(function () { - sasl.startSession([]) - }, { - message: 'SASL: Only mechanism SCRAM-SHA-256 is currently supported', - }) + assert.throws( + function () { + sasl.startSession([]) + }, + { + message: 'SASL: Only mechanism SCRAM-SHA-256 is currently supported', + } + ) }) test('returns expected session data', function () { @@ -31,65 +32,90 @@ test('sasl/scram', function () { assert(session1.clientNonce != session2.clientNonce) }) - }) test('continueSession', function () { - test('fails when last session message was not SASLInitialResponse', function () { - assert.throws(function () { - sasl.continueSession({}) - }, { - message: 'SASL: Last message was not SASLInitialResponse', - }) + assert.throws( + function () { + sasl.continueSession({}) + }, + { + message: 'SASL: Last message was not SASLInitialResponse', + } + ) }) test('fails when nonce is missing in server message', function () { - assert.throws(function () { - sasl.continueSession({ - message: 'SASLInitialResponse', - }, "s=1,i=1") - }, { - message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing', - }) + assert.throws( + function () { + sasl.continueSession( + { + message: 'SASLInitialResponse', + }, + 's=1,i=1' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing', + } + ) }) test('fails when salt is missing in server message', function () { - assert.throws(function () { - sasl.continueSession({ - message: 'SASLInitialResponse', - }, "r=1,i=1") - }, { - message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: salt missing', - }) + assert.throws( + function () { + sasl.continueSession( + { + message: 'SASLInitialResponse', + }, + 'r=1,i=1' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: salt missing', + } + ) }) test('fails when iteration is missing in server message', function () { - assert.throws(function () { - sasl.continueSession({ - message: 'SASLInitialResponse', - }, "r=1,s=1") - }, { - message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing', - }) + assert.throws( + function () { + sasl.continueSession( + { + message: 'SASLInitialResponse', + }, + 'r=1,s=1' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing', + } + ) }) test('fails when server nonce does not start with client nonce', function () { - assert.throws(function () { - sasl.continueSession({ - message: 'SASLInitialResponse', - clientNonce: '2', - }, 'r=1,s=1,i=1') - }, { - message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce does not start with client nonce', - }) + assert.throws( + function () { + sasl.continueSession( + { + message: 'SASLInitialResponse', + clientNonce: '2', + }, + 'r=1,s=1,i=1' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce does not start with client nonce', + } + ) }) test('sets expected session data', function () { const session = { message: 'SASLInitialResponse', clientNonce: 'a', - }; + } sasl.continueSession(session, 'password', 'r=ab,s=x,i=1') @@ -98,38 +124,45 @@ test('sasl/scram', function () { assert.equal(session.response, 'c=biws,r=ab,p=KAEPBUTjjofB0IM5UWcZApK1dSzFE0o5vnbWjBbvFHA=') }) - }) test('continueSession', function () { - test('fails when last session message was not SASLResponse', function () { - assert.throws(function () { - sasl.finalizeSession({}) - }, { - message: 'SASL: Last message was not SASLResponse', - }) + assert.throws( + function () { + sasl.finalizeSession({}) + }, + { + message: 'SASL: Last message was not SASLResponse', + } + ) }) test('fails when server signature does not match', function () { - assert.throws(function () { - sasl.finalizeSession({ - message: 'SASLResponse', - serverSignature: '3', - }, "v=4") - }, { - message: 'SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature does not match', - }) + assert.throws( + function () { + sasl.finalizeSession( + { + message: 'SASLResponse', + serverSignature: '3', + }, + 'v=4' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature does not match', + } + ) }) test('does not fail when eveything is ok', function () { - sasl.finalizeSession({ - message: 'SASLResponse', - serverSignature: '5', - }, "v=5") + sasl.finalizeSession( + { + message: 'SASLResponse', + serverSignature: '5', + }, + 'v=5' + ) }) - }) - }) - diff --git a/packages/pg/test/unit/client/set-keepalives-tests.js b/packages/pg/test/unit/client/set-keepalives-tests.js index 55ff04f39..3fef0c055 100644 --- a/packages/pg/test/unit/client/set-keepalives-tests.js +++ b/packages/pg/test/unit/client/set-keepalives-tests.js @@ -5,8 +5,8 @@ const helper = require('./test-helper') const suite = new helper.Suite() -suite.test('setting keep alive', done => { - const server = net.createServer(c => { +suite.test('setting keep alive', (done) => { + const server = net.createServer((c) => { c.destroy() server.close() }) @@ -24,7 +24,7 @@ suite.test('setting keep alive', done => { port: 7777, keepAlive: true, keepAliveInitialDelayMillis: 10000, - stream + stream, }) client.connect().catch(() => {}) diff --git a/packages/pg/test/unit/client/simple-query-tests.js b/packages/pg/test/unit/client/simple-query-tests.js index 3d1deef41..b0d5b8674 100644 --- a/packages/pg/test/unit/client/simple-query-tests.js +++ b/packages/pg/test/unit/client/simple-query-tests.js @@ -77,9 +77,11 @@ test('executing query', function () { test('handles rowDescription message', function () { var handled = con.emit('rowDescription', { - fields: [{ - name: 'boom' - }] + fields: [ + { + name: 'boom', + }, + ], }) assert.ok(handled, 'should have handlded rowDescription') }) @@ -104,7 +106,7 @@ test('executing query', function () { // when multiple queries are in a simple command test('handles command complete messages', function () { con.emit('commandComplete', { - text: 'INSERT 31 1' + text: 'INSERT 31 1', }) }) @@ -113,9 +115,9 @@ test('executing query', function () { assert.emits(query, 'end', function (msg) { // TODO do we want to check the complete messages? }) - con.emit('readyForQuery'); + con.emit('readyForQuery') // this would never actually happen - ['dataRow', 'rowDescription', 'commandComplete'].forEach(function (msg) { + ;['dataRow', 'rowDescription', 'commandComplete'].forEach(function (msg) { assert.equal(con.emit(msg), false, "Should no longer be picking up '" + msg + "' messages") }) }) @@ -128,7 +130,11 @@ test('executing query', function () { try { client.query(null, undefined) } catch (error) { - assert.equal(error.message, 'Client was passed a null or undefined query', 'Should have thrown an Error for null queries') + assert.equal( + error.message, + 'Client was passed a null or undefined query', + 'Should have thrown an Error for null queries' + ) } }) @@ -136,7 +142,11 @@ test('executing query', function () { try { client.query() } catch (error) { - assert.equal(error.message, 'Client was passed a null or undefined query', 'Should have thrown an Error for null queries') + assert.equal( + error.message, + 'Client was passed a null or undefined query', + 'Should have thrown an Error for null queries' + ) } }) }) diff --git a/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js index af0e09a64..9b0a3560b 100644 --- a/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js +++ b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js @@ -9,12 +9,17 @@ test('emits end when not in query', function () { // NOOP } - var client = new Client({connection: new Connection({stream: stream})}) - client.connect(assert.calls(function () { - client.query('SELECT NOW()', assert.calls(function (err, result) { - assert(err) - })) - })) + var client = new Client({ connection: new Connection({ stream: stream }) }) + client.connect( + assert.calls(function () { + client.query( + 'SELECT NOW()', + assert.calls(function (err, result) { + assert(err) + }) + ) + }) + ) assert.emits(client, 'error') assert.emits(client, 'end') client.connection.emit('connect') diff --git a/packages/pg/test/unit/client/test-helper.js b/packages/pg/test/unit/client/test-helper.js index 24f94df3b..8d1859033 100644 --- a/packages/pg/test/unit/client/test-helper.js +++ b/packages/pg/test/unit/client/test-helper.js @@ -3,19 +3,22 @@ var helper = require('../test-helper') var Connection = require('../../../lib/connection') var makeClient = function () { - var connection = new Connection({stream: 'no'}) + var connection = new Connection({ stream: 'no' }) connection.startup = function () {} connection.connect = function () {} connection.query = function (text) { this.queries.push(text) } connection.queries = [] - var client = new Client({connection: connection}) + var client = new Client({ connection: connection }) client.connect() client.connection.emit('connect') return client } -module.exports = Object.assign({ - client: makeClient -}, helper) +module.exports = Object.assign( + { + client: makeClient, + }, + helper +) diff --git a/packages/pg/test/unit/client/throw-in-type-parser-tests.js b/packages/pg/test/unit/client/throw-in-type-parser-tests.js index 24883241c..8f71fdc02 100644 --- a/packages/pg/test/unit/client/throw-in-type-parser-tests.js +++ b/packages/pg/test/unit/client/throw-in-type-parser-tests.js @@ -11,7 +11,7 @@ types.setTypeParser('special oid that will throw', function () { throw typeParserError }) -const emitFakeEvents = con => { +const emitFakeEvents = (con) => { setImmediate(() => { con.emit('readyForQuery') @@ -19,9 +19,9 @@ const emitFakeEvents = con => { fields: [ { name: 'boom', - dataTypeID: 'special oid that will throw' - } - ] + dataTypeID: 'special oid that will throw', + }, + ], }) con.emit('dataRow', { fields: ['hi'] }) @@ -62,7 +62,7 @@ suite.test('rejects promise with error', function (done) { var client = helper.client() var con = client.connection emitFakeEvents(con) - client.query('whatever').catch(err => { + client.query('whatever').catch((err) => { assert.equal(err, typeParserError) done() }) diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index fdb4e6627..820b320a5 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -11,15 +11,12 @@ for (var key in process.env) { test('ConnectionParameters construction', function () { assert.ok(new ConnectionParameters(), 'with null config') - assert.ok(new ConnectionParameters({user: 'asdf'}), 'with config object') + assert.ok(new ConnectionParameters({ user: 'asdf' }), 'with config object') assert.ok(new ConnectionParameters('postgres://localhost/postgres'), 'with connection string') }) var compare = function (actual, expected, type) { - const expectedDatabase = - expected.database === undefined - ? expected.user - : expected.database + const expectedDatabase = expected.database === undefined ? expected.user : expected.database assert.equal(actual.user, expected.user, type + ' user') assert.equal(actual.database, expectedDatabase, type + ' database') @@ -28,7 +25,11 @@ var compare = function (actual, expected, type) { assert.equal(actual.password, expected.password, type + ' password') assert.equal(actual.binary, expected.binary, type + ' binary') assert.equal(actual.statement_timeout, expected.statement_timeout, type + ' statement_timeout') - assert.equal(actual.idle_in_transaction_session_timeout, expected.idle_in_transaction_session_timeout, type + ' idle_in_transaction_session_timeout') + assert.equal( + actual.idle_in_transaction_session_timeout, + expected.idle_in_transaction_session_timeout, + type + ' idle_in_transaction_session_timeout' + ) } test('ConnectionParameters initializing from defaults', function () { @@ -68,37 +69,37 @@ test('ConnectionParameters initializing from config', function () { encoding: 'utf8', host: 'yo', ssl: { - asdf: 'blah' + asdf: 'blah', }, statement_timeout: 15000, - idle_in_transaction_session_timeout: 15000 + idle_in_transaction_session_timeout: 15000, } var subject = new ConnectionParameters(config) compare(subject, config, 'config') assert.ok(subject.isDomainSocket === false) }) -test('ConnectionParameters initializing from config and config.connectionString', function() { +test('ConnectionParameters initializing from config and config.connectionString', function () { var subject1 = new ConnectionParameters({ - connectionString: 'postgres://test@host/db' + connectionString: 'postgres://test@host/db', }) var subject2 = new ConnectionParameters({ - connectionString: 'postgres://test@host/db?ssl=1' + connectionString: 'postgres://test@host/db?ssl=1', }) var subject3 = new ConnectionParameters({ connectionString: 'postgres://test@host/db', - ssl: true + ssl: true, }) var subject4 = new ConnectionParameters({ connectionString: 'postgres://test@host/db?ssl=1', - ssl: false + ssl: false, }) assert.equal(subject1.ssl, false) assert.equal(subject2.ssl, true) assert.equal(subject3.ssl, true) assert.equal(subject4.ssl, true) -}); +}) test('escape spaces if present', function () { var subject = new ConnectionParameters('postgres://localhost/post gres') @@ -151,18 +152,20 @@ test('libpq connection string building', function () { password: 'xyz', port: 888, host: 'localhost', - database: 'bam' + database: 'bam', } var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString(assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "user='brian'") - checkForPart(parts, "password='xyz'") - checkForPart(parts, "port='888'") - checkForPart(parts, "hostaddr='127.0.0.1'") - checkForPart(parts, "dbname='bam'") - })) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, "password='xyz'") + checkForPart(parts, "port='888'") + checkForPart(parts, "hostaddr='127.0.0.1'") + checkForPart(parts, "dbname='bam'") + }) + ) }) test('builds dns string', function () { @@ -170,15 +173,17 @@ test('libpq connection string building', function () { user: 'brian', password: 'asdf', port: 5432, - host: 'localhost' + host: 'localhost', } var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString(assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "user='brian'") - checkForPart(parts, "hostaddr='127.0.0.1'") - })) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, "hostaddr='127.0.0.1'") + }) + ) }) test('error when dns fails', function () { @@ -186,13 +191,15 @@ test('libpq connection string building', function () { user: 'brian', password: 'asf', port: 5432, - host: 'asdlfkjasldfkksfd#!$!!!!..com' + host: 'asdlfkjasldfkksfd#!$!!!!..com', } var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString(assert.calls(function (err, constring) { - assert.ok(err) - assert.isNull(constring) - })) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert.ok(err) + assert.isNull(constring) + }) + ) }) test('connecting to unix domain socket', function () { @@ -200,43 +207,49 @@ test('libpq connection string building', function () { user: 'brian', password: 'asf', port: 5432, - host: '/tmp/' + host: '/tmp/', } var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString(assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "user='brian'") - checkForPart(parts, "host='/tmp/'") - })) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, "host='/tmp/'") + }) + ) }) test('config contains quotes and backslashes', function () { var config = { user: 'not\\brian', - password: 'bad\'chars', + password: "bad'chars", port: 5432, - host: '/tmp/' + host: '/tmp/', } var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString(assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "user='not\\\\brian'") - checkForPart(parts, "password='bad\\'chars'") - })) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='not\\\\brian'") + checkForPart(parts, "password='bad\\'chars'") + }) + ) }) test('encoding can be specified by config', function () { var config = { - client_encoding: 'utf-8' + client_encoding: 'utf-8', } var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString(assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "client_encoding='utf-8'") - })) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "client_encoding='utf-8'") + }) + ) }) test('password contains < and/or > characters', function () { @@ -246,9 +259,19 @@ test('libpq connection string building', function () { password: 'helloe', port: 5432, host: 'localhost', - database: 'postgres' + database: 'postgres', } - var connectionString = 'postgres://' + sourceConfig.user + ':' + sourceConfig.password + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database + var connectionString = + 'postgres://' + + sourceConfig.user + + ':' + + sourceConfig.password + + '@' + + sourceConfig.host + + ':' + + sourceConfig.port + + '/' + + sourceConfig.database var subject = new ConnectionParameters(connectionString) assert.equal(subject.password, sourceConfig.password) }) @@ -293,19 +316,22 @@ test('libpq connection string building', function () { sslca: '/path/ca.pem', sslkey: '/path/cert.key', sslcert: '/path/cert.crt', - sslrootcert: '/path/root.crt' - } + sslrootcert: '/path/root.crt', + }, } var Client = require('../../../lib/client') var defaults = require('../../../lib/defaults') defaults.ssl = true var c = new ConnectionParameters(sourceConfig) - c.getLibpqConnectionString(assert.calls(function (err, pgCString) { - assert(!err) - assert.equal( - pgCString.indexOf('sslrootcert=\'/path/root.crt\'') !== -1, true, - 'libpqConnectionString should contain sslrootcert' - ) - })) + c.getLibpqConnectionString( + assert.calls(function (err, pgCString) { + assert(!err) + assert.equal( + pgCString.indexOf("sslrootcert='/path/root.crt'") !== -1, + true, + 'libpqConnectionString should contain sslrootcert' + ) + }) + ) }) }) diff --git a/packages/pg/test/unit/connection-parameters/environment-variable-tests.js b/packages/pg/test/unit/connection-parameters/environment-variable-tests.js index 2c5e503d6..45d481e30 100644 --- a/packages/pg/test/unit/connection-parameters/environment-variable-tests.js +++ b/packages/pg/test/unit/connection-parameters/environment-variable-tests.js @@ -31,7 +31,7 @@ test('ConnectionParameters initialized from mix', function (t) { delete process.env['PGDATABASE'] var subject = new ConnectionParameters({ user: 'testing', - database: 'zugzug' + database: 'zugzug', }) assert.equal(subject.host, 'local', 'env host') assert.equal(subject.user, 'testing', 'config user') diff --git a/packages/pg/test/unit/connection/error-tests.js b/packages/pg/test/unit/connection/error-tests.js index f72e9ff04..5075c770d 100644 --- a/packages/pg/test/unit/connection/error-tests.js +++ b/packages/pg/test/unit/connection/error-tests.js @@ -6,7 +6,7 @@ var net = require('net') const suite = new helper.Suite() suite.test('connection emits stream errors', function (done) { - var con = new Connection({stream: new MemoryStream()}) + var con = new Connection({ stream: new MemoryStream() }) assert.emits(con, 'error', function (err) { assert.equal(err.message, 'OMG!') done() @@ -16,7 +16,7 @@ suite.test('connection emits stream errors', function (done) { }) suite.test('connection emits ECONNRESET errors during normal operation', function (done) { - var con = new Connection({stream: new MemoryStream()}) + var con = new Connection({ stream: new MemoryStream() }) con.connect() assert.emits(con, 'error', function (err) { assert.equal(err.code, 'ECONNRESET') @@ -28,7 +28,7 @@ suite.test('connection emits ECONNRESET errors during normal operation', functio }) suite.test('connection does not emit ECONNRESET errors during disconnect', function (done) { - var con = new Connection({stream: new MemoryStream()}) + var con = new Connection({ stream: new MemoryStream() }) con.connect() var e = new Error('Connection Reset') e.code = 'ECONNRESET' @@ -42,20 +42,20 @@ var SSLNegotiationPacketTests = [ testName: 'connection does not emit ECONNRESET errors during disconnect also when using SSL', errorMessage: null, response: 'S', - responseType: 'sslconnect' + responseType: 'sslconnect', }, { testName: 'connection emits an error when SSL is not supported', errorMessage: 'The server does not support SSL connections', response: 'N', - responseType: 'error' + responseType: 'error', }, { testName: 'connection emits an error when postmaster responds to SSL negotiation packet', errorMessage: 'There was an error establishing an SSL connection', response: 'E', - responseType: 'error' - } + responseType: 'error', + }, ] for (var i = 0; i < SSLNegotiationPacketTests.length; i++) { @@ -71,7 +71,7 @@ for (var i = 0; i < SSLNegotiationPacketTests.length; i++) { }) server.listen(7778, function () { - var con = new Connection({ssl: true}) + var con = new Connection({ ssl: true }) con.connect(7778, 'localhost') assert.emits(con, tc.responseType, function (err) { if (tc.errorMessage !== null || err) { diff --git a/packages/pg/test/unit/connection/inbound-parser-tests.js b/packages/pg/test/unit/connection/inbound-parser-tests.js index 7bb9a4329..5f92cdc52 100644 --- a/packages/pg/test/unit/connection/inbound-parser-tests.js +++ b/packages/pg/test/unit/connection/inbound-parser-tests.js @@ -16,7 +16,8 @@ var bindCompleteBuffer = buffers.bindComplete() var portalSuspendedBuffer = buffers.portalSuspended() var addRow = function (bufferList, name, offset) { - return bufferList.addCString(name) // field name + return bufferList + .addCString(name) // field name .addInt32(offset++) // table id .addInt16(offset++) // attribute of column number .addInt32(offset++) // objectId of field's data type @@ -32,24 +33,25 @@ var row1 = { dataTypeID: 3, dataTypeSize: 4, typeModifier: 5, - formatCode: 0 + formatCode: 0, } var oneRowDescBuff = new buffers.rowDescription([row1]) row1.name = 'bang' -var twoRowBuf = new buffers.rowDescription([row1, { - name: 'whoah', - tableID: 10, - attributeNumber: 11, - dataTypeID: 12, - dataTypeSize: 13, - typeModifier: 14, - formatCode: 0 -}]) - -var emptyRowFieldBuf = new BufferList() - .addInt16(0) - .join(true, 'D') +var twoRowBuf = new buffers.rowDescription([ + row1, + { + name: 'whoah', + tableID: 10, + attributeNumber: 11, + dataTypeID: 12, + dataTypeSize: 13, + typeModifier: 14, + formatCode: 0, + }, +]) + +var emptyRowFieldBuf = new BufferList().addInt16(0).join(true, 'D') var emptyRowFieldBuf = buffers.dataRow() @@ -63,31 +65,31 @@ var oneFieldBuf = buffers.dataRow(['test']) var expectedAuthenticationOkayMessage = { name: 'authenticationOk', - length: 8 + length: 8, } var expectedParameterStatusMessage = { name: 'parameterStatus', parameterName: 'client_encoding', parameterValue: 'UTF8', - length: 25 + length: 25, } var expectedBackendKeyDataMessage = { name: 'backendKeyData', processID: 1, - secretKey: 2 + secretKey: 2, } var expectedReadyForQueryMessage = { name: 'readyForQuery', length: 5, - status: 'I' + status: 'I', } var expectedCommandCompleteMessage = { length: 13, - text: 'SELECT 3' + text: 'SELECT 3', } var emptyRowDescriptionBuffer = new BufferList() .addInt16(0) // number of fields @@ -96,18 +98,18 @@ var emptyRowDescriptionBuffer = new BufferList() var expectedEmptyRowDescriptionMessage = { name: 'rowDescription', length: 6, - fieldCount: 0 + fieldCount: 0, } var expectedOneRowMessage = { name: 'rowDescription', length: 27, - fieldCount: 1 + fieldCount: 1, } var expectedTwoRowMessage = { name: 'rowDescription', length: 53, - fieldCount: 2 + fieldCount: 2, } var testForMessage = function (buffer, expectedMessage) { @@ -115,7 +117,7 @@ var testForMessage = function (buffer, expectedMessage) { test('recieves and parses ' + expectedMessage.name, function () { var stream = new MemoryStream() var client = new Connection({ - stream: stream + stream: stream, }) client.connect() @@ -140,11 +142,11 @@ var SASLContinueBuffer = buffers.authenticationSASLContinue() var SASLFinalBuffer = buffers.authenticationSASLFinal() var expectedPlainPasswordMessage = { - name: 'authenticationCleartextPassword' + name: 'authenticationCleartextPassword', } var expectedMD5PasswordMessage = { - name: 'authenticationMD5Password' + name: 'authenticationMD5Password', } var expectedSASLMessage = { @@ -166,7 +168,7 @@ var expectedNotificationResponseMessage = { name: 'notification', processId: 4, channel: 'hi', - payload: 'boom' + payload: 'boom', } test('Connection', function () { @@ -198,7 +200,7 @@ test('Connection', function () { test('no data message', function () { testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), { - name: 'noData' + name: 'noData', }) }) @@ -215,7 +217,7 @@ test('Connection', function () { dataTypeID: 3, dataTypeSize: 4, dataTypeModifier: 5, - format: 'text' + format: 'text', }) }) }) @@ -233,7 +235,7 @@ test('Connection', function () { dataTypeID: 3, dataTypeSize: 4, dataTypeModifier: 5, - format: 'text' + format: 'text', }) }) test('has correct second field', function () { @@ -244,7 +246,7 @@ test('Connection', function () { dataTypeID: 12, dataTypeSize: 13, dataTypeModifier: 14, - format: 'text' + format: 'text', }) }) }) @@ -253,7 +255,7 @@ test('Connection', function () { test('parsing empty row', function () { var message = testForMessage(emptyRowFieldBuf, { name: 'dataRow', - fieldCount: 0 + fieldCount: 0, }) test('has 0 fields', function () { assert.equal(message.fields.length, 0) @@ -263,7 +265,7 @@ test('Connection', function () { test('parsing data row with fields', function () { var message = testForMessage(oneFieldBuf, { name: 'dataRow', - fieldCount: 1 + fieldCount: 1, }) test('has 1 field', function () { assert.equal(message.fields.length, 1) @@ -277,61 +279,75 @@ test('Connection', function () { test('notice message', function () { // this uses the same logic as error message - var buff = buffers.notice([{type: 'C', value: 'code'}]) + var buff = buffers.notice([{ type: 'C', value: 'code' }]) testForMessage(buff, { name: 'notice', - code: 'code' + code: 'code', }) }) test('error messages', function () { test('with no fields', function () { var msg = testForMessage(buffers.error(), { - name: 'error' + name: 'error', }) }) test('with all the fields', function () { - var buffer = buffers.error([{ - type: 'S', - value: 'ERROR' - }, { - type: 'C', - value: 'code' - }, { - type: 'M', - value: 'message' - }, { - type: 'D', - value: 'details' - }, { - type: 'H', - value: 'hint' - }, { - type: 'P', - value: '100' - }, { - type: 'p', - value: '101' - }, { - type: 'q', - value: 'query' - }, { - type: 'W', - value: 'where' - }, { - type: 'F', - value: 'file' - }, { - type: 'L', - value: 'line' - }, { - type: 'R', - value: 'routine' - }, { - type: 'Z', // ignored - value: 'alsdkf' - }]) + var buffer = buffers.error([ + { + type: 'S', + value: 'ERROR', + }, + { + type: 'C', + value: 'code', + }, + { + type: 'M', + value: 'message', + }, + { + type: 'D', + value: 'details', + }, + { + type: 'H', + value: 'hint', + }, + { + type: 'P', + value: '100', + }, + { + type: 'p', + value: '101', + }, + { + type: 'q', + value: 'query', + }, + { + type: 'W', + value: 'where', + }, + { + type: 'F', + value: 'file', + }, + { + type: 'L', + value: 'line', + }, + { + type: 'R', + value: 'routine', + }, + { + type: 'Z', // ignored + value: 'alsdkf', + }, + ]) testForMessage(buffer, { name: 'error', @@ -346,33 +362,33 @@ test('Connection', function () { where: 'where', file: 'file', line: 'line', - routine: 'routine' + routine: 'routine', }) }) }) test('parses parse complete command', function () { testForMessage(parseCompleteBuffer, { - name: 'parseComplete' + name: 'parseComplete', }) }) test('parses bind complete command', function () { testForMessage(bindCompleteBuffer, { - name: 'bindComplete' + name: 'bindComplete', }) }) test('parses portal suspended message', function () { testForMessage(portalSuspendedBuffer, { - name: 'portalSuspended' + name: 'portalSuspended', }) }) test('parses replication start message', function () { testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { name: 'replicationStart', - length: 4 + length: 4, }) }) }) @@ -385,7 +401,7 @@ test('split buffer, single message parsing', function () { var stream = new MemoryStream() stream.readyState = 'open' var client = new Connection({ - stream: stream + stream: stream, }) client.connect() var message = null @@ -443,7 +459,7 @@ test('split buffer, multiple message parsing', function () { var messages = [] var stream = new MemoryStream() var client = new Connection({ - stream: stream + stream: stream, }) client.connect() client.on('message', function (msg) { @@ -454,11 +470,11 @@ test('split buffer, multiple message parsing', function () { assert.lengthIs(messages, 2) assert.same(messages[0], { name: 'dataRow', - fieldCount: 1 + fieldCount: 1, }) assert.equal(messages[0].fields[0], '!') assert.same(messages[1], { - name: 'readyForQuery' + name: 'readyForQuery', }) messages = [] } diff --git a/packages/pg/test/unit/connection/outbound-sending-tests.js b/packages/pg/test/unit/connection/outbound-sending-tests.js index 6c36401f0..b40af0005 100644 --- a/packages/pg/test/unit/connection/outbound-sending-tests.js +++ b/packages/pg/test/unit/connection/outbound-sending-tests.js @@ -3,7 +3,7 @@ require(__dirname + '/test-helper') var Connection = require(__dirname + '/../../../lib/connection') var stream = new MemoryStream() var con = new Connection({ - stream: stream + stream: stream, }) assert.received = function (stream, buffer) { @@ -15,18 +15,22 @@ assert.received = function (stream, buffer) { test('sends startup message', function () { con.startup({ user: 'brian', - database: 'bang' + database: 'bang', }) - assert.received(stream, new BufferList() - .addInt16(3) - .addInt16(0) - .addCString('user') - .addCString('brian') - .addCString('database') - .addCString('bang') - .addCString('client_encoding') - .addCString("'utf-8'") - .addCString('').join(true)) + assert.received( + stream, + new BufferList() + .addInt16(3) + .addInt16(0) + .addCString('user') + .addCString('brian') + .addCString('database') + .addCString('bang') + .addCString('client_encoding') + .addCString("'utf-8'") + .addCString('') + .join(true) + ) }) test('sends password message', function () { @@ -51,11 +55,8 @@ test('sends query message', function () { }) test('sends parse message', function () { - con.parse({text: '!'}) - var expected = new BufferList() - .addCString('') - .addCString('!') - .addInt16(0).join(true, 'P') + con.parse({ text: '!' }) + var expected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P') assert.received(stream, expected) }) @@ -63,19 +64,16 @@ test('sends parse message with named query', function () { con.parse({ name: 'boom', text: 'select * from boom', - types: [] + types: [], }) - var expected = new BufferList() - .addCString('boom') - .addCString('select * from boom') - .addInt16(0).join(true, 'P') + var expected = new BufferList().addCString('boom').addCString('select * from boom').addInt16(0).join(true, 'P') assert.received(stream, expected) test('with multiple parameters', function () { con.parse({ name: 'force', text: 'select * from bang where name = $1', - types: [1, 2, 3, 4] + types: [1, 2, 3, 4], }) var expected = new BufferList() .addCString('force') @@ -84,7 +82,8 @@ test('sends parse message with named query', function () { .addInt32(1) .addInt32(2) .addInt32(3) - .addInt32(4).join(true, 'P') + .addInt32(4) + .join(true, 'P') assert.received(stream, expected) }) }) @@ -107,10 +106,10 @@ test('bind messages', function () { con.bind({ portal: 'bang', statement: 'woo', - values: ['1', 'hi', null, 'zing'] + values: ['1', 'hi', null, 'zing'], }) var expectedBuffer = new BufferList() - .addCString('bang') // portal name + .addCString('bang') // portal name .addCString('woo') // statement name .addInt16(0) .addInt16(4) @@ -131,16 +130,16 @@ test('with named statement, portal, and buffer value', function () { con.bind({ portal: 'bang', statement: 'woo', - values: ['1', 'hi', null, Buffer.from('zing', 'utf8')] + values: ['1', 'hi', null, Buffer.from('zing', 'utf8')], }) var expectedBuffer = new BufferList() - .addCString('bang') // portal name + .addCString('bang') // portal name .addCString('woo') // statement name - .addInt16(4)// value count - .addInt16(0)// string - .addInt16(0)// string - .addInt16(0)// string - .addInt16(1)// binary + .addInt16(4) // value count + .addInt16(0) // string + .addInt16(0) // string + .addInt16(0) // string + .addInt16(1) // binary .addInt16(4) .addInt32(1) .add(Buffer.from('1')) @@ -157,22 +156,16 @@ test('with named statement, portal, and buffer value', function () { test('sends execute message', function () { test('for unamed portal with no row limit', function () { con.execute() - var expectedBuffer = new BufferList() - .addCString('') - .addInt32(0) - .join(true, 'E') + var expectedBuffer = new BufferList().addCString('').addInt32(0).join(true, 'E') assert.received(stream, expectedBuffer) }) test('for named portal with row limit', function () { con.execute({ portal: 'my favorite portal', - rows: 100 + rows: 100, }) - var expectedBuffer = new BufferList() - .addCString('my favorite portal') - .addInt32(100) - .join(true, 'E') + var expectedBuffer = new BufferList().addCString('my favorite portal').addInt32(100).join(true, 'E') assert.received(stream, expectedBuffer) }) }) @@ -198,13 +191,13 @@ test('sends end command', function () { test('sends describe command', function () { test('describe statement', function () { - con.describe({type: 'S', name: 'bang'}) + con.describe({ type: 'S', name: 'bang' }) var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D') assert.received(stream, expected) }) test('describe unnamed portal', function () { - con.describe({type: 'P'}) + con.describe({ type: 'P' }) var expected = new BufferList().addChar('P').addCString('').join(true, 'D') assert.received(stream, expected) }) diff --git a/packages/pg/test/unit/connection/startup-tests.js b/packages/pg/test/unit/connection/startup-tests.js index dc793e697..09a710c7a 100644 --- a/packages/pg/test/unit/connection/startup-tests.js +++ b/packages/pg/test/unit/connection/startup-tests.js @@ -3,7 +3,7 @@ require(__dirname + '/test-helper') var Connection = require(__dirname + '/../../../lib/connection') test('connection can take existing stream', function () { var stream = new MemoryStream() - var con = new Connection({stream: stream}) + var con = new Connection({ stream: stream }) assert.equal(con.stream, stream) }) @@ -21,7 +21,7 @@ test('using closed stream', function () { var stream = makeStream() - var con = new Connection({stream: stream}) + var con = new Connection({ stream: stream }) con.connect(1234, 'bang') @@ -72,7 +72,7 @@ test('using opened stream', function () { stream.connect = function () { assert.ok(false, 'Should not call open') } - var con = new Connection({stream: stream}) + var con = new Connection({ stream: stream }) test('does not call open', function () { var hit = false con.once('connect', function () { diff --git a/packages/pg/test/unit/test-helper.js b/packages/pg/test/unit/test-helper.js index 04b73f372..5793251b5 100644 --- a/packages/pg/test/unit/test-helper.js +++ b/packages/pg/test/unit/test-helper.js @@ -15,29 +15,29 @@ var p = MemoryStream.prototype p.write = function (packet, cb) { this.packets.push(packet) - if(cb){ - cb(); + if (cb) { + cb() } } -p.end = function() { - p.closed = true; +p.end = function () { + p.closed = true } p.setKeepAlive = function () {} -p.closed = false; +p.closed = false p.writable = true const createClient = function () { var stream = new MemoryStream() stream.readyState = 'open' var client = new Client({ - connection: new Connection({stream: stream}) + connection: new Connection({ stream: stream }), }) client.connect() return client } module.exports = Object.assign({}, helper, { - createClient: createClient + createClient: createClient, }) diff --git a/packages/pg/test/unit/utils-tests.js b/packages/pg/test/unit/utils-tests.js index 4308f7a18..3d087ad0d 100644 --- a/packages/pg/test/unit/utils-tests.js +++ b/packages/pg/test/unit/utils-tests.js @@ -29,7 +29,7 @@ test('EventEmitter.once', function (t) { test('normalizing query configs', function () { var config - var callback = function () { } + var callback = function () {} config = utils.normalizeQueryConfig({ text: 'TEXT' }) assert.same(config, { text: 'TEXT' }) @@ -162,7 +162,7 @@ test('prepareValue: objects with simple toPostgres prepared properly', function var customType = { toPostgres: function () { return 'zomgcustom!' - } + }, } var out = utils.prepareValue(customType) assert.strictEqual(out, 'zomgcustom!') @@ -180,7 +180,7 @@ test('prepareValue: objects with complex toPostgres prepared properly', function var customType = { toPostgres: function () { return [1, 2] - } + }, } var out = utils.prepareValue(customType) assert.strictEqual(out, '{"1","2"}') @@ -188,11 +188,19 @@ test('prepareValue: objects with complex toPostgres prepared properly', function test('prepareValue: objects with toPostgres receive prepareValue', function () { var customRange = { - lower: { toPostgres: function () { return 5 } }, - upper: { toPostgres: function () { return 10 } }, + lower: { + toPostgres: function () { + return 5 + }, + }, + upper: { + toPostgres: function () { + return 10 + }, + }, toPostgres: function (prepare) { return '[' + prepare(this.lower) + ',' + prepare(this.upper) + ']' - } + }, } var out = utils.prepareValue(customRange) assert.strictEqual(out, '[5,10]') @@ -202,8 +210,12 @@ test('prepareValue: objects with circular toPostgres rejected', function () { var buf = Buffer.from('zomgcustom!') var customType = { toPostgres: function () { - return { toPostgres: function () { return customType } } - } + return { + toPostgres: function () { + return customType + }, + } + }, } // can't use `assert.throws` since we need to distinguish circular reference @@ -221,7 +233,7 @@ test('prepareValue: can safely be used to map an array of values including those var customType = { toPostgres: function () { return 'zomgcustom!' - } + }, } var values = [1, 'test', customType] var out = values.map(utils.prepareValue) From 6353affecaaa12a4d989ef2506d4460792b63d2b Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 10 Apr 2020 11:15:42 -0500 Subject: [PATCH 0621/1037] Downgrade to prettier@1.x to support node@8.x --- .prettierrc.json | 6 - package.json | 9 +- packages/pg-cursor/index.js | 36 ++--- packages/pg-cursor/test/close.js | 22 +-- packages/pg-cursor/test/error-handling.js | 26 ++-- packages/pg-cursor/test/index.js | 68 ++++----- packages/pg-cursor/test/no-data-handling.js | 14 +- packages/pg-cursor/test/pool.js | 20 +-- packages/pg-pool/index.js | 10 +- .../pg-pool/test/bring-your-own-promise.js | 6 +- packages/pg-pool/test/connection-strings.js | 12 +- packages/pg-pool/test/connection-timeout.js | 6 +- packages/pg-pool/test/ending.js | 4 +- packages/pg-pool/test/error-handling.js | 26 ++-- packages/pg-pool/test/events.js | 32 ++-- packages/pg-pool/test/idle-timeout.js | 6 +- packages/pg-pool/test/index.js | 92 ++++++------ packages/pg-pool/test/logging.js | 8 +- packages/pg-pool/test/max-uses.js | 12 +- packages/pg-pool/test/sizing.js | 6 +- .../pg-protocol/src/inbound-parser.test.ts | 50 +++--- .../src/outbound-serializer.test.ts | 110 +++++++++----- packages/pg-protocol/src/serializer.ts | 14 +- .../pg-protocol/src/testing/buffer-list.ts | 4 +- .../pg-protocol/src/testing/test-buffers.ts | 88 ++++++----- packages/pg-query-stream/test/close.js | 26 ++-- packages/pg-query-stream/test/concat.js | 10 +- packages/pg-query-stream/test/empty-query.js | 10 +- packages/pg-query-stream/test/error.js | 10 +- packages/pg-query-stream/test/fast-reader.js | 10 +- packages/pg-query-stream/test/helper.js | 8 +- packages/pg-query-stream/test/instant.js | 6 +- packages/pg-query-stream/test/issue-3.js | 12 +- .../pg-query-stream/test/passing-options.js | 6 +- packages/pg-query-stream/test/pauses.js | 6 +- packages/pg-query-stream/test/slow-reader.js | 10 +- .../test/stream-tester-timestamp.js | 13 +- .../pg-query-stream/test/stream-tester.js | 9 +- packages/pg/lib/client.js | 74 ++++----- packages/pg/lib/connection-fast.js | 54 +++---- packages/pg/lib/connection-parameters.js | 14 +- packages/pg/lib/connection.js | 142 ++++++++++-------- packages/pg/lib/defaults.js | 2 +- packages/pg/lib/index.js | 2 +- packages/pg/lib/native/client.js | 38 ++--- packages/pg/lib/native/query.js | 24 +-- packages/pg/lib/result.js | 12 +- packages/pg/lib/sasl.js | 14 +- packages/pg/lib/type-overrides.js | 6 +- packages/pg/lib/utils.js | 11 +- packages/pg/script/dump-db-types.js | 4 +- packages/pg/script/list-db-types.js | 2 +- packages/pg/test/buffer-list.js | 24 +-- .../pg/test/integration/client/api-tests.js | 54 +++---- .../test/integration/client/appname-tests.js | 28 ++-- .../pg/test/integration/client/array-tests.js | 56 +++---- .../client/big-simple-query-tests.js | 30 ++-- .../integration/client/configuration-tests.js | 4 +- .../integration/client/custom-types-tests.js | 4 +- .../integration/client/empty-query-tests.js | 8 +- .../client/error-handling-tests.js | 38 ++--- .../client/field-name-escape-tests.js | 2 +- .../integration/client/huge-numeric-tests.js | 8 +- ...le_in_transaction_session_timeout-tests.js | 28 ++-- .../client/json-type-parsing-tests.js | 6 +- .../client/multiple-results-tests.js | 6 +- .../client/network-partition-tests.js | 22 +-- .../test/integration/client/no-data-tests.js | 4 +- .../integration/client/no-row-result-tests.js | 8 +- .../test/integration/client/notice-tests.js | 18 +-- .../integration/client/parse-int-8-tests.js | 8 +- .../client/prepared-statement-tests.js | 42 +++--- .../client/query-as-promise-tests.js | 10 +- .../client/query-column-names-tests.js | 6 +- ...error-handling-prepared-statement-tests.js | 30 ++-- .../client/query-error-handling-tests.js | 32 ++-- .../client/result-metadata-tests.js | 12 +- .../client/results-as-array-tests.js | 8 +- .../row-description-on-results-tests.js | 14 +- .../integration/client/simple-query-tests.js | 32 ++-- .../pg/test/integration/client/ssl-tests.js | 6 +- .../client/statement_timeout-tests.js | 26 ++-- .../test/integration/client/timezone-tests.js | 10 +- .../integration/client/transaction-tests.js | 26 ++-- .../integration/client/type-coercion-tests.js | 40 ++--- .../client/type-parser-override-tests.js | 14 +- .../connection-pool/error-tests.js | 10 +- .../connection-pool/idle-timeout-tests.js | 4 +- .../connection-pool/native-instance-tests.js | 2 +- .../connection-pool/test-helper.js | 8 +- .../connection-pool/yield-support-tests.js | 2 +- .../connection/bound-command-tests.js | 24 +-- .../test/integration/connection/copy-tests.js | 20 +-- .../connection/notification-tests.js | 8 +- .../integration/connection/query-tests.js | 10 +- .../integration/connection/test-helper.js | 16 +- packages/pg/test/integration/domain-tests.js | 20 +-- .../test/integration/gh-issues/130-tests.js | 8 +- .../test/integration/gh-issues/131-tests.js | 6 +- .../test/integration/gh-issues/1854-tests.js | 2 +- .../test/integration/gh-issues/199-tests.js | 2 +- .../test/integration/gh-issues/507-tests.js | 6 +- .../test/integration/gh-issues/600-tests.js | 16 +- .../test/integration/gh-issues/675-tests.js | 8 +- .../test/integration/gh-issues/699-tests.js | 6 +- .../test/integration/gh-issues/787-tests.js | 4 +- .../test/integration/gh-issues/882-tests.js | 2 +- .../test/integration/gh-issues/981-tests.js | 4 +- packages/pg/test/integration/test-helper.js | 6 +- packages/pg/test/native/callback-api-tests.js | 12 +- packages/pg/test/native/evented-api-tests.js | 46 +++--- packages/pg/test/native/stress-tests.js | 18 +-- packages/pg/test/test-buffers.js | 78 ++++++---- packages/pg/test/test-helper.js | 56 +++---- .../unit/client/cleartext-password-tests.js | 4 +- .../test/unit/client/configuration-tests.js | 26 ++-- .../unit/client/early-disconnect-tests.js | 6 +- packages/pg/test/unit/client/escape-tests.js | 10 +- .../pg/test/unit/client/md5-password-tests.js | 8 +- .../pg/test/unit/client/notification-tests.js | 4 +- .../unit/client/prepared-statement-tests.js | 70 ++++----- .../pg/test/unit/client/query-queue-tests.js | 26 ++-- .../test/unit/client/result-metadata-tests.js | 8 +- .../pg/test/unit/client/sasl-scram-tests.js | 48 +++--- .../pg/test/unit/client/simple-query-tests.js | 48 +++--- ...tream-and-query-error-interaction-tests.js | 12 +- packages/pg/test/unit/client/test-helper.js | 8 +- .../unit/client/throw-in-type-parser-tests.js | 12 +- .../connection-parameters/creation-tests.js | 64 ++++---- .../environment-variable-tests.js | 14 +- .../pg/test/unit/connection/error-tests.js | 20 +-- .../unit/connection/inbound-parser-tests.js | 98 ++++++------ .../unit/connection/outbound-sending-tests.js | 85 +++++++---- .../pg/test/unit/connection/startup-tests.js | 32 ++-- packages/pg/test/unit/test-helper.js | 10 +- packages/pg/test/unit/utils-tests.js | 70 ++++----- yarn.lock | 8 +- 137 files changed, 1564 insertions(+), 1417 deletions(-) delete mode 100644 .prettierrc.json diff --git a/.prettierrc.json b/.prettierrc.json deleted file mode 100644 index eb146cdce..000000000 --- a/.prettierrc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "semi": false, - "printWidth": 120, - "trailingComma": "es5", - "singleQuote": true -} diff --git a/package.json b/package.json index 83867563a..4eb352834 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,13 @@ "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^3.1.2", "lerna": "^3.19.0", - "prettier": "^2.0.4" + "prettier": "1.19.1" + }, + "prettier": { + "semi": false, + "printWidth": 120, + "arrowParens": "always", + "trailingComma": "es5", + "singleQuote": true } } diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index 9d672dbff..1750b34c8 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -25,18 +25,18 @@ function Cursor(text, values, config) { util.inherits(Cursor, EventEmitter) -Cursor.prototype._ifNoData = function () { +Cursor.prototype._ifNoData = function() { this.state = 'idle' this._shiftQueue() } -Cursor.prototype._rowDescription = function () { +Cursor.prototype._rowDescription = function() { if (this.connection) { this.connection.removeListener('noData', this._ifNoData) } } -Cursor.prototype.submit = function (connection) { +Cursor.prototype.submit = function(connection) { this.connection = connection this._portal = 'C_' + nextUniqueID++ @@ -75,13 +75,13 @@ Cursor.prototype.submit = function (connection) { con.once('rowDescription', this._rowDescription) } -Cursor.prototype._shiftQueue = function () { +Cursor.prototype._shiftQueue = function() { if (this._queue.length) { this._getRows.apply(this, this._queue.shift()) } } -Cursor.prototype._closePortal = function () { +Cursor.prototype._closePortal = function() { // because we opened a named portal to stream results // we need to close the same named portal. Leaving a named portal // open can lock tables for modification if inside a transaction. @@ -90,19 +90,19 @@ Cursor.prototype._closePortal = function () { this.connection.sync() } -Cursor.prototype.handleRowDescription = function (msg) { +Cursor.prototype.handleRowDescription = function(msg) { this._result.addFields(msg.fields) this.state = 'idle' this._shiftQueue() } -Cursor.prototype.handleDataRow = function (msg) { +Cursor.prototype.handleDataRow = function(msg) { const row = this._result.parseRow(msg.fields) this.emit('row', row, this._result) this._rows.push(row) } -Cursor.prototype._sendRows = function () { +Cursor.prototype._sendRows = function() { this.state = 'idle' setImmediate(() => { const cb = this._cb @@ -118,26 +118,26 @@ Cursor.prototype._sendRows = function () { }) } -Cursor.prototype.handleCommandComplete = function (msg) { +Cursor.prototype.handleCommandComplete = function(msg) { this._result.addCommandComplete(msg) this._closePortal() } -Cursor.prototype.handlePortalSuspended = function () { +Cursor.prototype.handlePortalSuspended = function() { this._sendRows() } -Cursor.prototype.handleReadyForQuery = function () { +Cursor.prototype.handleReadyForQuery = function() { this._sendRows() this.state = 'done' this.emit('end', this._result) } -Cursor.prototype.handleEmptyQuery = function () { +Cursor.prototype.handleEmptyQuery = function() { this.connection.sync() } -Cursor.prototype.handleError = function (msg) { +Cursor.prototype.handleError = function(msg) { this.connection.removeListener('noData', this._ifNoData) this.connection.removeListener('rowDescription', this._rowDescription) this.state = 'error' @@ -159,7 +159,7 @@ Cursor.prototype.handleError = function (msg) { this.connection.sync() } -Cursor.prototype._getRows = function (rows, cb) { +Cursor.prototype._getRows = function(rows, cb) { this.state = 'busy' this._cb = cb this._rows = [] @@ -173,7 +173,7 @@ Cursor.prototype._getRows = function (rows, cb) { // users really shouldn't be calling 'end' here and terminating a connection to postgres // via the low level connection.end api -Cursor.prototype.end = util.deprecate(function (cb) { +Cursor.prototype.end = util.deprecate(function(cb) { if (this.state !== 'initialized') { this.connection.sync() } @@ -181,7 +181,7 @@ Cursor.prototype.end = util.deprecate(function (cb) { this.connection.end() }, 'Cursor.end is deprecated. Call end on the client itself to end a connection to the database.') -Cursor.prototype.close = function (cb) { +Cursor.prototype.close = function(cb) { if (!this.connection || this.state === 'done') { if (cb) { return setImmediate(cb) @@ -192,13 +192,13 @@ Cursor.prototype.close = function (cb) { this._closePortal() this.state = 'done' if (cb) { - this.connection.once('readyForQuery', function () { + this.connection.once('readyForQuery', function() { cb() }) } } -Cursor.prototype.read = function (rows, cb) { +Cursor.prototype.read = function(rows, cb) { if (this.state === 'idle') { return this._getRows(rows, cb) } diff --git a/packages/pg-cursor/test/close.js b/packages/pg-cursor/test/close.js index e63512abd..fbaa68069 100644 --- a/packages/pg-cursor/test/close.js +++ b/packages/pg-cursor/test/close.js @@ -3,51 +3,51 @@ const Cursor = require('../') const pg = require('pg') const text = 'SELECT generate_series as num FROM generate_series(0, 50)' -describe('close', function () { - beforeEach(function (done) { +describe('close', function() { + beforeEach(function(done) { const client = (this.client = new pg.Client()) client.connect(done) }) - this.afterEach(function (done) { + this.afterEach(function(done) { this.client.end(done) }) - it('can close a finished cursor without a callback', function (done) { + it('can close a finished cursor without a callback', function(done) { const cursor = new Cursor(text) this.client.query(cursor) this.client.query('SELECT NOW()', done) - cursor.read(100, function (err) { + cursor.read(100, function(err) { assert.ifError(err) cursor.close() }) }) - it('closes cursor early', function (done) { + it('closes cursor early', function(done) { const cursor = new Cursor(text) this.client.query(cursor) this.client.query('SELECT NOW()', done) - cursor.read(25, function (err) { + cursor.read(25, function(err) { assert.ifError(err) cursor.close() }) }) - it('works with callback style', function (done) { + it('works with callback style', function(done) { const cursor = new Cursor(text) const client = this.client client.query(cursor) - cursor.read(25, function (err, rows) { + cursor.read(25, function(err, rows) { assert.ifError(err) assert.strictEqual(rows.length, 25) - cursor.close(function (err) { + cursor.close(function(err) { assert.ifError(err) client.query('SELECT NOW()', done) }) }) }) - it('is a no-op to "close" the cursor before submitting it', function (done) { + it('is a no-op to "close" the cursor before submitting it', function(done) { const cursor = new Cursor(text) cursor.close(done) }) diff --git a/packages/pg-cursor/test/error-handling.js b/packages/pg-cursor/test/error-handling.js index f6edef6d5..a6c38342e 100644 --- a/packages/pg-cursor/test/error-handling.js +++ b/packages/pg-cursor/test/error-handling.js @@ -5,14 +5,14 @@ const pg = require('pg') const text = 'SELECT generate_series as num FROM generate_series(0, 4)' -describe('error handling', function () { - it('can continue after error', function (done) { +describe('error handling', function() { + it('can continue after error', function(done) { const client = new pg.Client() client.connect() const cursor = client.query(new Cursor('asdfdffsdf')) - cursor.read(1, function (err) { + cursor.read(1, function(err) { assert(err) - client.query('SELECT NOW()', function (err) { + client.query('SELECT NOW()', function(err) { assert.ifError(err) client.end() done() @@ -27,11 +27,11 @@ describe('read callback does not fire sync', () => { client.connect() const cursor = client.query(new Cursor('asdfdffsdf')) let after = false - cursor.read(1, function (err) { + cursor.read(1, function(err) { assert(err, 'error should be returned') assert.strictEqual(after, true, 'should not call read sync') after = false - cursor.read(1, function (err) { + cursor.read(1, function(err) { assert(err, 'error should be returned') assert.strictEqual(after, true, 'should not call read sync') client.end() @@ -47,13 +47,13 @@ describe('read callback does not fire sync', () => { client.connect() const cursor = client.query(new Cursor('SELECT NOW()')) let after = false - cursor.read(1, function (err) { + cursor.read(1, function(err) { assert(!err) assert.strictEqual(after, true, 'should not call read sync') - cursor.read(1, function (err) { + cursor.read(1, function(err) { assert(!err) after = false - cursor.read(1, function (err) { + cursor.read(1, function(err) { assert(!err) assert.strictEqual(after, true, 'should not call read sync') client.end() @@ -66,16 +66,16 @@ describe('read callback does not fire sync', () => { }) }) -describe('proper cleanup', function () { - it('can issue multiple cursors on one client', function (done) { +describe('proper cleanup', function() { + it('can issue multiple cursors on one client', function(done) { const client = new pg.Client() client.connect() const cursor1 = client.query(new Cursor(text)) - cursor1.read(8, function (err, rows) { + cursor1.read(8, function(err, rows) { assert.ifError(err) assert.strictEqual(rows.length, 5) const cursor2 = client.query(new Cursor(text)) - cursor2.read(8, function (err, rows) { + cursor2.read(8, function(err, rows) { assert.ifError(err) assert.strictEqual(rows.length, 5) client.end() diff --git a/packages/pg-cursor/test/index.js b/packages/pg-cursor/test/index.js index 24d3cfd79..462442235 100644 --- a/packages/pg-cursor/test/index.js +++ b/packages/pg-cursor/test/index.js @@ -4,58 +4,58 @@ const pg = require('pg') const text = 'SELECT generate_series as num FROM generate_series(0, 5)' -describe('cursor', function () { - beforeEach(function (done) { +describe('cursor', function() { + beforeEach(function(done) { const client = (this.client = new pg.Client()) client.connect(done) - this.pgCursor = function (text, values) { + this.pgCursor = function(text, values) { return client.query(new Cursor(text, values || [])) } }) - afterEach(function () { + afterEach(function() { this.client.end() }) - it('fetch 6 when asking for 10', function (done) { + it('fetch 6 when asking for 10', function(done) { const cursor = this.pgCursor(text) - cursor.read(10, function (err, res) { + cursor.read(10, function(err, res) { assert.ifError(err) assert.strictEqual(res.length, 6) done() }) }) - it('end before reading to end', function (done) { + it('end before reading to end', function(done) { const cursor = this.pgCursor(text) - cursor.read(3, function (err, res) { + cursor.read(3, function(err, res) { assert.ifError(err) assert.strictEqual(res.length, 3) done() }) }) - it('callback with error', function (done) { + it('callback with error', function(done) { const cursor = this.pgCursor('select asdfasdf') - cursor.read(1, function (err) { + cursor.read(1, function(err) { assert(err) done() }) }) - it('read a partial chunk of data', function (done) { + it('read a partial chunk of data', function(done) { const cursor = this.pgCursor(text) - cursor.read(2, function (err, res) { + cursor.read(2, function(err, res) { assert.ifError(err) assert.strictEqual(res.length, 2) - cursor.read(3, function (err, res) { + cursor.read(3, function(err, res) { assert(!err) assert.strictEqual(res.length, 3) - cursor.read(1, function (err, res) { + cursor.read(1, function(err, res) { assert(!err) assert.strictEqual(res.length, 1) - cursor.read(1, function (err, res) { + cursor.read(1, function(err, res) { assert(!err) assert.ifError(err) assert.strictEqual(res.length, 0) @@ -66,14 +66,14 @@ describe('cursor', function () { }) }) - it('read return length 0 past the end', function (done) { + it('read return length 0 past the end', function(done) { const cursor = this.pgCursor(text) - cursor.read(2, function (err) { + cursor.read(2, function(err) { assert(!err) - cursor.read(100, function (err, res) { + cursor.read(100, function(err, res) { assert(!err) assert.strictEqual(res.length, 4) - cursor.read(100, function (err, res) { + cursor.read(100, function(err, res) { assert(!err) assert.strictEqual(res.length, 0) done() @@ -82,14 +82,14 @@ describe('cursor', function () { }) }) - it('read huge result', function (done) { + it('read huge result', function(done) { this.timeout(10000) const text = 'SELECT generate_series as num FROM generate_series(0, 100000)' const values = [] const cursor = this.pgCursor(text, values) let count = 0 - const read = function () { - cursor.read(100, function (err, rows) { + const read = function() { + cursor.read(100, function(err, rows) { if (err) return done(err) if (!rows.length) { assert.strictEqual(count, 100001) @@ -105,14 +105,14 @@ describe('cursor', function () { read() }) - it('normalizes parameter values', function (done) { + it('normalizes parameter values', function(done) { const text = 'SELECT $1::json me' const values = [{ name: 'brian' }] const cursor = this.pgCursor(text, values) - cursor.read(1, function (err, rows) { + cursor.read(1, function(err, rows) { if (err) return done(err) assert.strictEqual(rows[0].me.name, 'brian') - cursor.read(1, function (err, rows) { + cursor.read(1, function(err, rows) { assert(!err) assert.strictEqual(rows.length, 0) done() @@ -120,9 +120,9 @@ describe('cursor', function () { }) }) - it('returns result along with rows', function (done) { + it('returns result along with rows', function(done) { const cursor = this.pgCursor(text) - cursor.read(1, function (err, rows, result) { + cursor.read(1, function(err, rows, result) { assert.ifError(err) assert.strictEqual(rows.length, 1) assert.strictEqual(rows, result.rows) @@ -134,7 +134,7 @@ describe('cursor', function () { }) }) - it('emits row events', function (done) { + it('emits row events', function(done) { const cursor = this.pgCursor(text) cursor.read(10) cursor.on('row', (row, result) => result.addRow(row)) @@ -144,7 +144,7 @@ describe('cursor', function () { }) }) - it('emits row events when cursor is closed manually', function (done) { + it('emits row events when cursor is closed manually', function(done) { const cursor = this.pgCursor(text) cursor.on('row', (row, result) => result.addRow(row)) cursor.on('end', (result) => { @@ -155,21 +155,21 @@ describe('cursor', function () { cursor.read(3, () => cursor.close()) }) - it('emits error events', function (done) { + it('emits error events', function(done) { const cursor = this.pgCursor('select asdfasdf') - cursor.on('error', function (err) { + cursor.on('error', function(err) { assert(err) done() }) }) - it('returns rowCount on insert', function (done) { + it('returns rowCount on insert', function(done) { const pgCursor = this.pgCursor this.client .query('CREATE TEMPORARY TABLE pg_cursor_test (foo VARCHAR(1), bar VARCHAR(1))') - .then(function () { + .then(function() { const cursor = pgCursor('insert into pg_cursor_test values($1, $2)', ['a', 'b']) - cursor.read(1, function (err, rows, result) { + cursor.read(1, function(err, rows, result) { assert.ifError(err) assert.strictEqual(rows.length, 0) assert.strictEqual(result.rowCount, 1) diff --git a/packages/pg-cursor/test/no-data-handling.js b/packages/pg-cursor/test/no-data-handling.js index 9c860b9cd..755658746 100644 --- a/packages/pg-cursor/test/no-data-handling.js +++ b/packages/pg-cursor/test/no-data-handling.js @@ -2,30 +2,30 @@ const assert = require('assert') const pg = require('pg') const Cursor = require('../') -describe('queries with no data', function () { - beforeEach(function (done) { +describe('queries with no data', function() { + beforeEach(function(done) { const client = (this.client = new pg.Client()) client.connect(done) }) - afterEach(function () { + afterEach(function() { this.client.end() }) - it('handles queries that return no data', function (done) { + it('handles queries that return no data', function(done) { const cursor = new Cursor('CREATE TEMPORARY TABLE whatwhat (thing int)') this.client.query(cursor) - cursor.read(100, function (err, rows) { + cursor.read(100, function(err, rows) { assert.ifError(err) assert.strictEqual(rows.length, 0) done() }) }) - it('handles empty query', function (done) { + it('handles empty query', function(done) { let cursor = new Cursor('-- this is a comment') cursor = this.client.query(cursor) - cursor.read(100, function (err, rows) { + cursor.read(100, function(err, rows) { assert.ifError(err) assert.strictEqual(rows.length, 0) done() diff --git a/packages/pg-cursor/test/pool.js b/packages/pg-cursor/test/pool.js index 9d8ca772f..9562ca8ae 100644 --- a/packages/pg-cursor/test/pool.js +++ b/packages/pg-cursor/test/pool.js @@ -31,16 +31,16 @@ function poolQueryPromise(pool, readRowCount) { }) } -describe('pool', function () { - beforeEach(function () { +describe('pool', function() { + beforeEach(function() { this.pool = new pg.Pool({ max: 1 }) }) - afterEach(function () { + afterEach(function() { this.pool.end() }) - it('closes cursor early, single pool query', function (done) { + it('closes cursor early, single pool query', function(done) { poolQueryPromise(this.pool, 25) .then(() => done()) .catch((err) => { @@ -49,7 +49,7 @@ describe('pool', function () { }) }) - it('closes cursor early, saturated pool', function (done) { + it('closes cursor early, saturated pool', function(done) { const promises = [] for (let i = 0; i < 10; i++) { promises.push(poolQueryPromise(this.pool, 25)) @@ -62,7 +62,7 @@ describe('pool', function () { }) }) - it('closes exhausted cursor, single pool query', function (done) { + it('closes exhausted cursor, single pool query', function(done) { poolQueryPromise(this.pool, 100) .then(() => done()) .catch((err) => { @@ -71,7 +71,7 @@ describe('pool', function () { }) }) - it('closes exhausted cursor, saturated pool', function (done) { + it('closes exhausted cursor, saturated pool', function(done) { const promises = [] for (let i = 0; i < 10; i++) { promises.push(poolQueryPromise(this.pool, 100)) @@ -84,16 +84,16 @@ describe('pool', function () { }) }) - it('can close multiple times on a pool', async function () { + it('can close multiple times on a pool', async function() { const pool = new pg.Pool({ max: 1 }) const run = async () => { const cursor = new Cursor(text) const client = await pool.connect() client.query(cursor) await new Promise((resolve) => { - cursor.read(25, function (err) { + cursor.read(25, function(err) { assert.ifError(err) - cursor.close(function (err) { + cursor.close(function(err) { assert.ifError(err) client.release() resolve() diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 27875c1f8..fe104a3df 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -1,7 +1,7 @@ 'use strict' const EventEmitter = require('events').EventEmitter -const NOOP = function () {} +const NOOP = function() {} const removeWhere = (list, predicate) => { const i = list.findIndex(predicate) @@ -33,10 +33,10 @@ function promisify(Promise, callback) { } let rej let res - const cb = function (err, client) { + const cb = function(err, client) { err ? rej(err) : res(client) } - const result = new Promise(function (resolve, reject) { + const result = new Promise(function(resolve, reject) { res = resolve rej = reject }) @@ -76,7 +76,7 @@ class Pool extends EventEmitter { this.options.max = this.options.max || this.options.poolSize || 10 this.options.maxUses = this.options.maxUses || Infinity - this.log = this.options.log || function () {} + this.log = this.options.log || function() {} this.Client = this.options.Client || Client || require('pg').Client this.Promise = this.options.Promise || global.Promise @@ -321,7 +321,7 @@ class Pool extends EventEmitter { // guard clause against passing a function as the first parameter if (typeof text === 'function') { const response = promisify(this.Promise, text) - setImmediate(function () { + setImmediate(function() { return response.callback(new Error('Passing a function as the first parameter to pool.query is not supported')) }) return response.result diff --git a/packages/pg-pool/test/bring-your-own-promise.js b/packages/pg-pool/test/bring-your-own-promise.js index e905ccc0b..b9a74d433 100644 --- a/packages/pg-pool/test/bring-your-own-promise.js +++ b/packages/pg-pool/test/bring-your-own-promise.js @@ -13,10 +13,10 @@ const checkType = (promise) => { return promise.catch((e) => undefined) } -describe('Bring your own promise', function () { +describe('Bring your own promise', function() { it( 'uses supplied promise for operations', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool({ Promise: BluebirdPromise }) const client1 = yield checkType(pool.connect()) client1.release() @@ -30,7 +30,7 @@ describe('Bring your own promise', function () { it( 'uses promises in errors', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool({ Promise: BluebirdPromise, port: 48484 }) yield checkType(pool.connect()) yield checkType(pool.end()) diff --git a/packages/pg-pool/test/connection-strings.js b/packages/pg-pool/test/connection-strings.js index de45830dc..6d9794143 100644 --- a/packages/pg-pool/test/connection-strings.js +++ b/packages/pg-pool/test/connection-strings.js @@ -3,25 +3,25 @@ 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) { +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) { + Client: function(args) { expect(args.connectionString).to.equal(connectionString) return { - connect: function (cb) { + connect: function(cb) { cb(new Error('testing')) }, - on: function () {}, + on: function() {}, } }, connectionString: connectionString, }) - pool.connect(function (err, client) { + pool.connect(function(err, client) { expect(err).to.not.be(undefined) done() }) diff --git a/packages/pg-pool/test/connection-timeout.js b/packages/pg-pool/test/connection-timeout.js index 05e8931df..1624a1ec2 100644 --- a/packages/pg-pool/test/connection-timeout.js +++ b/packages/pg-pool/test/connection-timeout.js @@ -54,7 +54,7 @@ describe('connection timeout', () => { it( 'should handle multiple timeouts', co.wrap( - function* () { + function*() { const errors = [] const pool = new Pool({ connectionTimeoutMillis: 1, port: this.port, host: 'localhost' }) for (var i = 0; i < 15; i++) { @@ -142,7 +142,7 @@ describe('connection timeout', () => { const orgConnect = Client.prototype.connect let called = false - Client.prototype.connect = function (cb) { + Client.prototype.connect = function(cb) { // Simulate a failure on first call if (!called) { called = true @@ -179,7 +179,7 @@ describe('connection timeout', () => { let connection = 0 - Client.prototype.connect = function (cb) { + Client.prototype.connect = function(cb) { // Simulate a failure on first call if (connection === 0) { connection++ diff --git a/packages/pg-pool/test/ending.js b/packages/pg-pool/test/ending.js index e1839b46c..379575bdb 100644 --- a/packages/pg-pool/test/ending.js +++ b/packages/pg-pool/test/ending.js @@ -19,7 +19,7 @@ describe('pool ending', () => { it( 'ends with clients', - co.wrap(function* () { + 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') @@ -29,7 +29,7 @@ describe('pool ending', () => { it( 'allows client to finish', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool() const query = pool.query('SELECT $1::text as name', ['brianc']) yield pool.end() diff --git a/packages/pg-pool/test/error-handling.js b/packages/pg-pool/test/error-handling.js index fea1d1148..6c92dd729 100644 --- a/packages/pg-pool/test/error-handling.js +++ b/packages/pg-pool/test/error-handling.js @@ -8,20 +8,20 @@ const it = require('mocha').it const Pool = require('../') -describe('pool error handling', function () { - it('Should complete these queries without dying', function (done) { +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) { + return new Promise(function(resolve, reject) { pool .query("SELECT 'asd'+1 ") - .then(function (res) { + .then(function(res) { reject(res) // this should always error }) - .catch(function (err) { + .catch(function(err) { errors++ resolve(err) }) @@ -31,7 +31,7 @@ describe('pool error handling', function () { for (let i = 0; i < 5; i++) { ps.push(runErrorQuery()) } - Promise.all(ps).then(function () { + Promise.all(ps).then(function() { expect(shouldGet).to.eql(errors) pool.end(done) }) @@ -40,7 +40,7 @@ describe('pool error handling', function () { describe('calling release more than once', () => { it( 'should throw each time', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool() const client = yield pool.connect() client.release() @@ -50,10 +50,10 @@ describe('pool error handling', function () { }) ) - it('should throw each time with callbacks', function (done) { + it('should throw each time with callbacks', function(done) { const pool = new Pool() - pool.connect(function (err, client, clientDone) { + pool.connect(function(err, client, clientDone) { expect(err).not.to.be.an(Error) clientDone() @@ -66,7 +66,7 @@ describe('pool error handling', function () { }) describe('calling connect after end', () => { - it('should return an error', function* () { + 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') @@ -113,7 +113,7 @@ describe('pool error handling', function () { describe('error from idle client', () => { it( 'removes client from pool', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool() const client = yield pool.connect() expect(pool.totalCount).to.equal(1) @@ -148,7 +148,7 @@ describe('pool error handling', function () { describe('error from in-use client', () => { it( 'keeps the client in the pool', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool() const client = yield pool.connect() expect(pool.totalCount).to.equal(1) @@ -195,7 +195,7 @@ describe('pool error handling', function () { describe('pool with lots of errors', () => { it( 'continues to work and provide new clients', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool({ max: 1 }) const errors = [] for (var i = 0; i < 20; i++) { diff --git a/packages/pg-pool/test/events.js b/packages/pg-pool/test/events.js index 61979247d..1a0a52c1b 100644 --- a/packages/pg-pool/test/events.js +++ b/packages/pg-pool/test/events.js @@ -6,15 +6,15 @@ const describe = require('mocha').describe const it = require('mocha').it const Pool = require('../') -describe('events', function () { - it('emits connect before callback', function (done) { +describe('events', function() { + it('emits connect before callback', function(done) { const pool = new Pool() let emittedClient = false - pool.on('connect', function (client) { + pool.on('connect', function(client) { emittedClient = client }) - pool.connect(function (err, client, release) { + pool.connect(function(err, client, release) { if (err) return done(err) release() pool.end() @@ -23,52 +23,52 @@ describe('events', function () { }) }) - it('emits "connect" only with a successful connection', function () { + it('emits "connect" only with a successful connection', function() { const pool = new Pool({ // This client will always fail to connect Client: mockClient({ - connect: function (cb) { + connect: function(cb) { process.nextTick(() => { cb(new Error('bad news')) }) }, }), }) - pool.on('connect', function () { + 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) { + it('emits acquire every time a client is acquired', function(done) { const pool = new Pool() let acquireCount = 0 - pool.on('acquire', function (client) { + pool.on('acquire', function(client) { expect(client).to.be.ok() acquireCount++ }) for (let i = 0; i < 10; i++) { - pool.connect(function (err, client, release) { + pool.connect(function(err, client, release) { if (err) return done(err) release() }) pool.query('SELECT now()') } - setTimeout(function () { + 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) { + 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) { + pool.connect(function(err, client) { expect(err).to.equal(undefined) client.release() - setImmediate(function () { + setImmediate(function() { client.emit('error', new Error('problem')) }) - pool.once('error', function (err, errClient) { + pool.once('error', function(err, errClient) { expect(err.message).to.equal('problem') expect(errClient).to.equal(client) done() @@ -78,7 +78,7 @@ describe('events', function () { }) function mockClient(methods) { - return function () { + return function() { const client = new EventEmitter() Object.assign(client, methods) return client diff --git a/packages/pg-pool/test/idle-timeout.js b/packages/pg-pool/test/idle-timeout.js index fd9fba4a4..bf9bbae23 100644 --- a/packages/pg-pool/test/idle-timeout.js +++ b/packages/pg-pool/test/idle-timeout.js @@ -22,7 +22,7 @@ describe('idle timeout', () => { it( 'times out and removes clients when others are also removed', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool({ idleTimeoutMillis: 10 }) const clientA = yield pool.connect() const clientB = yield pool.connect() @@ -49,7 +49,7 @@ describe('idle timeout', () => { it( 'can remove idle clients and recreate them', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool({ idleTimeoutMillis: 1 }) const results = [] for (var i = 0; i < 20; i++) { @@ -67,7 +67,7 @@ describe('idle timeout', () => { it( 'does not time out clients which are used', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool({ idleTimeoutMillis: 1 }) const results = [] for (var i = 0; i < 20; i++) { diff --git a/packages/pg-pool/test/index.js b/packages/pg-pool/test/index.js index 57a68e01e..bc8f2a241 100644 --- a/packages/pg-pool/test/index.js +++ b/packages/pg-pool/test/index.js @@ -7,13 +7,13 @@ const it = require('mocha').it const Pool = require('../') -describe('pool', function () { - describe('with callbacks', function () { - it('works totally unconfigured', function (done) { +describe('pool', function() { + describe('with callbacks', function() { + it('works totally unconfigured', function(done) { const pool = new Pool() - pool.connect(function (err, client, release) { + pool.connect(function(err, client, release) { if (err) return done(err) - client.query('SELECT NOW()', function (err, res) { + client.query('SELECT NOW()', function(err, res) { release() if (err) return done(err) expect(res.rows).to.have.length(1) @@ -22,9 +22,9 @@ describe('pool', function () { }) }) - it('passes props to clients', function (done) { + it('passes props to clients', function(done) { const pool = new Pool({ binary: true }) - pool.connect(function (err, client, release) { + pool.connect(function(err, client, release) { release() if (err) return done(err) expect(client.binary).to.eql(true) @@ -32,42 +32,42 @@ describe('pool', function () { }) }) - it('can run a query with a callback without parameters', function (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) { + pool.query('SELECT 1 as num', function(err, res) { expect(res.rows[0]).to.eql({ num: 1 }) - pool.end(function () { + pool.end(function() { done(err) }) }) }) - it('can run a query with a callback', function (done) { + 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) { + pool.query('SELECT $1::text as name', ['brianc'], function(err, res) { expect(res.rows[0]).to.eql({ name: 'brianc' }) - pool.end(function () { + pool.end(function() { done(err) }) }) }) - it('passes connection errors to callback', function (done) { + 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) { + 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) { + pool.end(function(err) { done(err) }) }) }) - it('does not pass client to error callback', function (done) { + it('does not pass client to error callback', function(done) { const pool = new Pool({ port: 58242 }) - pool.connect(function (err, client, release) { + pool.connect(function(err, client, release) { expect(err).to.be.an(Error) expect(client).to.be(undefined) expect(release).to.be.a(Function) @@ -75,30 +75,30 @@ describe('pool', function () { }) }) - it('removes client if it errors in background', function (done) { + it('removes client if it errors in background', function(done) { const pool = new Pool() - pool.connect(function (err, client, release) { + pool.connect(function(err, client, release) { release() if (err) return done(err) client.testString = 'foo' - setTimeout(function () { + setTimeout(function() { client.emit('error', new Error('on purpose')) }, 10) }) - pool.on('error', function (err) { + 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 () { + err.client.connection.stream.on('end', function() { pool.end(done) }) }) }) - it('should not change given options', function (done) { + it('should not change given options', function(done) { const options = { max: 10 } const pool = new Pool(options) - pool.connect(function (err, client, release) { + pool.connect(function(err, client, release) { release() if (err) return done(err) expect(options).to.eql({ max: 10 }) @@ -106,9 +106,9 @@ describe('pool', function () { }) }) - it('does not create promises when connecting', function (done) { + it('does not create promises when connecting', function(done) { const pool = new Pool() - const returnValue = pool.connect(function (err, client, release) { + const returnValue = pool.connect(function(err, client, release) { release() if (err) return done(err) pool.end(done) @@ -116,23 +116,23 @@ describe('pool', function () { expect(returnValue).to.be(undefined) }) - it('does not create promises when querying', function (done) { + 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 () { + 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) { + 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) { + it('never calls callback syncronously', function(done) { const pool = new Pool() pool.connect((err, client) => { if (err) throw err @@ -153,11 +153,11 @@ describe('pool', function () { }) }) - describe('with promises', function () { - it('connects, queries, and disconnects', function () { + 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) { + 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() @@ -174,41 +174,41 @@ describe('pool', function () { }) }) - it('properly pools clients', function () { + 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) { + 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) { + 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 () { + 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) { + return Promise.all(promises).then(function(queries) { expect(queries).to.have.length(30) return pool.end() }) }) - it('recovers from query errors', function () { + it('recovers from query errors', function() { const pool = new Pool() const errors = [] const promises = _.times(30, () => { - return pool.query('SELECT asldkfjasldkf').catch(function (e) { + return pool.query('SELECT asldkfjasldkf').catch(function(e) { errors.push(e) }) }) @@ -216,7 +216,7 @@ describe('pool', function () { 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) { + return pool.query('SELECT $1::text as name', ['hi']).then(function(res) { expect(res.rows).to.eql([{ name: 'hi' }]) return pool.end() }) diff --git a/packages/pg-pool/test/logging.js b/packages/pg-pool/test/logging.js index 839603b78..9374e2751 100644 --- a/packages/pg-pool/test/logging.js +++ b/packages/pg-pool/test/logging.js @@ -5,14 +5,14 @@ const it = require('mocha').it const Pool = require('../') -describe('logging', function () { - it('logs to supplied log function if given', function () { +describe('logging', function() { + it('logs to supplied log function if given', function() { const messages = [] - const log = function (msg) { + const log = function(msg) { messages.push(msg) } const pool = new Pool({ log: log }) - return pool.query('SELECT NOW()').then(function () { + return pool.query('SELECT NOW()').then(function() { expect(messages.length).to.be.greaterThan(0) return pool.end() }) diff --git a/packages/pg-pool/test/max-uses.js b/packages/pg-pool/test/max-uses.js index c94ddec6b..840ac6419 100644 --- a/packages/pg-pool/test/max-uses.js +++ b/packages/pg-pool/test/max-uses.js @@ -10,7 +10,7 @@ const Pool = require('../') describe('maxUses', () => { it( 'can create a single client and use it once', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool({ maxUses: 2 }) expect(pool.waitingCount).to.equal(0) const client = yield pool.connect() @@ -23,7 +23,7 @@ describe('maxUses', () => { it( 'getting a connection a second time returns the same connection and releasing it also closes it', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool({ maxUses: 2 }) expect(pool.waitingCount).to.equal(0) const client = yield pool.connect() @@ -39,7 +39,7 @@ describe('maxUses', () => { it( 'getting a connection a third time returns a new connection', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool({ maxUses: 2 }) expect(pool.waitingCount).to.equal(0) const client = yield pool.connect() @@ -56,7 +56,7 @@ describe('maxUses', () => { it( 'getting a connection from a pending request gets a fresh client when the released candidate is expended', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool({ max: 1, maxUses: 2 }) expect(pool.waitingCount).to.equal(0) const client1 = yield pool.connect() @@ -83,9 +83,9 @@ describe('maxUses', () => { it( 'logs when removing an expended client', - co.wrap(function* () { + co.wrap(function*() { const messages = [] - const log = function (msg) { + const log = function(msg) { messages.push(msg) } const pool = new Pool({ maxUses: 1, log }) diff --git a/packages/pg-pool/test/sizing.js b/packages/pg-pool/test/sizing.js index e7863ba07..32154548a 100644 --- a/packages/pg-pool/test/sizing.js +++ b/packages/pg-pool/test/sizing.js @@ -10,7 +10,7 @@ const Pool = require('../') describe('pool size of 1', () => { it( 'can create a single client and use it once', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool({ max: 1 }) expect(pool.waitingCount).to.equal(0) const client = yield pool.connect() @@ -23,7 +23,7 @@ describe('pool size of 1', () => { it( 'can create a single client and use it multiple times', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool({ max: 1 }) expect(pool.waitingCount).to.equal(0) const client = yield pool.connect() @@ -39,7 +39,7 @@ describe('pool size of 1', () => { it( 'can only send 1 query at a time', - co.wrap(function* () { + co.wrap(function*() { const pool = new Pool({ max: 1 }) // the query text column name changed in PostgreSQL 9.2 diff --git a/packages/pg-protocol/src/inbound-parser.test.ts b/packages/pg-protocol/src/inbound-parser.test.ts index 8a8785a5c..8ea9f7570 100644 --- a/packages/pg-protocol/src/inbound-parser.test.ts +++ b/packages/pg-protocol/src/inbound-parser.test.ts @@ -14,7 +14,7 @@ var parseCompleteBuffer = buffers.parseComplete() var bindCompleteBuffer = buffers.bindComplete() var portalSuspendedBuffer = buffers.portalSuspended() -var addRow = function (bufferList: BufferList, name: string, offset: number) { +var addRow = function(bufferList: BufferList, name: string, offset: number) { return bufferList .addCString(name) // field name .addInt32(offset++) // table id @@ -144,7 +144,7 @@ var expectedTwoRowMessage = { ], } -var testForMessage = function (buffer: Buffer, expectedMessage: any) { +var testForMessage = function(buffer: Buffer, expectedMessage: any) { it('recieves and parses ' + expectedMessage.name, async () => { const messages = await parseBuffers([buffer]) const [lastMessage] = messages @@ -204,7 +204,7 @@ const parseBuffers = async (buffers: Buffer[]): Promise => { return msgs } -describe('PgPacketStream', function () { +describe('PgPacketStream', function() { testForMessage(authOkBuffer, expectedAuthenticationOkayMessage) testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage) testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage) @@ -226,21 +226,21 @@ describe('PgPacketStream', function () { name: 'noData', }) - describe('rowDescription messages', function () { + describe('rowDescription messages', function() { testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage) testForMessage(oneRowDescBuff, expectedOneRowMessage) testForMessage(twoRowBuf, expectedTwoRowMessage) }) - describe('parsing rows', function () { - describe('parsing empty row', function () { + describe('parsing rows', function() { + describe('parsing empty row', function() { testForMessage(emptyRowFieldBuf, { name: 'dataRow', fieldCount: 0, }) }) - describe('parsing data row with fields', function () { + describe('parsing data row with fields', function() { testForMessage(oneFieldBuf, { name: 'dataRow', fieldCount: 1, @@ -249,7 +249,7 @@ describe('PgPacketStream', function () { }) }) - describe('notice message', function () { + describe('notice message', function() { // this uses the same logic as error message var buff = buffers.notice([{ type: 'C', value: 'code' }]) testForMessage(buff, { @@ -262,7 +262,7 @@ describe('PgPacketStream', function () { name: 'error', }) - describe('with all the fields', function () { + describe('with all the fields', function() { var buffer = buffers.error([ { type: 'S', @@ -351,13 +351,13 @@ describe('PgPacketStream', function () { name: 'closeComplete', }) - describe('parses portal suspended message', function () { + describe('parses portal suspended message', function() { testForMessage(portalSuspendedBuffer, { name: 'portalSuspended', }) }) - describe('parses replication start message', function () { + describe('parses replication start message', function() { testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { name: 'replicationStart', length: 4, @@ -408,10 +408,10 @@ describe('PgPacketStream', function () { // since the data message on a stream can randomly divide the incomming // tcp packets anywhere, we need to make sure we can parse every single // split on a tcp message - describe('split buffer, single message parsing', function () { + describe('split buffer, single message parsing', function() { var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']) - it('parses when full buffer comes in', async function () { + it('parses when full buffer comes in', async function() { const messages = await parseBuffers([fullBuffer]) const message = messages[0] as any assert.equal(message.fields.length, 5) @@ -422,7 +422,7 @@ describe('PgPacketStream', function () { assert.equal(message.fields[4], '!') }) - var testMessageRecievedAfterSpiltAt = async function (split: number) { + var testMessageRecievedAfterSpiltAt = async function(split: number) { var firstBuffer = Buffer.alloc(fullBuffer.length - split) var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) fullBuffer.copy(firstBuffer, 0, 0) @@ -437,29 +437,29 @@ describe('PgPacketStream', function () { assert.equal(message.fields[4], '!') } - it('parses when split in the middle', function () { + it('parses when split in the middle', function() { testMessageRecievedAfterSpiltAt(6) }) - it('parses when split at end', function () { + it('parses when split at end', function() { testMessageRecievedAfterSpiltAt(2) }) - it('parses when split at beginning', function () { + it('parses when split at beginning', function() { testMessageRecievedAfterSpiltAt(fullBuffer.length - 2) testMessageRecievedAfterSpiltAt(fullBuffer.length - 1) testMessageRecievedAfterSpiltAt(fullBuffer.length - 5) }) }) - describe('split buffer, multiple message parsing', function () { + describe('split buffer, multiple message parsing', function() { var dataRowBuffer = buffers.dataRow(['!']) var readyForQueryBuffer = buffers.readyForQuery() var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length) dataRowBuffer.copy(fullBuffer, 0, 0) readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0) - var verifyMessages = function (messages: any[]) { + var verifyMessages = function(messages: any[]) { assert.strictEqual(messages.length, 2) assert.deepEqual(messages[0], { name: 'dataRow', @@ -475,12 +475,12 @@ describe('PgPacketStream', function () { }) } // sanity check - it('recieves both messages when packet is not split', async function () { + it('recieves both messages when packet is not split', async function() { const messages = await parseBuffers([fullBuffer]) verifyMessages(messages) }) - var splitAndVerifyTwoMessages = async function (split: number) { + var splitAndVerifyTwoMessages = async function(split: number) { var firstBuffer = Buffer.alloc(fullBuffer.length - split) var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) fullBuffer.copy(firstBuffer, 0, 0) @@ -489,11 +489,11 @@ describe('PgPacketStream', function () { verifyMessages(messages) } - describe('recieves both messages when packet is split', function () { - it('in the middle', function () { + describe('recieves both messages when packet is split', function() { + it('in the middle', function() { return splitAndVerifyTwoMessages(11) }) - it('at the front', function () { + it('at the front', function() { return Promise.all([ splitAndVerifyTwoMessages(fullBuffer.length - 1), splitAndVerifyTwoMessages(fullBuffer.length - 4), @@ -501,7 +501,7 @@ describe('PgPacketStream', function () { ]) }) - it('at the end', function () { + it('at the end', function() { return Promise.all([splitAndVerifyTwoMessages(8), splitAndVerifyTwoMessages(1)]) }) }) diff --git a/packages/pg-protocol/src/outbound-serializer.test.ts b/packages/pg-protocol/src/outbound-serializer.test.ts index 4d2457e19..23de94c92 100644 --- a/packages/pg-protocol/src/outbound-serializer.test.ts +++ b/packages/pg-protocol/src/outbound-serializer.test.ts @@ -3,7 +3,7 @@ import { serialize } from './serializer' import BufferList from './testing/buffer-list' describe('serializer', () => { - it('builds startup message', function () { + it('builds startup message', function() { const actual = serialize.startup({ user: 'brian', database: 'bang', @@ -24,51 +24,66 @@ describe('serializer', () => { ) }) - it('builds password message', function () { + it('builds password message', function() { const actual = serialize.password('!') assert.deepEqual(actual, new BufferList().addCString('!').join(true, 'p')) }) - it('builds request ssl message', function () { + it('builds request ssl message', function() { const actual = serialize.requestSsl() const expected = new BufferList().addInt32(80877103).join(true) assert.deepEqual(actual, expected) }) - it('builds SASLInitialResponseMessage message', function () { + it('builds SASLInitialResponseMessage message', function() { const actual = serialize.sendSASLInitialResponseMessage('mech', 'data') - assert.deepEqual(actual, new BufferList().addCString('mech').addInt32(4).addString('data').join(true, 'p')) + assert.deepEqual( + actual, + new BufferList() + .addCString('mech') + .addInt32(4) + .addString('data') + .join(true, 'p') + ) }) - it('builds SCRAMClientFinalMessage message', function () { + it('builds SCRAMClientFinalMessage message', function() { const actual = serialize.sendSCRAMClientFinalMessage('data') assert.deepEqual(actual, new BufferList().addString('data').join(true, 'p')) }) - it('builds query message', function () { + it('builds query message', function() { var txt = 'select * from boom' const actual = serialize.query(txt) assert.deepEqual(actual, new BufferList().addCString(txt).join(true, 'Q')) }) describe('parse message', () => { - it('builds parse message', function () { + it('builds parse message', function() { const actual = serialize.parse({ text: '!' }) - var expected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P') + var expected = new BufferList() + .addCString('') + .addCString('!') + .addInt16(0) + .join(true, 'P') assert.deepEqual(actual, expected) }) - it('builds parse message with named query', function () { + it('builds parse message with named query', function() { const actual = serialize.parse({ name: 'boom', text: 'select * from boom', types: [], }) - var expected = new BufferList().addCString('boom').addCString('select * from boom').addInt16(0).join(true, 'P') + var expected = new BufferList() + .addCString('boom') + .addCString('select * from boom') + .addInt16(0) + .join(true, 'P') assert.deepEqual(actual, expected) }) - it('with multiple parameters', function () { + it('with multiple parameters', function() { const actual = serialize.parse({ name: 'force', text: 'select * from bang where name = $1', @@ -87,8 +102,8 @@ describe('serializer', () => { }) }) - describe('bind messages', function () { - it('with no values', function () { + describe('bind messages', function() { + it('with no values', function() { const actual = serialize.bind() var expectedBuffer = new BufferList() @@ -101,7 +116,7 @@ describe('serializer', () => { assert.deepEqual(actual, expectedBuffer) }) - it('with named statement, portal, and values', function () { + it('with named statement, portal, and values', function() { const actual = serialize.bind({ portal: 'bang', statement: 'woo', @@ -125,7 +140,7 @@ describe('serializer', () => { }) }) - it('with named statement, portal, and buffer value', function () { + it('with named statement, portal, and buffer value', function() { const actual = serialize.bind({ portal: 'bang', statement: 'woo', @@ -152,70 +167,88 @@ describe('serializer', () => { assert.deepEqual(actual, expectedBuffer) }) - describe('builds execute message', function () { - it('for unamed portal with no row limit', function () { + describe('builds execute message', function() { + it('for unamed portal with no row limit', function() { const actual = serialize.execute() - var expectedBuffer = new BufferList().addCString('').addInt32(0).join(true, 'E') + var expectedBuffer = new BufferList() + .addCString('') + .addInt32(0) + .join(true, 'E') assert.deepEqual(actual, expectedBuffer) }) - it('for named portal with row limit', function () { + it('for named portal with row limit', function() { const actual = serialize.execute({ portal: 'my favorite portal', rows: 100, }) - var expectedBuffer = new BufferList().addCString('my favorite portal').addInt32(100).join(true, 'E') + var expectedBuffer = new BufferList() + .addCString('my favorite portal') + .addInt32(100) + .join(true, 'E') assert.deepEqual(actual, expectedBuffer) }) }) - it('builds flush command', function () { + it('builds flush command', function() { const actual = serialize.flush() var expected = new BufferList().join(true, 'H') assert.deepEqual(actual, expected) }) - it('builds sync command', function () { + it('builds sync command', function() { const actual = serialize.sync() var expected = new BufferList().join(true, 'S') assert.deepEqual(actual, expected) }) - it('builds end command', function () { + it('builds end command', function() { const actual = serialize.end() var expected = Buffer.from([0x58, 0, 0, 0, 4]) assert.deepEqual(actual, expected) }) - describe('builds describe command', function () { - it('describe statement', function () { + describe('builds describe command', function() { + it('describe statement', function() { const actual = serialize.describe({ type: 'S', name: 'bang' }) - var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D') + var expected = new BufferList() + .addChar('S') + .addCString('bang') + .join(true, 'D') assert.deepEqual(actual, expected) }) - it('describe unnamed portal', function () { + it('describe unnamed portal', function() { const actual = serialize.describe({ type: 'P' }) - var expected = new BufferList().addChar('P').addCString('').join(true, 'D') + var expected = new BufferList() + .addChar('P') + .addCString('') + .join(true, 'D') assert.deepEqual(actual, expected) }) }) - describe('builds close command', function () { - it('describe statement', function () { + describe('builds close command', function() { + it('describe statement', function() { const actual = serialize.close({ type: 'S', name: 'bang' }) - var expected = new BufferList().addChar('S').addCString('bang').join(true, 'C') + var expected = new BufferList() + .addChar('S') + .addCString('bang') + .join(true, 'C') assert.deepEqual(actual, expected) }) - it('describe unnamed portal', function () { + it('describe unnamed portal', function() { const actual = serialize.close({ type: 'P' }) - var expected = new BufferList().addChar('P').addCString('').join(true, 'C') + var expected = new BufferList() + .addChar('P') + .addCString('') + .join(true, 'C') assert.deepEqual(actual, expected) }) }) - describe('copy messages', function () { + describe('copy messages', function() { it('builds copyFromChunk', () => { const actual = serialize.copyData(Buffer.from([1, 2, 3])) const expected = new BufferList().add(Buffer.from([1, 2, 3])).join(true, 'd') @@ -237,7 +270,12 @@ describe('serializer', () => { it('builds cancel message', () => { const actual = serialize.cancel(3, 4) - const expected = new BufferList().addInt16(1234).addInt16(5678).addInt32(3).addInt32(4).join(true) + const expected = new BufferList() + .addInt16(1234) + .addInt16(5678) + .addInt32(3) + .addInt32(4) + .join(true) assert.deepEqual(actual, expected) }) }) diff --git a/packages/pg-protocol/src/serializer.ts b/packages/pg-protocol/src/serializer.ts index 00e43fffe..37208096e 100644 --- a/packages/pg-protocol/src/serializer.ts +++ b/packages/pg-protocol/src/serializer.ts @@ -32,7 +32,10 @@ const startup = (opts: Record): Buffer => { var length = bodyBuffer.length + 4 - return new Writer().addInt32(length).add(bodyBuffer).flush() + return new Writer() + .addInt32(length) + .add(bodyBuffer) + .flush() } const requestSsl = (): Buffer => { @@ -46,14 +49,17 @@ const password = (password: string): Buffer => { return writer.addCString(password).flush(code.startup) } -const sendSASLInitialResponseMessage = function (mechanism: string, initialResponse: string): Buffer { +const sendSASLInitialResponseMessage = function(mechanism: string, initialResponse: string): Buffer { // 0x70 = 'p' - writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse) + writer + .addCString(mechanism) + .addInt32(Buffer.byteLength(initialResponse)) + .addString(initialResponse) return writer.flush(code.startup) } -const sendSCRAMClientFinalMessage = function (additionalData: string): Buffer { +const sendSCRAMClientFinalMessage = function(additionalData: string): Buffer { return writer.addString(additionalData).flush(code.startup) } diff --git a/packages/pg-protocol/src/testing/buffer-list.ts b/packages/pg-protocol/src/testing/buffer-list.ts index 15ac785cc..35a5420a7 100644 --- a/packages/pg-protocol/src/testing/buffer-list.ts +++ b/packages/pg-protocol/src/testing/buffer-list.ts @@ -11,7 +11,7 @@ export default class BufferList { } public getByteLength(initial?: number) { - return this.buffers.reduce(function (previous, current) { + return this.buffers.reduce(function(previous, current) { return previous + current.length }, initial || 0) } @@ -58,7 +58,7 @@ export default class BufferList { } var result = Buffer.alloc(length) var index = 0 - this.buffers.forEach(function (buffer) { + this.buffers.forEach(function(buffer) { buffer.copy(result, index, 0) index += buffer.length }) diff --git a/packages/pg-protocol/src/testing/test-buffers.ts b/packages/pg-protocol/src/testing/test-buffers.ts index 19ba16cce..a378a5d2d 100644 --- a/packages/pg-protocol/src/testing/test-buffers.ts +++ b/packages/pg-protocol/src/testing/test-buffers.ts @@ -2,54 +2,70 @@ import BufferList from './buffer-list' const buffers = { - readyForQuery: function () { + readyForQuery: function() { return new BufferList().add(Buffer.from('I')).join(true, 'Z') }, - authenticationOk: function () { + authenticationOk: function() { return new BufferList().addInt32(0).join(true, 'R') }, - authenticationCleartextPassword: function () { + authenticationCleartextPassword: function() { return new BufferList().addInt32(3).join(true, 'R') }, - authenticationMD5Password: function () { + authenticationMD5Password: function() { return new BufferList() .addInt32(5) .add(Buffer.from([1, 2, 3, 4])) .join(true, 'R') }, - authenticationSASL: function () { - return new BufferList().addInt32(10).addCString('SCRAM-SHA-256').addCString('').join(true, 'R') + authenticationSASL: function() { + return new BufferList() + .addInt32(10) + .addCString('SCRAM-SHA-256') + .addCString('') + .join(true, 'R') }, - authenticationSASLContinue: function () { - return new BufferList().addInt32(11).addString('data').join(true, 'R') + authenticationSASLContinue: function() { + return new BufferList() + .addInt32(11) + .addString('data') + .join(true, 'R') }, - authenticationSASLFinal: function () { - return new BufferList().addInt32(12).addString('data').join(true, 'R') + authenticationSASLFinal: function() { + return new BufferList() + .addInt32(12) + .addString('data') + .join(true, 'R') }, - parameterStatus: function (name: string, value: string) { - return new BufferList().addCString(name).addCString(value).join(true, 'S') + parameterStatus: function(name: string, value: string) { + return new BufferList() + .addCString(name) + .addCString(value) + .join(true, 'S') }, - backendKeyData: function (processID: number, secretKey: number) { - return new BufferList().addInt32(processID).addInt32(secretKey).join(true, 'K') + backendKeyData: function(processID: number, secretKey: number) { + return new BufferList() + .addInt32(processID) + .addInt32(secretKey) + .join(true, 'K') }, - commandComplete: function (string: string) { + commandComplete: function(string: string) { return new BufferList().addCString(string).join(true, 'C') }, - rowDescription: function (fields: any[]) { + rowDescription: function(fields: any[]) { fields = fields || [] var buf = new BufferList() buf.addInt16(fields.length) - fields.forEach(function (field) { + fields.forEach(function(field) { buf .addCString(field.name) .addInt32(field.tableID || 0) @@ -62,11 +78,11 @@ const buffers = { return buf.join(true, 'T') }, - dataRow: function (columns: any[]) { + dataRow: function(columns: any[]) { columns = columns || [] var buf = new BufferList() buf.addInt16(columns.length) - columns.forEach(function (col) { + columns.forEach(function(col) { if (col == null) { buf.addInt32(-1) } else { @@ -78,49 +94,53 @@ const buffers = { return buf.join(true, 'D') }, - error: function (fields: any) { + error: function(fields: any) { return buffers.errorOrNotice(fields).join(true, 'E') }, - notice: function (fields: any) { + notice: function(fields: any) { return buffers.errorOrNotice(fields).join(true, 'N') }, - errorOrNotice: function (fields: any) { + errorOrNotice: function(fields: any) { fields = fields || [] var buf = new BufferList() - fields.forEach(function (field: any) { + fields.forEach(function(field: any) { buf.addChar(field.type) buf.addCString(field.value) }) return buf.add(Buffer.from([0])) // terminator }, - parseComplete: function () { + parseComplete: function() { return new BufferList().join(true, '1') }, - bindComplete: function () { + bindComplete: function() { return new BufferList().join(true, '2') }, - notification: function (id: number, channel: string, payload: string) { - return new BufferList().addInt32(id).addCString(channel).addCString(payload).join(true, 'A') + notification: function(id: number, channel: string, payload: string) { + return new BufferList() + .addInt32(id) + .addCString(channel) + .addCString(payload) + .join(true, 'A') }, - emptyQuery: function () { + emptyQuery: function() { return new BufferList().join(true, 'I') }, - portalSuspended: function () { + portalSuspended: function() { return new BufferList().join(true, 's') }, - closeComplete: function () { + closeComplete: function() { return new BufferList().join(true, '3') }, - copyIn: function (cols: number) { + copyIn: function(cols: number) { const list = new BufferList() // text mode .addByte(0) @@ -132,7 +152,7 @@ const buffers = { return list.join(true, 'G') }, - copyOut: function (cols: number) { + copyOut: function(cols: number) { const list = new BufferList() // text mode .addByte(0) @@ -144,11 +164,11 @@ const buffers = { return list.join(true, 'H') }, - copyData: function (bytes: Buffer) { + copyData: function(bytes: Buffer) { return new BufferList().add(bytes).join(true, 'd') }, - copyDone: function () { + copyDone: function() { return new BufferList().join(true, 'c') }, } diff --git a/packages/pg-query-stream/test/close.js b/packages/pg-query-stream/test/close.js index 4a95464a7..0f97277f7 100644 --- a/packages/pg-query-stream/test/close.js +++ b/packages/pg-query-stream/test/close.js @@ -7,37 +7,37 @@ var helper = require('./helper') if (process.version.startsWith('v8.')) { console.error('warning! node less than 10lts stream closing semantics may not behave properly') } else { - helper('close', function (client) { - it('emits close', function (done) { + helper('close', function(client) { + it('emits close', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], { batchSize: 2, highWaterMark: 2 }) var query = client.query(stream) - query.pipe(concat(function () {})) + query.pipe(concat(function() {})) query.on('close', done) }) }) - helper('early close', function (client) { - it('can be closed early', function (done) { + helper('early close', function(client) { + it('can be closed early', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [20000], { batchSize: 2, highWaterMark: 2, }) var query = client.query(stream) var readCount = 0 - query.on('readable', function () { + query.on('readable', function() { readCount++ query.read() }) - query.once('readable', function () { + query.once('readable', function() { query.destroy() }) - query.on('close', function () { + query.on('close', function() { assert(readCount < 10, 'should not have read more than 10 rows') done() }) }) - it('can destroy stream while reading', function (done) { + it('can destroy stream while reading', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') client.query(stream) stream.on('data', () => done(new Error('stream should not have returned rows'))) @@ -47,7 +47,7 @@ if (process.version.startsWith('v8.')) { }, 100) }) - it('emits an error when calling destroy with an error', function (done) { + it('emits an error when calling destroy with an error', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') client.query(stream) stream.on('data', () => done(new Error('stream should not have returned rows'))) @@ -62,7 +62,7 @@ if (process.version.startsWith('v8.')) { }, 100) }) - it('can destroy stream while reading an error', function (done) { + it('can destroy stream while reading an error', function(done) { var stream = new QueryStream('SELECT * from pg_sleep(1), basdfasdf;') client.query(stream) stream.on('data', () => done(new Error('stream should not have returned rows'))) @@ -73,7 +73,7 @@ if (process.version.startsWith('v8.')) { }) }) - it('does not crash when destroying the stream immediately after calling read', function (done) { + it('does not crash when destroying the stream immediately after calling read', function(done) { var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') client.query(stream) stream.on('data', () => done(new Error('stream should not have returned rows'))) @@ -81,7 +81,7 @@ if (process.version.startsWith('v8.')) { stream.on('close', done) }) - it('does not crash when destroying the stream before its submitted', function (done) { + it('does not crash when destroying the stream before its submitted', function(done) { var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') stream.on('data', () => done(new Error('stream should not have returned rows'))) stream.destroy() diff --git a/packages/pg-query-stream/test/concat.js b/packages/pg-query-stream/test/concat.js index 6ce17a28e..417a4486e 100644 --- a/packages/pg-query-stream/test/concat.js +++ b/packages/pg-query-stream/test/concat.js @@ -5,19 +5,19 @@ var helper = require('./helper') var QueryStream = require('../') -helper('concat', function (client) { - it('concats correctly', function (done) { +helper('concat', function(client) { + it('concats correctly', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) query .pipe( - through(function (row) { + through(function(row) { this.push(row.num) }) ) .pipe( - concat(function (result) { - var total = result.reduce(function (prev, cur) { + concat(function(result) { + var total = result.reduce(function(prev, cur) { return prev + cur }) assert.equal(total, 20100) diff --git a/packages/pg-query-stream/test/empty-query.js b/packages/pg-query-stream/test/empty-query.js index 25f7d6956..c4bfa95b2 100644 --- a/packages/pg-query-stream/test/empty-query.js +++ b/packages/pg-query-stream/test/empty-query.js @@ -2,21 +2,21 @@ const assert = require('assert') const helper = require('./helper') const QueryStream = require('../') -helper('empty-query', function (client) { - it('handles empty query', function (done) { +helper('empty-query', function(client) { + it('handles empty query', function(done) { const stream = new QueryStream('-- this is a comment', []) const query = client.query(stream) query - .on('end', function () { + .on('end', function() { // nothing should happen for empty query done() }) - .on('data', function () { + .on('data', function() { // noop to kick off reading }) }) - it('continues to function after stream', function (done) { + it('continues to function after stream', function(done) { client.query('SELECT NOW()', done) }) }) diff --git a/packages/pg-query-stream/test/error.js b/packages/pg-query-stream/test/error.js index 0b732923d..29b5edc40 100644 --- a/packages/pg-query-stream/test/error.js +++ b/packages/pg-query-stream/test/error.js @@ -3,22 +3,22 @@ var helper = require('./helper') var QueryStream = require('../') -helper('error', function (client) { - it('receives error on stream', function (done) { +helper('error', function(client) { + it('receives error on stream', function(done) { var stream = new QueryStream('SELECT * FROM asdf num', []) var query = client.query(stream) query - .on('error', function (err) { + .on('error', function(err) { assert(err) assert.equal(err.code, '42P01') done() }) - .on('data', function () { + .on('data', function() { // noop to kick of reading }) }) - it('continues to function after stream', function (done) { + it('continues to function after stream', function(done) { client.query('SELECT NOW()', done) }) }) diff --git a/packages/pg-query-stream/test/fast-reader.js b/packages/pg-query-stream/test/fast-reader.js index 4c6f31f95..77e023a0e 100644 --- a/packages/pg-query-stream/test/fast-reader.js +++ b/packages/pg-query-stream/test/fast-reader.js @@ -2,12 +2,12 @@ var assert = require('assert') var helper = require('./helper') var QueryStream = require('../') -helper('fast reader', function (client) { - it('works', function (done) { +helper('fast reader', function(client) { + it('works', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) var result = [] - stream.on('readable', function () { + stream.on('readable', function() { var res = stream.read() while (res) { if (result.length !== 201) { @@ -23,8 +23,8 @@ helper('fast reader', function (client) { res = stream.read() } }) - stream.on('end', function () { - var total = result.reduce(function (prev, cur) { + stream.on('end', function() { + var total = result.reduce(function(prev, cur) { return prev + cur }) assert.equal(total, 20100) diff --git a/packages/pg-query-stream/test/helper.js b/packages/pg-query-stream/test/helper.js index ad21d6ea2..f4e427203 100644 --- a/packages/pg-query-stream/test/helper.js +++ b/packages/pg-query-stream/test/helper.js @@ -1,15 +1,15 @@ var pg = require('pg') -module.exports = function (name, cb) { - describe(name, function () { +module.exports = function(name, cb) { + describe(name, function() { var client = new pg.Client() - before(function (done) { + before(function(done) { client.connect(done) }) cb(client) - after(function (done) { + after(function(done) { client.end() client.on('end', done) }) diff --git a/packages/pg-query-stream/test/instant.js b/packages/pg-query-stream/test/instant.js index 0939753bb..ae1b3c0a1 100644 --- a/packages/pg-query-stream/test/instant.js +++ b/packages/pg-query-stream/test/instant.js @@ -3,12 +3,12 @@ var concat = require('concat-stream') var QueryStream = require('../') -require('./helper')('instant', function (client) { - it('instant', function (done) { +require('./helper')('instant', function(client) { + it('instant', function(done) { var query = new QueryStream('SELECT pg_sleep(1)', []) var stream = client.query(query) stream.pipe( - concat(function (res) { + concat(function(res) { assert.equal(res.length, 1) done() }) diff --git a/packages/pg-query-stream/test/issue-3.js b/packages/pg-query-stream/test/issue-3.js index 7b467a3b3..ba03c5e60 100644 --- a/packages/pg-query-stream/test/issue-3.js +++ b/packages/pg-query-stream/test/issue-3.js @@ -1,7 +1,7 @@ var pg = require('pg') var QueryStream = require('../') -describe('end semantics race condition', function () { - before(function (done) { +describe('end semantics race condition', function() { + before(function(done) { var client = new pg.Client() client.connect() client.on('drain', client.end.bind(client)) @@ -9,7 +9,7 @@ describe('end semantics race condition', function () { client.query('create table IF NOT EXISTS p(id serial primary key)') client.query('create table IF NOT EXISTS c(id int primary key references p)') }) - it('works', function (done) { + it('works', function(done) { var client1 = new pg.Client() client1.connect() var client2 = new pg.Client() @@ -18,11 +18,11 @@ describe('end semantics race condition', function () { var qr = new QueryStream('INSERT INTO p DEFAULT VALUES RETURNING id') client1.query(qr) var id = null - qr.on('data', function (row) { + qr.on('data', function(row) { id = row.id }) - qr.on('end', function () { - client2.query('INSERT INTO c(id) VALUES ($1)', [id], function (err, rows) { + qr.on('end', function() { + client2.query('INSERT INTO c(id) VALUES ($1)', [id], function(err, rows) { client1.end() client2.end() done(err) diff --git a/packages/pg-query-stream/test/passing-options.js b/packages/pg-query-stream/test/passing-options.js index 858767de2..011e2e0d3 100644 --- a/packages/pg-query-stream/test/passing-options.js +++ b/packages/pg-query-stream/test/passing-options.js @@ -2,8 +2,8 @@ var assert = require('assert') var helper = require('./helper') var QueryStream = require('../') -helper('passing options', function (client) { - it('passes row mode array', function (done) { +helper('passing options', function(client) { + it('passes row mode array', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { rowMode: 'array' }) var query = client.query(stream) var result = [] @@ -17,7 +17,7 @@ helper('passing options', function (client) { }) }) - it('passes custom types', function (done) { + it('passes custom types', function(done) { const types = { getTypeParser: () => (string) => string, } diff --git a/packages/pg-query-stream/test/pauses.js b/packages/pg-query-stream/test/pauses.js index 3da9a0b07..f5d538552 100644 --- a/packages/pg-query-stream/test/pauses.js +++ b/packages/pg-query-stream/test/pauses.js @@ -4,8 +4,8 @@ var JSONStream = require('JSONStream') var QueryStream = require('../') -require('./helper')('pauses', function (client) { - it('pauses', function (done) { +require('./helper')('pauses', function(client) { + it('pauses', function(done) { this.timeout(5000) var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], { batchSize: 2, highWaterMark: 2 }) var query = client.query(stream) @@ -14,7 +14,7 @@ require('./helper')('pauses', function (client) { .pipe(JSONStream.stringify()) .pipe(pauser) .pipe( - concat(function (json) { + concat(function(json) { JSON.parse(json) done() }) diff --git a/packages/pg-query-stream/test/slow-reader.js b/packages/pg-query-stream/test/slow-reader.js index 3978f3004..b96c93ab5 100644 --- a/packages/pg-query-stream/test/slow-reader.js +++ b/packages/pg-query-stream/test/slow-reader.js @@ -6,24 +6,24 @@ var Transform = require('stream').Transform var mapper = new Transform({ objectMode: true }) -mapper._transform = function (obj, enc, cb) { +mapper._transform = function(obj, enc, cb) { this.push(obj) setTimeout(cb, 5) } -helper('slow reader', function (client) { - it('works', function (done) { +helper('slow reader', function(client) { + it('works', function(done) { this.timeout(50000) var stream = new QueryStream('SELECT * FROM generate_series(0, 201) num', [], { highWaterMark: 100, batchSize: 50, }) - stream.on('end', function () { + stream.on('end', function() { // console.log('stream end') }) client.query(stream) stream.pipe(mapper).pipe( - concat(function (res) { + concat(function(res) { done() }) ) diff --git a/packages/pg-query-stream/test/stream-tester-timestamp.js b/packages/pg-query-stream/test/stream-tester-timestamp.js index ce989cc3f..4f10b2894 100644 --- a/packages/pg-query-stream/test/stream-tester-timestamp.js +++ b/packages/pg-query-stream/test/stream-tester-timestamp.js @@ -2,17 +2,20 @@ var QueryStream = require('../') var spec = require('stream-spec') var assert = require('assert') -require('./helper')('stream tester timestamp', function (client) { - it('should not warn about max listeners', function (done) { +require('./helper')('stream tester timestamp', function(client) { + it('should not warn about max listeners', function(done) { var sql = "SELECT * FROM generate_series('1983-12-30 00:00'::timestamp, '2013-12-30 00:00', '1 years')" var stream = new QueryStream(sql, []) var ended = false var query = client.query(stream) - query.on('end', function () { + query.on('end', function() { ended = true }) - spec(query).readable().pausable({ strict: true }).validateOnExit() - var checkListeners = function () { + spec(query) + .readable() + .pausable({ strict: true }) + .validateOnExit() + var checkListeners = function() { assert(stream.listeners('end').length < 10) if (!ended) { setImmediate(checkListeners) diff --git a/packages/pg-query-stream/test/stream-tester.js b/packages/pg-query-stream/test/stream-tester.js index f5ab2e372..a0d53779b 100644 --- a/packages/pg-query-stream/test/stream-tester.js +++ b/packages/pg-query-stream/test/stream-tester.js @@ -2,11 +2,14 @@ var spec = require('stream-spec') var QueryStream = require('../') -require('./helper')('stream tester', function (client) { - it('passes stream spec', function (done) { +require('./helper')('stream tester', function(client) { + it('passes stream spec', function(done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) - spec(query).readable().pausable({ strict: true }).validateOnExit() + spec(query) + .readable() + .pausable({ strict: true }) + .validateOnExit() stream.on('end', done) }) }) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 04124f8a0..81f82fdac 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -22,7 +22,7 @@ if (process.env.PG_FAST_CONNECTION) { Connection = require('./connection-fast') } -var Client = function (config) { +var Client = function(config) { EventEmitter.call(this) this.connectionParameters = new ConnectionParameters(config) @@ -71,7 +71,7 @@ var Client = function (config) { util.inherits(Client, EventEmitter) -Client.prototype._errorAllQueries = function (err) { +Client.prototype._errorAllQueries = function(err) { const enqueueError = (query) => { process.nextTick(() => { query.handleError(err, this.connection) @@ -87,7 +87,7 @@ Client.prototype._errorAllQueries = function (err) { this.queryQueue.length = 0 } -Client.prototype._connect = function (callback) { +Client.prototype._connect = function(callback) { var self = this var con = this.connection if (this._connecting || this._connected) { @@ -114,7 +114,7 @@ Client.prototype._connect = function (callback) { } // once connection is established send startup message - con.on('connect', function () { + con.on('connect', function() { if (self.ssl) { con.requestSsl() } else { @@ -122,12 +122,12 @@ Client.prototype._connect = function (callback) { } }) - con.on('sslconnect', function () { + con.on('sslconnect', function() { con.startup(self.getStartupConf()) }) function checkPgPass(cb) { - return function (msg) { + return function(msg) { if (typeof self.password === 'function') { self._Promise .resolve() @@ -150,7 +150,7 @@ Client.prototype._connect = function (callback) { } else if (self.password !== null) { cb(msg) } else { - pgPass(self.connectionParameters, function (pass) { + pgPass(self.connectionParameters, function(pass) { if (undefined !== pass) { self.connectionParameters.password = self.password = pass } @@ -163,7 +163,7 @@ Client.prototype._connect = function (callback) { // password request handling con.on( 'authenticationCleartextPassword', - checkPgPass(function () { + checkPgPass(function() { con.password(self.password) }) ) @@ -171,7 +171,7 @@ Client.prototype._connect = function (callback) { // password request handling con.on( 'authenticationMD5Password', - checkPgPass(function (msg) { + checkPgPass(function(msg) { con.password(utils.postgresMd5PasswordHash(self.user, self.password, msg.salt)) }) ) @@ -180,7 +180,7 @@ Client.prototype._connect = function (callback) { var saslSession con.on( 'authenticationSASL', - checkPgPass(function (msg) { + checkPgPass(function(msg) { saslSession = sasl.startSession(msg.mechanisms) con.sendSASLInitialResponseMessage(saslSession.mechanism, saslSession.response) @@ -188,20 +188,20 @@ Client.prototype._connect = function (callback) { ) // password request handling (SASL) - con.on('authenticationSASLContinue', function (msg) { + con.on('authenticationSASLContinue', function(msg) { sasl.continueSession(saslSession, self.password, msg.data) con.sendSCRAMClientFinalMessage(saslSession.response) }) // password request handling (SASL) - con.on('authenticationSASLFinal', function (msg) { + con.on('authenticationSASLFinal', function(msg) { sasl.finalizeSession(saslSession, msg.data) saslSession = null }) - con.once('backendKeyData', function (msg) { + con.once('backendKeyData', function(msg) { self.processID = msg.processID self.secretKey = msg.secretKey }) @@ -241,7 +241,7 @@ Client.prototype._connect = function (callback) { // hook up query handling events to connection // after the connection initially becomes ready for queries - con.once('readyForQuery', function () { + con.once('readyForQuery', function() { self._connecting = false self._connected = true self._attachListeners(con) @@ -261,7 +261,7 @@ Client.prototype._connect = function (callback) { self.emit('connect') }) - con.on('readyForQuery', function () { + con.on('readyForQuery', function() { var activeQuery = self.activeQuery self.activeQuery = null self.readyForQuery = true @@ -298,12 +298,12 @@ Client.prototype._connect = function (callback) { }) }) - con.on('notice', function (msg) { + con.on('notice', function(msg) { self.emit('notice', msg) }) } -Client.prototype.connect = function (callback) { +Client.prototype.connect = function(callback) { if (callback) { this._connect(callback) return @@ -320,32 +320,32 @@ Client.prototype.connect = function (callback) { }) } -Client.prototype._attachListeners = function (con) { +Client.prototype._attachListeners = function(con) { const self = this // delegate rowDescription to active query - con.on('rowDescription', function (msg) { + con.on('rowDescription', function(msg) { self.activeQuery.handleRowDescription(msg) }) // delegate dataRow to active query - con.on('dataRow', function (msg) { + con.on('dataRow', function(msg) { self.activeQuery.handleDataRow(msg) }) // delegate portalSuspended to active query // eslint-disable-next-line no-unused-vars - con.on('portalSuspended', function (msg) { + con.on('portalSuspended', function(msg) { self.activeQuery.handlePortalSuspended(con) }) // delegate emptyQuery to active query // eslint-disable-next-line no-unused-vars - con.on('emptyQuery', function (msg) { + con.on('emptyQuery', function(msg) { self.activeQuery.handleEmptyQuery(con) }) // delegate commandComplete to active query - con.on('commandComplete', function (msg) { + con.on('commandComplete', function(msg) { self.activeQuery.handleCommandComplete(msg, con) }) @@ -353,27 +353,27 @@ Client.prototype._attachListeners = function (con) { // we track that its already been executed so we don't parse // it again on the same client // eslint-disable-next-line no-unused-vars - con.on('parseComplete', function (msg) { + con.on('parseComplete', function(msg) { if (self.activeQuery.name) { con.parsedStatements[self.activeQuery.name] = self.activeQuery.text } }) // eslint-disable-next-line no-unused-vars - con.on('copyInResponse', function (msg) { + con.on('copyInResponse', function(msg) { self.activeQuery.handleCopyInResponse(self.connection) }) - con.on('copyData', function (msg) { + con.on('copyData', function(msg) { self.activeQuery.handleCopyData(msg, self.connection) }) - con.on('notification', function (msg) { + con.on('notification', function(msg) { self.emit('notification', msg) }) } -Client.prototype.getStartupConf = function () { +Client.prototype.getStartupConf = function() { var params = this.connectionParameters var data = { @@ -398,7 +398,7 @@ Client.prototype.getStartupConf = function () { return data } -Client.prototype.cancel = function (client, query) { +Client.prototype.cancel = function(client, query) { if (client.activeQuery === query) { var con = this.connection @@ -409,7 +409,7 @@ Client.prototype.cancel = function (client, query) { } // once connection is established send cancel message - con.on('connect', function () { + con.on('connect', function() { con.cancel(client.processID, client.secretKey) }) } else if (client.queryQueue.indexOf(query) !== -1) { @@ -417,21 +417,21 @@ Client.prototype.cancel = function (client, query) { } } -Client.prototype.setTypeParser = function (oid, format, parseFn) { +Client.prototype.setTypeParser = function(oid, format, parseFn) { return this._types.setTypeParser(oid, format, parseFn) } -Client.prototype.getTypeParser = function (oid, format) { +Client.prototype.getTypeParser = function(oid, format) { return this._types.getTypeParser(oid, format) } // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c -Client.prototype.escapeIdentifier = function (str) { +Client.prototype.escapeIdentifier = function(str) { return '"' + str.replace(/"/g, '""') + '"' } // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c -Client.prototype.escapeLiteral = function (str) { +Client.prototype.escapeLiteral = function(str) { var hasBackslash = false var escaped = "'" @@ -456,7 +456,7 @@ Client.prototype.escapeLiteral = function (str) { return escaped } -Client.prototype._pulseQueryQueue = function () { +Client.prototype._pulseQueryQueue = function() { if (this.readyForQuery === true) { this.activeQuery = this.queryQueue.shift() if (this.activeQuery) { @@ -478,7 +478,7 @@ Client.prototype._pulseQueryQueue = function () { } } -Client.prototype.query = function (config, values, callback) { +Client.prototype.query = function(config, values, callback) { // can take in strings, config object or query object var query var result @@ -562,7 +562,7 @@ Client.prototype.query = function (config, values, callback) { return result } -Client.prototype.end = function (cb) { +Client.prototype.end = function(cb) { this._ending = true // if we have never connected, then end is a noop, callback immediately diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index acc5c0e8c..58764abf3 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -17,7 +17,7 @@ const { parse, serialize } = require('../../pg-protocol/dist') // TODO(bmc) support binary mode here // var BINARY_MODE = 1 console.log('***using faster connection***') -var Connection = function (config) { +var Connection = function(config) { EventEmitter.call(this) config = config || {} this.stream = config.stream || new net.Socket() @@ -30,7 +30,7 @@ var Connection = function (config) { this._ending = false this._emitMessage = false var self = this - this.on('newListener', function (eventName) { + this.on('newListener', function(eventName) { if (eventName === 'message') { self._emitMessage = true } @@ -39,7 +39,7 @@ var Connection = function (config) { util.inherits(Connection, EventEmitter) -Connection.prototype.connect = function (port, host) { +Connection.prototype.connect = function(port, host) { var self = this if (this.stream.readyState === 'closed') { @@ -48,14 +48,14 @@ Connection.prototype.connect = function (port, host) { this.emit('connect') } - this.stream.on('connect', function () { + this.stream.on('connect', function() { if (self._keepAlive) { self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis) } self.emit('connect') }) - const reportStreamError = function (error) { + const reportStreamError = function(error) { // errors about disconnections should be ignored during disconnect if (self._ending && (error.code === 'ECONNRESET' || error.code === 'EPIPE')) { return @@ -64,7 +64,7 @@ Connection.prototype.connect = function (port, host) { } this.stream.on('error', reportStreamError) - this.stream.on('close', function () { + this.stream.on('close', function() { self.emit('end') }) @@ -72,7 +72,7 @@ Connection.prototype.connect = function (port, host) { return this.attachListeners(this.stream) } - this.stream.once('data', function (buffer) { + this.stream.once('data', function(buffer) { var responseCode = buffer.toString('utf8') switch (responseCode) { case 'S': // Server supports SSL connections, continue with a secure connection @@ -103,7 +103,7 @@ Connection.prototype.connect = function (port, host) { }) } -Connection.prototype.attachListeners = function (stream) { +Connection.prototype.attachListeners = function(stream) { stream.on('end', () => { this.emit('end') }) @@ -116,67 +116,67 @@ Connection.prototype.attachListeners = function (stream) { }) } -Connection.prototype.requestSsl = function () { +Connection.prototype.requestSsl = function() { this.stream.write(serialize.requestSsl()) } -Connection.prototype.startup = function (config) { +Connection.prototype.startup = function(config) { this.stream.write(serialize.startup(config)) } -Connection.prototype.cancel = function (processID, secretKey) { +Connection.prototype.cancel = function(processID, secretKey) { this._send(serialize.cancel(processID, secretKey)) } -Connection.prototype.password = function (password) { +Connection.prototype.password = function(password) { this._send(serialize.password(password)) } -Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) { +Connection.prototype.sendSASLInitialResponseMessage = function(mechanism, initialResponse) { this._send(serialize.sendSASLInitialResponseMessage(mechanism, initialResponse)) } -Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) { +Connection.prototype.sendSCRAMClientFinalMessage = function(additionalData) { this._send(serialize.sendSCRAMClientFinalMessage(additionalData)) } -Connection.prototype._send = function (buffer) { +Connection.prototype._send = function(buffer) { if (!this.stream.writable) { return false } return this.stream.write(buffer) } -Connection.prototype.query = function (text) { +Connection.prototype.query = function(text) { this._send(serialize.query(text)) } // send parse message -Connection.prototype.parse = function (query) { +Connection.prototype.parse = function(query) { this._send(serialize.parse(query)) } // send bind message // "more" === true to buffer the message until flush() is called -Connection.prototype.bind = function (config) { +Connection.prototype.bind = function(config) { this._send(serialize.bind(config)) } // send execute message // "more" === true to buffer the message until flush() is called -Connection.prototype.execute = function (config) { +Connection.prototype.execute = function(config) { this._send(serialize.execute(config)) } const flushBuffer = serialize.flush() -Connection.prototype.flush = function () { +Connection.prototype.flush = function() { if (this.stream.writable) { this.stream.write(flushBuffer) } } const syncBuffer = serialize.sync() -Connection.prototype.sync = function () { +Connection.prototype.sync = function() { this._ending = true this._send(syncBuffer) this._send(flushBuffer) @@ -184,7 +184,7 @@ Connection.prototype.sync = function () { const endBuffer = serialize.end() -Connection.prototype.end = function () { +Connection.prototype.end = function() { // 0x58 = 'X' this._ending = true if (!this.stream.writable) { @@ -196,23 +196,23 @@ Connection.prototype.end = function () { }) } -Connection.prototype.close = function (msg) { +Connection.prototype.close = function(msg) { this._send(serialize.close(msg)) } -Connection.prototype.describe = function (msg) { +Connection.prototype.describe = function(msg) { this._send(serialize.describe(msg)) } -Connection.prototype.sendCopyFromChunk = function (chunk) { +Connection.prototype.sendCopyFromChunk = function(chunk) { this._send(serialize.copyData(chunk)) } -Connection.prototype.endCopyFrom = function () { +Connection.prototype.endCopyFrom = function() { this._send(serialize.copyDone()) } -Connection.prototype.sendCopyFail = function (msg) { +Connection.prototype.sendCopyFail = function(msg) { this._send(serialize.copyFail(msg)) } diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index b34e0df5f..4b0799574 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -13,7 +13,7 @@ var defaults = require('./defaults') var parse = require('pg-connection-string').parse // parses a connection string -var val = function (key, config, envVar) { +var val = function(key, config, envVar) { if (envVar === undefined) { envVar = process.env['PG' + key.toUpperCase()] } else if (envVar === false) { @@ -25,7 +25,7 @@ var val = function (key, config, envVar) { return config[key] || envVar || defaults[key] } -var useSsl = function () { +var useSsl = function() { switch (process.env.PGSSLMODE) { case 'disable': return false @@ -38,7 +38,7 @@ var useSsl = function () { return defaults.ssl } -var ConnectionParameters = function (config) { +var ConnectionParameters = function(config) { // if a string is passed, it is a raw connection string so we parse it into a config config = typeof config === 'string' ? parse(config) : config || {} @@ -98,18 +98,18 @@ var ConnectionParameters = function (config) { } // Convert arg to a string, surround in single quotes, and escape single quotes and backslashes -var quoteParamValue = function (value) { +var quoteParamValue = function(value) { return "'" + ('' + value).replace(/\\/g, '\\\\').replace(/'/g, "\\'") + "'" } -var add = function (params, config, paramName) { +var add = function(params, config, paramName) { var value = config[paramName] if (value !== undefined && value !== null) { params.push(paramName + '=' + quoteParamValue(value)) } } -ConnectionParameters.prototype.getLibpqConnectionString = function (cb) { +ConnectionParameters.prototype.getLibpqConnectionString = function(cb) { var params = [] add(params, this, 'user') add(params, this, 'password') @@ -140,7 +140,7 @@ ConnectionParameters.prototype.getLibpqConnectionString = function (cb) { if (this.client_encoding) { params.push('client_encoding=' + quoteParamValue(this.client_encoding)) } - dns.lookup(this.host, function (err, address) { + dns.lookup(this.host, function(err, address) { if (err) return cb(err, null) params.push('hostaddr=' + quoteParamValue(address)) return cb(null, params.join(' ')) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 243872c93..e5a9aad9a 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -16,7 +16,7 @@ var Reader = require('packet-reader') var TEXT_MODE = 0 var BINARY_MODE = 1 -var Connection = function (config) { +var Connection = function(config) { EventEmitter.call(this) config = config || {} this.stream = config.stream || new net.Socket() @@ -38,7 +38,7 @@ var Connection = function (config) { lengthPadding: -4, }) var self = this - this.on('newListener', function (eventName) { + this.on('newListener', function(eventName) { if (eventName === 'message') { self._emitMessage = true } @@ -47,7 +47,7 @@ var Connection = function (config) { util.inherits(Connection, EventEmitter) -Connection.prototype.connect = function (port, host) { +Connection.prototype.connect = function(port, host) { var self = this if (this.stream.readyState === 'closed') { @@ -56,14 +56,14 @@ Connection.prototype.connect = function (port, host) { this.emit('connect') } - this.stream.on('connect', function () { + this.stream.on('connect', function() { if (self._keepAlive) { self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis) } self.emit('connect') }) - const reportStreamError = function (error) { + const reportStreamError = function(error) { // errors about disconnections should be ignored during disconnect if (self._ending && (error.code === 'ECONNRESET' || error.code === 'EPIPE')) { return @@ -72,7 +72,7 @@ Connection.prototype.connect = function (port, host) { } this.stream.on('error', reportStreamError) - this.stream.on('close', function () { + this.stream.on('close', function() { self.emit('end') }) @@ -80,7 +80,7 @@ Connection.prototype.connect = function (port, host) { return this.attachListeners(this.stream) } - this.stream.once('data', function (buffer) { + this.stream.once('data', function(buffer) { var responseCode = buffer.toString('utf8') switch (responseCode) { case 'S': // Server supports SSL connections, continue with a secure connection @@ -110,9 +110,9 @@ Connection.prototype.connect = function (port, host) { }) } -Connection.prototype.attachListeners = function (stream) { +Connection.prototype.attachListeners = function(stream) { var self = this - stream.on('data', function (buff) { + stream.on('data', function(buff) { self._reader.addChunk(buff) var packet = self._reader.read() while (packet) { @@ -125,24 +125,30 @@ Connection.prototype.attachListeners = function (stream) { packet = self._reader.read() } }) - stream.on('end', function () { + stream.on('end', function() { self.emit('end') }) } -Connection.prototype.requestSsl = function () { - var bodyBuffer = this.writer.addInt16(0x04d2).addInt16(0x162f).flush() +Connection.prototype.requestSsl = function() { + var bodyBuffer = this.writer + .addInt16(0x04d2) + .addInt16(0x162f) + .flush() var length = bodyBuffer.length + 4 - var buffer = new Writer().addInt32(length).add(bodyBuffer).join() + var buffer = new Writer() + .addInt32(length) + .add(bodyBuffer) + .join() this.stream.write(buffer) } -Connection.prototype.startup = function (config) { +Connection.prototype.startup = function(config) { var writer = this.writer.addInt16(3).addInt16(0) - Object.keys(config).forEach(function (key) { + Object.keys(config).forEach(function(key) { var val = config[key] writer.addCString(key).addCString(val) }) @@ -154,39 +160,53 @@ Connection.prototype.startup = function (config) { var length = bodyBuffer.length + 4 - var buffer = new Writer().addInt32(length).add(bodyBuffer).join() + var buffer = new Writer() + .addInt32(length) + .add(bodyBuffer) + .join() this.stream.write(buffer) } -Connection.prototype.cancel = function (processID, secretKey) { - var bodyBuffer = this.writer.addInt16(1234).addInt16(5678).addInt32(processID).addInt32(secretKey).flush() +Connection.prototype.cancel = function(processID, secretKey) { + var bodyBuffer = this.writer + .addInt16(1234) + .addInt16(5678) + .addInt32(processID) + .addInt32(secretKey) + .flush() var length = bodyBuffer.length + 4 - var buffer = new Writer().addInt32(length).add(bodyBuffer).join() + var buffer = new Writer() + .addInt32(length) + .add(bodyBuffer) + .join() this.stream.write(buffer) } -Connection.prototype.password = function (password) { +Connection.prototype.password = function(password) { // 0x70 = 'p' this._send(0x70, this.writer.addCString(password)) } -Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) { +Connection.prototype.sendSASLInitialResponseMessage = function(mechanism, initialResponse) { // 0x70 = 'p' - this.writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse) + this.writer + .addCString(mechanism) + .addInt32(Buffer.byteLength(initialResponse)) + .addString(initialResponse) this._send(0x70) } -Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) { +Connection.prototype.sendSCRAMClientFinalMessage = function(additionalData) { // 0x70 = 'p' this.writer.addString(additionalData) this._send(0x70) } -Connection.prototype._send = function (code, more) { +Connection.prototype._send = function(code, more) { if (!this.stream.writable) { return false } @@ -197,14 +217,14 @@ Connection.prototype._send = function (code, more) { } } -Connection.prototype.query = function (text) { +Connection.prototype.query = function(text) { // 0x51 = Q this.stream.write(this.writer.addCString(text).flush(0x51)) } // send parse message // "more" === true to buffer the message until flush() is called -Connection.prototype.parse = function (query, more) { +Connection.prototype.parse = function(query, more) { // expect something like this: // { name: 'queryName', // text: 'select * from blah', @@ -236,7 +256,7 @@ Connection.prototype.parse = function (query, more) { // send bind message // "more" === true to buffer the message until flush() is called -Connection.prototype.bind = function (config, more) { +Connection.prototype.bind = function(config, more) { // normalize config config = config || {} config.portal = config.portal || '' @@ -283,7 +303,7 @@ Connection.prototype.bind = function (config, more) { // send execute message // "more" === true to buffer the message until flush() is called -Connection.prototype.execute = function (config, more) { +Connection.prototype.execute = function(config, more) { config = config || {} config.portal = config.portal || '' config.rows = config.rows || '' @@ -295,13 +315,13 @@ Connection.prototype.execute = function (config, more) { var emptyBuffer = Buffer.alloc(0) -Connection.prototype.flush = function () { +Connection.prototype.flush = function() { // 0x48 = 'H' this.writer.add(emptyBuffer) this._send(0x48) } -Connection.prototype.sync = function () { +Connection.prototype.sync = function() { // clear out any pending data in the writer this.writer.flush(0) @@ -312,7 +332,7 @@ Connection.prototype.sync = function () { const END_BUFFER = Buffer.from([0x58, 0x00, 0x00, 0x00, 0x04]) -Connection.prototype.end = function () { +Connection.prototype.end = function() { // 0x58 = 'X' this.writer.add(emptyBuffer) this._ending = true @@ -325,36 +345,36 @@ Connection.prototype.end = function () { }) } -Connection.prototype.close = function (msg, more) { +Connection.prototype.close = function(msg, more) { this.writer.addCString(msg.type + (msg.name || '')) this._send(0x43, more) } -Connection.prototype.describe = function (msg, more) { +Connection.prototype.describe = function(msg, more) { this.writer.addCString(msg.type + (msg.name || '')) this._send(0x44, more) } -Connection.prototype.sendCopyFromChunk = function (chunk) { +Connection.prototype.sendCopyFromChunk = function(chunk) { this.stream.write(this.writer.add(chunk).flush(0x64)) } -Connection.prototype.endCopyFrom = function () { +Connection.prototype.endCopyFrom = function() { this.stream.write(this.writer.add(emptyBuffer).flush(0x63)) } -Connection.prototype.sendCopyFail = function (msg) { +Connection.prototype.sendCopyFail = function(msg) { // this.stream.write(this.writer.add(emptyBuffer).flush(0x66)); this.writer.addCString(msg) this._send(0x66) } -var Message = function (name, length) { +var Message = function(name, length) { this.name = name this.length = length } -Connection.prototype.parseMessage = function (buffer) { +Connection.prototype.parseMessage = function(buffer) { this.offset = 0 var length = buffer.length + 4 switch (this._reader.header) { @@ -423,7 +443,7 @@ Connection.prototype.parseMessage = function (buffer) { } } -Connection.prototype.parseR = function (buffer, length) { +Connection.prototype.parseR = function(buffer, length) { var code = this.parseInt32(buffer) var msg = new Message('authenticationOk', length) @@ -474,27 +494,27 @@ Connection.prototype.parseR = function (buffer, length) { throw new Error('Unknown authenticationOk message type' + util.inspect(msg)) } -Connection.prototype.parseS = function (buffer, length) { +Connection.prototype.parseS = function(buffer, length) { var msg = new Message('parameterStatus', length) msg.parameterName = this.parseCString(buffer) msg.parameterValue = this.parseCString(buffer) return msg } -Connection.prototype.parseK = function (buffer, length) { +Connection.prototype.parseK = function(buffer, length) { var msg = new Message('backendKeyData', length) msg.processID = this.parseInt32(buffer) msg.secretKey = this.parseInt32(buffer) return msg } -Connection.prototype.parseC = function (buffer, length) { +Connection.prototype.parseC = function(buffer, length) { var msg = new Message('commandComplete', length) msg.text = this.parseCString(buffer) return msg } -Connection.prototype.parseZ = function (buffer, length) { +Connection.prototype.parseZ = function(buffer, length) { var msg = new Message('readyForQuery', length) msg.name = 'readyForQuery' msg.status = this.readString(buffer, 1) @@ -502,7 +522,7 @@ Connection.prototype.parseZ = function (buffer, length) { } var ROW_DESCRIPTION = 'rowDescription' -Connection.prototype.parseT = function (buffer, length) { +Connection.prototype.parseT = function(buffer, length) { var msg = new Message(ROW_DESCRIPTION, length) msg.fieldCount = this.parseInt16(buffer) var fields = [] @@ -513,7 +533,7 @@ Connection.prototype.parseT = function (buffer, length) { return msg } -var Field = function () { +var Field = function() { this.name = null this.tableID = null this.columnID = null @@ -525,7 +545,7 @@ var Field = function () { var FORMAT_TEXT = 'text' var FORMAT_BINARY = 'binary' -Connection.prototype.parseField = function (buffer) { +Connection.prototype.parseField = function(buffer) { var field = new Field() field.name = this.parseCString(buffer) field.tableID = this.parseInt32(buffer) @@ -544,7 +564,7 @@ Connection.prototype.parseField = function (buffer) { } var DATA_ROW = 'dataRow' -var DataRowMessage = function (length, fieldCount) { +var DataRowMessage = function(length, fieldCount) { this.name = DATA_ROW this.length = length this.fieldCount = fieldCount @@ -552,7 +572,7 @@ var DataRowMessage = function (length, fieldCount) { } // extremely hot-path code -Connection.prototype.parseD = function (buffer, length) { +Connection.prototype.parseD = function(buffer, length) { var fieldCount = this.parseInt16(buffer) var msg = new DataRowMessage(length, fieldCount) for (var i = 0; i < fieldCount; i++) { @@ -562,7 +582,7 @@ Connection.prototype.parseD = function (buffer, length) { } // extremely hot-path code -Connection.prototype._readValue = function (buffer) { +Connection.prototype._readValue = function(buffer) { var length = this.parseInt32(buffer) if (length === -1) return null if (this._mode === TEXT_MODE) { @@ -572,7 +592,7 @@ Connection.prototype._readValue = function (buffer) { } // parses error -Connection.prototype.parseE = function (buffer, length, isNotice) { +Connection.prototype.parseE = function(buffer, length, isNotice) { var fields = {} var fieldType = this.readString(buffer, 1) while (fieldType !== '\0') { @@ -607,13 +627,13 @@ Connection.prototype.parseE = function (buffer, length, isNotice) { } // same thing, different name -Connection.prototype.parseN = function (buffer, length) { +Connection.prototype.parseN = function(buffer, length) { var msg = this.parseE(buffer, length, true) msg.name = 'notice' return msg } -Connection.prototype.parseA = function (buffer, length) { +Connection.prototype.parseA = function(buffer, length) { var msg = new Message('notification', length) msg.processId = this.parseInt32(buffer) msg.channel = this.parseCString(buffer) @@ -621,17 +641,17 @@ Connection.prototype.parseA = function (buffer, length) { return msg } -Connection.prototype.parseG = function (buffer, length) { +Connection.prototype.parseG = function(buffer, length) { var msg = new Message('copyInResponse', length) return this.parseGH(buffer, msg) } -Connection.prototype.parseH = function (buffer, length) { +Connection.prototype.parseH = function(buffer, length) { var msg = new Message('copyOutResponse', length) return this.parseGH(buffer, msg) } -Connection.prototype.parseGH = function (buffer, msg) { +Connection.prototype.parseGH = function(buffer, msg) { var isBinary = buffer[this.offset] !== 0 this.offset++ msg.binary = isBinary @@ -643,33 +663,33 @@ Connection.prototype.parseGH = function (buffer, msg) { return msg } -Connection.prototype.parsed = function (buffer, length) { +Connection.prototype.parsed = function(buffer, length) { var msg = new Message('copyData', length) msg.chunk = this.readBytes(buffer, msg.length - 4) return msg } -Connection.prototype.parseInt32 = function (buffer) { +Connection.prototype.parseInt32 = function(buffer) { var value = buffer.readInt32BE(this.offset) this.offset += 4 return value } -Connection.prototype.parseInt16 = function (buffer) { +Connection.prototype.parseInt16 = function(buffer) { var value = buffer.readInt16BE(this.offset) this.offset += 2 return value } -Connection.prototype.readString = function (buffer, length) { +Connection.prototype.readString = function(buffer, length) { return buffer.toString(this.encoding, this.offset, (this.offset += length)) } -Connection.prototype.readBytes = function (buffer, length) { +Connection.prototype.readBytes = function(buffer, length) { return buffer.slice(this.offset, (this.offset += length)) } -Connection.prototype.parseCString = function (buffer) { +Connection.prototype.parseCString = function(buffer) { var start = this.offset var end = buffer.indexOf(0, start) this.offset = end + 1 diff --git a/packages/pg/lib/defaults.js b/packages/pg/lib/defaults.js index 394216680..47e510337 100644 --- a/packages/pg/lib/defaults.js +++ b/packages/pg/lib/defaults.js @@ -79,7 +79,7 @@ var parseBigInteger = pgTypes.getTypeParser(20, 'text') var parseBigIntegerArray = pgTypes.getTypeParser(1016, 'text') // parse int8 so you can get your count values as actual numbers -module.exports.__defineSetter__('parseInt8', function (val) { +module.exports.__defineSetter__('parseInt8', function(val) { pgTypes.setTypeParser(20, 'text', val ? pgTypes.getTypeParser(23, 'text') : parseBigInteger) pgTypes.setTypeParser(1016, 'text', val ? pgTypes.getTypeParser(1007, 'text') : parseBigIntegerArray) }) diff --git a/packages/pg/lib/index.js b/packages/pg/lib/index.js index 975175cd4..de171620e 100644 --- a/packages/pg/lib/index.js +++ b/packages/pg/lib/index.js @@ -20,7 +20,7 @@ const poolFactory = (Client) => { } } -var PG = function (clientConstructor) { +var PG = function(clientConstructor) { this.defaults = defaults this.Client = clientConstructor this.Query = this.Client.Query diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index f45546151..883aca005 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -22,7 +22,7 @@ assert(semver.gte(Native.version, pkg.minNativeVersion), msg) var NativeQuery = require('./query') -var Client = (module.exports = function (config) { +var Client = (module.exports = function(config) { EventEmitter.call(this) config = config || {} @@ -64,7 +64,7 @@ Client.Query = NativeQuery util.inherits(Client, EventEmitter) -Client.prototype._errorAllQueries = function (err) { +Client.prototype._errorAllQueries = function(err) { const enqueueError = (query) => { process.nextTick(() => { query.native = this.native @@ -84,7 +84,7 @@ Client.prototype._errorAllQueries = function (err) { // connect to the backend // pass an optional callback to be called once connected // or with an error if there was a connection error -Client.prototype._connect = function (cb) { +Client.prototype._connect = function(cb) { var self = this if (this._connecting) { @@ -94,9 +94,9 @@ Client.prototype._connect = function (cb) { this._connecting = true - this.connectionParameters.getLibpqConnectionString(function (err, conString) { + this.connectionParameters.getLibpqConnectionString(function(err, conString) { if (err) return cb(err) - self.native.connect(conString, function (err) { + self.native.connect(conString, function(err) { if (err) { self.native.end() return cb(err) @@ -106,13 +106,13 @@ Client.prototype._connect = function (cb) { self._connected = true // handle connection errors from the native layer - self.native.on('error', function (err) { + self.native.on('error', function(err) { self._queryable = false self._errorAllQueries(err) self.emit('error', err) }) - self.native.on('notification', function (msg) { + self.native.on('notification', function(msg) { self.emit('notification', { channel: msg.relname, payload: msg.extra, @@ -128,7 +128,7 @@ Client.prototype._connect = function (cb) { }) } -Client.prototype.connect = function (callback) { +Client.prototype.connect = function(callback) { if (callback) { this._connect(callback) return @@ -155,7 +155,7 @@ Client.prototype.connect = function (callback) { // optional string name to name & cache the query plan // optional string rowMode = 'array' for an array of results // } -Client.prototype.query = function (config, values, callback) { +Client.prototype.query = function(config, values, callback) { var query var result var readTimeout @@ -237,7 +237,7 @@ Client.prototype.query = function (config, values, callback) { } // disconnect from the backend server -Client.prototype.end = function (cb) { +Client.prototype.end = function(cb) { var self = this this._ending = true @@ -247,11 +247,11 @@ Client.prototype.end = function (cb) { } var result if (!cb) { - result = new this._Promise(function (resolve, reject) { + result = new this._Promise(function(resolve, reject) { cb = (err) => (err ? reject(err) : resolve()) }) } - this.native.end(function () { + this.native.end(function() { self._errorAllQueries(new Error('Connection terminated')) process.nextTick(() => { @@ -262,11 +262,11 @@ Client.prototype.end = function (cb) { return result } -Client.prototype._hasActiveQuery = function () { +Client.prototype._hasActiveQuery = function() { return this._activeQuery && this._activeQuery.state !== 'error' && this._activeQuery.state !== 'end' } -Client.prototype._pulseQueryQueue = function (initialConnection) { +Client.prototype._pulseQueryQueue = function(initialConnection) { if (!this._connected) { return } @@ -283,24 +283,24 @@ Client.prototype._pulseQueryQueue = function (initialConnection) { this._activeQuery = query query.submit(this) var self = this - query.once('_done', function () { + query.once('_done', function() { self._pulseQueryQueue() }) } // attempt to cancel an in-progress query -Client.prototype.cancel = function (query) { +Client.prototype.cancel = function(query) { if (this._activeQuery === query) { - this.native.cancel(function () {}) + this.native.cancel(function() {}) } else if (this._queryQueue.indexOf(query) !== -1) { this._queryQueue.splice(this._queryQueue.indexOf(query), 1) } } -Client.prototype.setTypeParser = function (oid, format, parseFn) { +Client.prototype.setTypeParser = function(oid, format, parseFn) { return this._types.setTypeParser(oid, format, parseFn) } -Client.prototype.getTypeParser = function (oid, format) { +Client.prototype.getTypeParser = function(oid, format) { return this._types.getTypeParser(oid, format) } diff --git a/packages/pg/lib/native/query.js b/packages/pg/lib/native/query.js index de443489a..c2e3ed446 100644 --- a/packages/pg/lib/native/query.js +++ b/packages/pg/lib/native/query.js @@ -11,7 +11,7 @@ var EventEmitter = require('events').EventEmitter var util = require('util') var utils = require('../utils') -var NativeQuery = (module.exports = function (config, values, callback) { +var NativeQuery = (module.exports = function(config, values, callback) { EventEmitter.call(this) config = utils.normalizeQueryConfig(config, values, callback) this.text = config.text @@ -29,7 +29,7 @@ var NativeQuery = (module.exports = function (config, values, callback) { this._emitRowEvents = false this.on( 'newListener', - function (event) { + function(event) { if (event === 'row') this._emitRowEvents = true }.bind(this) ) @@ -53,7 +53,7 @@ var errorFieldMap = { sourceFunction: 'routine', } -NativeQuery.prototype.handleError = function (err) { +NativeQuery.prototype.handleError = function(err) { // copy pq error fields into the error object var fields = this.native.pq.resultErrorFields() if (fields) { @@ -70,18 +70,18 @@ NativeQuery.prototype.handleError = function (err) { this.state = 'error' } -NativeQuery.prototype.then = function (onSuccess, onFailure) { +NativeQuery.prototype.then = function(onSuccess, onFailure) { return this._getPromise().then(onSuccess, onFailure) } -NativeQuery.prototype.catch = function (callback) { +NativeQuery.prototype.catch = function(callback) { return this._getPromise().catch(callback) } -NativeQuery.prototype._getPromise = function () { +NativeQuery.prototype._getPromise = function() { if (this._promise) return this._promise this._promise = new Promise( - function (resolve, reject) { + function(resolve, reject) { this._once('end', resolve) this._once('error', reject) }.bind(this) @@ -89,15 +89,15 @@ NativeQuery.prototype._getPromise = function () { return this._promise } -NativeQuery.prototype.submit = function (client) { +NativeQuery.prototype.submit = function(client) { this.state = 'running' var self = this this.native = client.native client.native.arrayMode = this._arrayMode - var after = function (err, rows, results) { + var after = function(err, rows, results) { client.native.arrayMode = false - setImmediate(function () { + setImmediate(function() { self.emit('_done') }) @@ -115,7 +115,7 @@ NativeQuery.prototype.submit = function (client) { }) }) } else { - rows.forEach(function (row) { + rows.forEach(function(row) { self.emit('row', row, results) }) } @@ -154,7 +154,7 @@ NativeQuery.prototype.submit = function (client) { return client.native.execute(this.name, values, after) } // plan the named query the first time, then execute it - return client.native.prepare(this.name, this.text, values.length, function (err) { + return client.native.prepare(this.name, this.text, values.length, function(err) { if (err) return after(err) client.namedQueries[self.name] = self.text return self.native.execute(self.name, values, after) diff --git a/packages/pg/lib/result.js b/packages/pg/lib/result.js index 233455b06..615a06d0c 100644 --- a/packages/pg/lib/result.js +++ b/packages/pg/lib/result.js @@ -12,7 +12,7 @@ var types = require('pg-types') // result object returned from query // in the 'end' event and also // passed as second argument to provided callback -var Result = function (rowMode, types) { +var Result = function(rowMode, types) { this.command = null this.rowCount = null this.oid = null @@ -30,7 +30,7 @@ var Result = function (rowMode, types) { var matchRegexp = /^([A-Za-z]+)(?: (\d+))?(?: (\d+))?/ // adds a command complete message -Result.prototype.addCommandComplete = function (msg) { +Result.prototype.addCommandComplete = function(msg) { var match if (msg.text) { // pure javascript @@ -52,7 +52,7 @@ Result.prototype.addCommandComplete = function (msg) { } } -Result.prototype._parseRowAsArray = function (rowData) { +Result.prototype._parseRowAsArray = function(rowData) { var row = new Array(rowData.length) for (var i = 0, len = rowData.length; i < len; i++) { var rawValue = rowData[i] @@ -65,7 +65,7 @@ Result.prototype._parseRowAsArray = function (rowData) { return row } -Result.prototype.parseRow = function (rowData) { +Result.prototype.parseRow = function(rowData) { var row = {} for (var i = 0, len = rowData.length; i < len; i++) { var rawValue = rowData[i] @@ -79,11 +79,11 @@ Result.prototype.parseRow = function (rowData) { return row } -Result.prototype.addRow = function (row) { +Result.prototype.addRow = function(row) { this.rows.push(row) } -Result.prototype.addFields = function (fieldDescriptions) { +Result.prototype.addFields = function(fieldDescriptions) { // clears field definitions // multiple query statements in 1 action can result in multiple sets // of rowDescriptions...eg: 'select NOW(); select 1::int;' diff --git a/packages/pg/lib/sasl.js b/packages/pg/lib/sasl.js index 22abf5c4a..8308a489d 100644 --- a/packages/pg/lib/sasl.js +++ b/packages/pg/lib/sasl.js @@ -32,7 +32,10 @@ function continueSession(session, password, serverData) { var saltedPassword = Hi(password, saltBytes, sv.iteration) var clientKey = createHMAC(saltedPassword, 'Client Key') - var storedKey = crypto.createHash('sha256').update(clientKey).digest() + var storedKey = crypto + .createHash('sha256') + .update(clientKey) + .digest() var clientFirstMessageBare = 'n=*,r=' + session.clientNonce var serverFirstMessage = 'r=' + sv.nonce + ',s=' + sv.salt + ',i=' + sv.iteration @@ -62,7 +65,7 @@ function finalizeSession(session, serverData) { String(serverData) .split(',') - .forEach(function (part) { + .forEach(function(part) { switch (part[0]) { case 'v': serverSignature = part.substr(2) @@ -80,7 +83,7 @@ function extractVariablesFromFirstServerMessage(data) { String(data) .split(',') - .forEach(function (part) { + .forEach(function(part) { switch (part[0]) { case 'r': nonce = part.substr(2) @@ -130,7 +133,10 @@ function xorBuffers(a, b) { } function createHMAC(key, msg) { - return crypto.createHmac('sha256', key).update(msg).digest() + return crypto + .createHmac('sha256', key) + .update(msg) + .digest() } function Hi(password, saltBytes, iterations) { diff --git a/packages/pg/lib/type-overrides.js b/packages/pg/lib/type-overrides.js index 63bfc83e1..88b5b93c2 100644 --- a/packages/pg/lib/type-overrides.js +++ b/packages/pg/lib/type-overrides.js @@ -15,7 +15,7 @@ function TypeOverrides(userTypes) { this.binary = {} } -TypeOverrides.prototype.getOverrides = function (format) { +TypeOverrides.prototype.getOverrides = function(format) { switch (format) { case 'text': return this.text @@ -26,7 +26,7 @@ TypeOverrides.prototype.getOverrides = function (format) { } } -TypeOverrides.prototype.setTypeParser = function (oid, format, parseFn) { +TypeOverrides.prototype.setTypeParser = function(oid, format, parseFn) { if (typeof format === 'function') { parseFn = format format = 'text' @@ -34,7 +34,7 @@ TypeOverrides.prototype.setTypeParser = function (oid, format, parseFn) { this.getOverrides(format)[oid] = parseFn } -TypeOverrides.prototype.getTypeParser = function (oid, format) { +TypeOverrides.prototype.getTypeParser = function(oid, format) { format = format || 'text' return this.getOverrides(format)[oid] || this._types.getTypeParser(oid, format) } diff --git a/packages/pg/lib/utils.js b/packages/pg/lib/utils.js index f6da81f47..f4e29f8ef 100644 --- a/packages/pg/lib/utils.js +++ b/packages/pg/lib/utils.js @@ -44,7 +44,7 @@ function arrayString(val) { // to their 'raw' counterparts for use as a postgres parameter // note: you can override this function to provide your own conversion mechanism // for complex types, etc... -var prepareValue = function (val, seen) { +var prepareValue = function(val, seen) { if (val instanceof Buffer) { return val } @@ -170,12 +170,15 @@ function normalizeQueryConfig(config, values, callback) { return config } -const md5 = function (string) { - return crypto.createHash('md5').update(string, 'utf-8').digest('hex') +const md5 = function(string) { + return crypto + .createHash('md5') + .update(string, 'utf-8') + .digest('hex') } // See AuthenticationMD5Password at https://www.postgresql.org/docs/current/static/protocol-flow.html -const postgresMd5PasswordHash = function (user, password, salt) { +const postgresMd5PasswordHash = function(user, password, salt) { var inner = md5(password + user) var outer = md5(Buffer.concat([Buffer.from(inner), salt])) return 'md5' + outer diff --git a/packages/pg/script/dump-db-types.js b/packages/pg/script/dump-db-types.js index 08fe4dc98..d1e7f7328 100644 --- a/packages/pg/script/dump-db-types.js +++ b/packages/pg/script/dump-db-types.js @@ -4,14 +4,14 @@ var args = require(__dirname + '/../test/cli') var queries = ['select CURRENT_TIMESTAMP', "select interval '1 day' + interval '1 hour'", "select TIMESTAMP 'today'"] -queries.forEach(function (query) { +queries.forEach(function(query) { var client = new pg.Client({ user: args.user, database: args.database, password: args.password, }) client.connect() - client.query(query).on('row', function (row) { + client.query(query).on('row', function(row) { console.log(row) client.end() }) diff --git a/packages/pg/script/list-db-types.js b/packages/pg/script/list-db-types.js index c3e75c1ae..dfe527251 100644 --- a/packages/pg/script/list-db-types.js +++ b/packages/pg/script/list-db-types.js @@ -3,7 +3,7 @@ var helper = require(__dirname + '/../test/integration/test-helper') var pg = helper.pg pg.connect( helper.config, - assert.success(function (client) { + assert.success(function(client) { var query = client.query("select oid, typname from pg_type where typtype = 'b' order by oid") query.on('row', console.log) }) diff --git a/packages/pg/test/buffer-list.js b/packages/pg/test/buffer-list.js index aea529c10..ca54e8ed6 100644 --- a/packages/pg/test/buffer-list.js +++ b/packages/pg/test/buffer-list.js @@ -1,32 +1,32 @@ 'use strict' -global.BufferList = function () { +global.BufferList = function() { this.buffers = [] } var p = BufferList.prototype -p.add = function (buffer, front) { +p.add = function(buffer, front) { this.buffers[front ? 'unshift' : 'push'](buffer) return this } -p.addInt16 = function (val, front) { +p.addInt16 = function(val, front) { return this.add(Buffer.from([val >>> 8, val >>> 0]), front) } -p.getByteLength = function (initial) { - return this.buffers.reduce(function (previous, current) { +p.getByteLength = function(initial) { + return this.buffers.reduce(function(previous, current) { return previous + current.length }, initial || 0) } -p.addInt32 = function (val, first) { +p.addInt32 = function(val, first) { return this.add( Buffer.from([(val >>> 24) & 0xff, (val >>> 16) & 0xff, (val >>> 8) & 0xff, (val >>> 0) & 0xff]), first ) } -p.addCString = function (val, front) { +p.addCString = function(val, front) { var len = Buffer.byteLength(val) var buffer = Buffer.alloc(len + 1) buffer.write(val) @@ -34,18 +34,18 @@ p.addCString = function (val, front) { return this.add(buffer, front) } -p.addString = function (val, front) { +p.addString = function(val, front) { var len = Buffer.byteLength(val) var buffer = Buffer.alloc(len) buffer.write(val) return this.add(buffer, front) } -p.addChar = function (char, first) { +p.addChar = function(char, first) { return this.add(Buffer.from(char, 'utf8'), first) } -p.join = function (appendLength, char) { +p.join = function(appendLength, char) { var length = this.getByteLength() if (appendLength) { this.addInt32(length + 4, true) @@ -57,14 +57,14 @@ p.join = function (appendLength, char) { } var result = Buffer.alloc(length) var index = 0 - this.buffers.forEach(function (buffer) { + this.buffers.forEach(function(buffer) { buffer.copy(result, index, 0) index += buffer.length }) return result } -BufferList.concat = function () { +BufferList.concat = function() { var total = new BufferList() for (var i = 0; i < arguments.length; i++) { total.add(arguments[i]) diff --git a/packages/pg/test/integration/client/api-tests.js b/packages/pg/test/integration/client/api-tests.js index a957c32ae..2abf7d6b8 100644 --- a/packages/pg/test/integration/client/api-tests.js +++ b/packages/pg/test/integration/client/api-tests.js @@ -4,10 +4,10 @@ var pg = helper.pg var suite = new helper.Suite() -suite.test('null and undefined are both inserted as NULL', function (done) { +suite.test('null and undefined are both inserted as NULL', function(done) { const pool = new pg.Pool() pool.connect( - assert.calls(function (err, client, release) { + assert.calls(function(err, client, release) { assert(!err) client.query('CREATE TEMP TABLE my_nulls(a varchar(1), b varchar(1), c integer, d integer, e date, f date)') client.query('INSERT INTO my_nulls(a,b,c,d,e,f) VALUES ($1,$2,$3,$4,$5,$6)', [ @@ -20,7 +20,7 @@ suite.test('null and undefined are both inserted as NULL', function (done) { ]) client.query( 'SELECT * FROM my_nulls', - assert.calls(function (err, result) { + assert.calls(function(err, result) { console.log(err) assert.ifError(err) assert.equal(result.rows.length, 1) @@ -41,7 +41,7 @@ suite.test('null and undefined are both inserted as NULL', function (done) { suite.test('pool callback behavior', (done) => { // test weird callback behavior with node-pool const pool = new pg.Pool() - pool.connect(function (err) { + pool.connect(function(err) { assert(!err) arguments[1].emit('drain') arguments[2]() @@ -54,7 +54,7 @@ suite.test('query timeout', (cb) => { pool.connect().then((client) => { client.query( 'SELECT pg_sleep(2)', - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(err) assert(err.message === 'Query read timeout') client.release() @@ -69,14 +69,14 @@ suite.test('query recover from timeout', (cb) => { pool.connect().then((client) => { client.query( 'SELECT pg_sleep(20)', - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(err) assert(err.message === 'Query read timeout') client.release(err) pool.connect().then((client) => { client.query( 'SELECT 1', - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) client.release(err) pool.end(cb) @@ -93,7 +93,7 @@ suite.test('query no timeout', (cb) => { pool.connect().then((client) => { client.query( 'SELECT pg_sleep(1)', - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) client.release() pool.end(cb) @@ -135,21 +135,21 @@ suite.test('callback API', (done) => { }) }) -suite.test('executing nested queries', function (done) { +suite.test('executing nested queries', function(done) { const pool = new pg.Pool() pool.connect( - assert.calls(function (err, client, release) { + assert.calls(function(err, client, release) { assert(!err) client.query( 'select now as now from NOW()', - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert.equal(new Date().getYear(), result.rows[0].now.getYear()) client.query( 'select now as now_again FROM NOW()', - assert.calls(function () { + assert.calls(function() { client.query( 'select * FROM NOW()', - assert.calls(function () { + assert.calls(function() { assert.ok('all queries hit') release() pool.end(done) @@ -163,25 +163,25 @@ suite.test('executing nested queries', function (done) { ) }) -suite.test('raises error if cannot connect', function () { +suite.test('raises error if cannot connect', function() { var connectionString = 'pg://sfalsdkf:asdf@localhost/ieieie' const pool = new pg.Pool({ connectionString: connectionString }) pool.connect( - assert.calls(function (err, client, done) { + assert.calls(function(err, client, done) { assert.ok(err, 'should have raised an error') done() }) ) }) -suite.test('query errors are handled and do not bubble if callback is provided', function (done) { +suite.test('query errors are handled and do not bubble if callback is provided', function(done) { const pool = new pg.Pool() pool.connect( - assert.calls(function (err, client, release) { + assert.calls(function(err, client, release) { assert(!err) client.query( 'SELECT OISDJF FROM LEIWLISEJLSE', - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert.ok(err) release() pool.end(done) @@ -191,10 +191,10 @@ suite.test('query errors are handled and do not bubble if callback is provided', ) }) -suite.test('callback is fired once and only once', function (done) { +suite.test('callback is fired once and only once', function(done) { const pool = new pg.Pool() pool.connect( - assert.calls(function (err, client, release) { + assert.calls(function(err, client, release) { assert(!err) client.query('CREATE TEMP TABLE boom(name varchar(10))') var callCount = 0 @@ -204,7 +204,7 @@ suite.test('callback is fired once and only once', function (done) { "INSERT INTO boom(name) VALUES('boom')", "INSERT INTO boom(name) VALUES('zoom')", ].join(';'), - function (err, callback) { + function(err, callback) { assert.equal(callCount++, 0, 'Call count should be 0. More means this callback fired more than once.') release() pool.end(done) @@ -214,17 +214,17 @@ suite.test('callback is fired once and only once', function (done) { ) }) -suite.test('can provide callback and config object', function (done) { +suite.test('can provide callback and config object', function(done) { const pool = new pg.Pool() pool.connect( - assert.calls(function (err, client, release) { + assert.calls(function(err, client, release) { assert(!err) client.query( { name: 'boom', text: 'select NOW()', }, - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) assert.equal(result.rows[0].now.getYear(), new Date().getYear()) release() @@ -235,10 +235,10 @@ suite.test('can provide callback and config object', function (done) { ) }) -suite.test('can provide callback and config and parameters', function (done) { +suite.test('can provide callback and config and parameters', function(done) { const pool = new pg.Pool() pool.connect( - assert.calls(function (err, client, release) { + assert.calls(function(err, client, release) { assert(!err) var config = { text: 'select $1::text as val', @@ -246,7 +246,7 @@ suite.test('can provide callback and config and parameters', function (done) { client.query( config, ['hi'], - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) assert.equal(result.rows.length, 1) assert.equal(result.rows[0].val, 'hi') diff --git a/packages/pg/test/integration/client/appname-tests.js b/packages/pg/test/integration/client/appname-tests.js index dd8de6b39..fc773af41 100644 --- a/packages/pg/test/integration/client/appname-tests.js +++ b/packages/pg/test/integration/client/appname-tests.js @@ -13,10 +13,10 @@ function getConInfo(override) { function getAppName(conf, cb) { var client = new Client(conf) client.connect( - assert.success(function () { + assert.success(function() { client.query( 'SHOW application_name', - assert.success(function (res) { + assert.success(function(res) { var appName = res.rows[0].application_name cb(appName) client.end() @@ -26,50 +26,50 @@ function getAppName(conf, cb) { ) } -suite.test('No default appliation_name ', function (done) { +suite.test('No default appliation_name ', function(done) { var conf = getConInfo() - getAppName({}, function (res) { + getAppName({}, function(res) { assert.strictEqual(res, '') done() }) }) -suite.test('fallback_application_name is used', function (done) { +suite.test('fallback_application_name is used', function(done) { var fbAppName = 'this is my app' var conf = getConInfo({ fallback_application_name: fbAppName, }) - getAppName(conf, function (res) { + getAppName(conf, function(res) { assert.strictEqual(res, fbAppName) done() }) }) -suite.test('application_name is used', function (done) { +suite.test('application_name is used', function(done) { var appName = 'some wired !@#$% application_name' var conf = getConInfo({ application_name: appName, }) - getAppName(conf, function (res) { + getAppName(conf, function(res) { assert.strictEqual(res, appName) done() }) }) -suite.test('application_name has precedence over fallback_application_name', function (done) { +suite.test('application_name has precedence over fallback_application_name', function(done) { var appName = 'some wired !@#$% application_name' var fbAppName = 'some other strange $$test$$ appname' var conf = getConInfo({ application_name: appName, fallback_application_name: fbAppName, }) - getAppName(conf, function (res) { + getAppName(conf, function(res) { assert.strictEqual(res, appName) done() }) }) -suite.test('application_name from connection string', function (done) { +suite.test('application_name from connection string', function(done) { var appName = 'my app' var conParams = require(__dirname + '/../../../lib/connection-parameters') var conf @@ -78,7 +78,7 @@ suite.test('application_name from connection string', function (done) { } else { conf = 'postgres://?application_name=' + appName } - getAppName(conf, function (res) { + getAppName(conf, function(res) { assert.strictEqual(res, appName) done() }) @@ -86,9 +86,9 @@ suite.test('application_name from connection string', function (done) { // TODO: make the test work for native client too if (!helper.args.native) { - suite.test('application_name is read from the env', function (done) { + suite.test('application_name is read from the env', function(done) { var appName = (process.env.PGAPPNAME = 'testest') - getAppName({}, function (res) { + getAppName({}, function(res) { delete process.env.PGAPPNAME assert.strictEqual(res, appName) done() diff --git a/packages/pg/test/integration/client/array-tests.js b/packages/pg/test/integration/client/array-tests.js index f5e62b032..dfeec66c3 100644 --- a/packages/pg/test/integration/client/array-tests.js +++ b/packages/pg/test/integration/client/array-tests.js @@ -7,14 +7,14 @@ var suite = new helper.Suite() const pool = new pg.Pool() pool.connect( - assert.calls(function (err, client, release) { + assert.calls(function(err, client, release) { assert(!err) - suite.test('nulls', function (done) { + suite.test('nulls', function(done) { client.query( 'SELECT $1::text[] as array', [[null]], - assert.success(function (result) { + assert.success(function(result) { var array = result.rows[0].array assert.lengthIs(array, 1) assert.isNull(array[0]) @@ -23,7 +23,7 @@ pool.connect( ) }) - suite.test('elements containing JSON-escaped characters', function (done) { + suite.test('elements containing JSON-escaped characters', function(done) { var param = '\\"\\"' for (var i = 1; i <= 0x1f; i++) { @@ -33,7 +33,7 @@ pool.connect( client.query( 'SELECT $1::text[] as array', [[param]], - assert.success(function (result) { + assert.success(function(result) { var array = result.rows[0].array assert.lengthIs(array, 1) assert.equal(array[0], param) @@ -45,17 +45,17 @@ pool.connect( suite.test('cleanup', () => release()) pool.connect( - assert.calls(function (err, client, release) { + assert.calls(function(err, client, release) { assert(!err) client.query('CREATE TEMP TABLE why(names text[], numbors integer[])') client .query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')) .on('error', console.log) - suite.test('numbers', function (done) { + suite.test('numbers', function(done) { // client.connection.on('message', console.log) client.query( 'SELECT numbors FROM why', - assert.success(function (result) { + assert.success(function(result) { assert.lengthIs(result.rows[0].numbors, 3) assert.equal(result.rows[0].numbors[0], 1) assert.equal(result.rows[0].numbors[1], 2) @@ -65,10 +65,10 @@ pool.connect( ) }) - suite.test('parses string arrays', function (done) { + suite.test('parses string arrays', function(done) { client.query( 'SELECT names FROM why', - assert.success(function (result) { + assert.success(function(result) { var names = result.rows[0].names assert.lengthIs(names, 3) assert.equal(names[0], 'aaron') @@ -79,10 +79,10 @@ pool.connect( ) }) - suite.test('empty array', function (done) { + suite.test('empty array', function(done) { client.query( "SELECT '{}'::text[] as names", - assert.success(function (result) { + assert.success(function(result) { var names = result.rows[0].names assert.lengthIs(names, 0) done() @@ -90,10 +90,10 @@ pool.connect( ) }) - suite.test('element containing comma', function (done) { + suite.test('element containing comma', function(done) { client.query( 'SELECT \'{"joe,bob",jim}\'::text[] as names', - assert.success(function (result) { + assert.success(function(result) { var names = result.rows[0].names assert.lengthIs(names, 2) assert.equal(names[0], 'joe,bob') @@ -103,10 +103,10 @@ pool.connect( ) }) - suite.test('bracket in quotes', function (done) { + suite.test('bracket in quotes', function(done) { client.query( 'SELECT \'{"{","}"}\'::text[] as names', - assert.success(function (result) { + assert.success(function(result) { var names = result.rows[0].names assert.lengthIs(names, 2) assert.equal(names[0], '{') @@ -116,10 +116,10 @@ pool.connect( ) }) - suite.test('null value', function (done) { + suite.test('null value', function(done) { client.query( 'SELECT \'{joe,null,bob,"NULL"}\'::text[] as names', - assert.success(function (result) { + assert.success(function(result) { var names = result.rows[0].names assert.lengthIs(names, 4) assert.equal(names[0], 'joe') @@ -131,10 +131,10 @@ pool.connect( ) }) - suite.test('element containing quote char', function (done) { + suite.test('element containing quote char', function(done) { client.query( "SELECT ARRAY['joe''', 'jim', 'bob\"'] AS names", - assert.success(function (result) { + assert.success(function(result) { var names = result.rows[0].names assert.lengthIs(names, 3) assert.equal(names[0], "joe'") @@ -145,10 +145,10 @@ pool.connect( ) }) - suite.test('nested array', function (done) { + suite.test('nested array', function(done) { client.query( "SELECT '{{1,joe},{2,bob}}'::text[] as names", - assert.success(function (result) { + assert.success(function(result) { var names = result.rows[0].names assert.lengthIs(names, 2) @@ -164,10 +164,10 @@ pool.connect( ) }) - suite.test('integer array', function (done) { + suite.test('integer array', function(done) { client.query( "SELECT '{1,2,3}'::integer[] as names", - assert.success(function (result) { + assert.success(function(result) { var names = result.rows[0].names assert.lengthIs(names, 3) assert.equal(names[0], 1) @@ -178,10 +178,10 @@ pool.connect( ) }) - suite.test('integer nested array', function (done) { + suite.test('integer nested array', function(done) { client.query( "SELECT '{{1,100},{2,100},{3,100}}'::integer[] as names", - assert.success(function (result) { + assert.success(function(result) { var names = result.rows[0].names assert.lengthIs(names, 3) assert.equal(names[0][0], 1) @@ -197,7 +197,7 @@ pool.connect( ) }) - suite.test('JS array parameter', function (done) { + suite.test('JS array parameter', function(done) { client.query( 'SELECT $1::integer[] as names', [ @@ -207,7 +207,7 @@ pool.connect( [3, 100], ], ], - assert.success(function (result) { + assert.success(function(result) { var names = result.rows[0].names assert.lengthIs(names, 3) assert.equal(names[0][0], 1) diff --git a/packages/pg/test/integration/client/big-simple-query-tests.js b/packages/pg/test/integration/client/big-simple-query-tests.js index b0dc252f6..e51cde546 100644 --- a/packages/pg/test/integration/client/big-simple-query-tests.js +++ b/packages/pg/test/integration/client/big-simple-query-tests.js @@ -17,7 +17,7 @@ var big_query_rows_2 = [] var big_query_rows_3 = [] // Works -suite.test('big simple query 1', function (done) { +suite.test('big simple query 1', function(done) { var client = helper.client() client .query( @@ -25,10 +25,10 @@ suite.test('big simple query 1', function (done) { "select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = '' or 1 = 1" ) ) - .on('row', function (row) { + .on('row', function(row) { big_query_rows_1.push(row) }) - .on('error', function (error) { + .on('error', function(error) { console.log('big simple query 1 error') console.log(error) }) @@ -39,7 +39,7 @@ suite.test('big simple query 1', function (done) { }) // Works -suite.test('big simple query 2', function (done) { +suite.test('big simple query 2', function(done) { var client = helper.client() client .query( @@ -48,10 +48,10 @@ suite.test('big simple query 2', function (done) { [''] ) ) - .on('row', function (row) { + .on('row', function(row) { big_query_rows_2.push(row) }) - .on('error', function (error) { + .on('error', function(error) { console.log('big simple query 2 error') console.log(error) }) @@ -63,7 +63,7 @@ suite.test('big simple query 2', function (done) { // Fails most of the time with 'invalid byte sequence for encoding "UTF8": 0xb9' or 'insufficient data left in message' // If test 1 and 2 are commented out it works -suite.test('big simple query 3', function (done) { +suite.test('big simple query 3', function(done) { var client = helper.client() client .query( @@ -72,10 +72,10 @@ suite.test('big simple query 3', function (done) { [''] ) ) - .on('row', function (row) { + .on('row', function(row) { big_query_rows_3.push(row) }) - .on('error', function (error) { + .on('error', function(error) { console.log('big simple query 3 error') console.log(error) }) @@ -85,18 +85,18 @@ suite.test('big simple query 3', function (done) { }) }) -process.on('exit', function () { +process.on('exit', function() { assert.equal(big_query_rows_1.length, 26, 'big simple query 1 should return 26 rows') assert.equal(big_query_rows_2.length, 26, 'big simple query 2 should return 26 rows') assert.equal(big_query_rows_3.length, 26, 'big simple query 3 should return 26 rows') }) -var runBigQuery = function (client) { +var runBigQuery = function(client) { var rows = [] var q = client.query( "select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", [''], - function (err, result) { + function(err, result) { if (err != null) { console.log(err) throw Err @@ -106,14 +106,14 @@ var runBigQuery = function (client) { ) } -suite.test('many times', function (done) { +suite.test('many times', function(done) { var client = helper.client() for (var i = 0; i < 20; i++) { runBigQuery(client) } - client.on('drain', function () { + client.on('drain', function() { client.end() - setTimeout(function () { + setTimeout(function() { done() // let client disconnect fully }, 100) diff --git a/packages/pg/test/integration/client/configuration-tests.js b/packages/pg/test/integration/client/configuration-tests.js index 0737a79c3..1366a3687 100644 --- a/packages/pg/test/integration/client/configuration-tests.js +++ b/packages/pg/test/integration/client/configuration-tests.js @@ -11,7 +11,7 @@ for (var key in process.env) { if (!key.indexOf('PG')) delete process.env[key] } -suite.test('default values are used in new clients', function () { +suite.test('default values are used in new clients', function() { assert.same(pg.defaults, { user: process.env.USER, database: undefined, @@ -37,7 +37,7 @@ suite.test('default values are used in new clients', function () { }) }) -suite.test('modified values are passed to created clients', function () { +suite.test('modified values are passed to created clients', function() { pg.defaults.user = 'boom' pg.defaults.password = 'zap' pg.defaults.database = 'pow' diff --git a/packages/pg/test/integration/client/custom-types-tests.js b/packages/pg/test/integration/client/custom-types-tests.js index d1dd2eec0..d22e9312d 100644 --- a/packages/pg/test/integration/client/custom-types-tests.js +++ b/packages/pg/test/integration/client/custom-types-tests.js @@ -13,7 +13,7 @@ suite.test('custom type parser in client config', (done) => { client.connect().then(() => { client.query( 'SELECT NOW() as val', - assert.success(function (res) { + assert.success(function(res) { assert.equal(res.rows[0].val, 'okay!') client.end().then(done) }) @@ -32,7 +32,7 @@ if (!helper.args.native) { text: 'SELECT NOW() as val', types: customTypes, }, - assert.success(function (res) { + assert.success(function(res) { assert.equal(res.rows[0].val, 'okay!') client.end().then(done) }) diff --git a/packages/pg/test/integration/client/empty-query-tests.js b/packages/pg/test/integration/client/empty-query-tests.js index d887885c7..f22e5b399 100644 --- a/packages/pg/test/integration/client/empty-query-tests.js +++ b/packages/pg/test/integration/client/empty-query-tests.js @@ -2,17 +2,17 @@ var helper = require('./test-helper') const suite = new helper.Suite() -suite.test('empty query message handling', function (done) { +suite.test('empty query message handling', function(done) { const client = helper.client() - assert.emits(client, 'drain', function () { + assert.emits(client, 'drain', function() { client.end(done) }) client.query({ text: '' }) }) -suite.test('callback supported', function (done) { +suite.test('callback supported', function(done) { const client = helper.client() - client.query('', function (err, result) { + client.query('', function(err, result) { assert(!err) assert.empty(result.rows) client.end(done) diff --git a/packages/pg/test/integration/client/error-handling-tests.js b/packages/pg/test/integration/client/error-handling-tests.js index 93959e02b..d5f44a94d 100644 --- a/packages/pg/test/integration/client/error-handling-tests.js +++ b/packages/pg/test/integration/client/error-handling-tests.js @@ -6,9 +6,9 @@ var util = require('util') var pg = helper.pg const Client = pg.Client -var createErorrClient = function () { +var createErorrClient = function() { var client = helper.client() - client.once('error', function (err) { + client.once('error', function(err) { assert.fail('Client shoud not throw error during query execution') }) client.on('drain', client.end.bind(client)) @@ -67,10 +67,10 @@ suite.test('using a client after closing it results in error', (done) => { }) }) -suite.test('query receives error on client shutdown', function (done) { +suite.test('query receives error on client shutdown', function(done) { var client = new Client() client.connect( - assert.success(function () { + assert.success(function() { const config = { text: 'select pg_sleep(5)', name: 'foobar', @@ -78,7 +78,7 @@ suite.test('query receives error on client shutdown', function (done) { let queryError client.query( new pg.Query(config), - assert.calls(function (err, res) { + assert.calls(function(err, res) { assert(err instanceof Error) queryError = err }) @@ -92,9 +92,9 @@ suite.test('query receives error on client shutdown', function (done) { ) }) -var ensureFuture = function (testClient, done) { +var ensureFuture = function(testClient, done) { var goodQuery = testClient.query(new pg.Query('select age from boom')) - assert.emits(goodQuery, 'row', function (row) { + assert.emits(goodQuery, 'row', function(row) { assert.equal(row.age, 28) done() }) @@ -113,12 +113,12 @@ suite.test('when query is parsing', (done) => { }) ) - assert.emits(query, 'error', function (err) { + assert.emits(query, 'error', function(err) { ensureFuture(client, done) }) }) -suite.test('when a query is binding', function (done) { +suite.test('when a query is binding', function(done) { var client = createErorrClient() var q = client.query({ text: 'CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);' }) @@ -130,25 +130,25 @@ suite.test('when a query is binding', function (done) { }) ) - assert.emits(query, 'error', function (err) { + assert.emits(query, 'error', function(err) { assert.equal(err.severity, 'ERROR') ensureFuture(client, done) }) }) -suite.test('non-query error with callback', function (done) { +suite.test('non-query error with callback', function(done) { var client = new Client({ user: 'asldkfjsadlfkj', }) client.connect( - assert.calls(function (error, client) { + assert.calls(function(error, client) { assert(error instanceof Error) done() }) ) }) -suite.test('non-error calls supplied callback', function (done) { +suite.test('non-error calls supplied callback', function(done) { var client = new Client({ user: helper.args.user, password: helper.args.password, @@ -158,27 +158,27 @@ suite.test('non-error calls supplied callback', function (done) { }) client.connect( - assert.calls(function (err) { + assert.calls(function(err) { assert.ifError(err) client.end(done) }) ) }) -suite.test('when connecting to an invalid host with callback', function (done) { +suite.test('when connecting to an invalid host with callback', function(done) { var client = new Client({ user: 'very invalid username', }) client.on('error', () => { assert.fail('unexpected error event when connecting') }) - client.connect(function (error, client) { + client.connect(function(error, client) { assert(error instanceof Error) done() }) }) -suite.test('when connecting to invalid host with promise', function (done) { +suite.test('when connecting to invalid host with promise', function(done) { var client = new Client({ user: 'very invalid username', }) @@ -188,7 +188,7 @@ suite.test('when connecting to invalid host with promise', function (done) { client.connect().catch((e) => done()) }) -suite.test('non-query error', function (done) { +suite.test('non-query error', function(done) { var client = new Client({ user: 'asldkfjsadlfkj', }) @@ -203,7 +203,7 @@ suite.test('within a simple query', (done) => { var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")) - assert.emits(query, 'error', function (error) { + assert.emits(query, 'error', function(error) { assert.equal(error.severity, 'ERROR') done() }) diff --git a/packages/pg/test/integration/client/field-name-escape-tests.js b/packages/pg/test/integration/client/field-name-escape-tests.js index 146ad1b68..bb6a9def9 100644 --- a/packages/pg/test/integration/client/field-name-escape-tests.js +++ b/packages/pg/test/integration/client/field-name-escape-tests.js @@ -4,7 +4,7 @@ var sql = 'SELECT 1 AS "\\\'/*", 2 AS "\\\'*/\n + process.exit(-1)] = null;\n//" var client = new pg.Client() client.connect() -client.query(sql, function (err, res) { +client.query(sql, function(err, res) { if (err) throw err client.end() }) diff --git a/packages/pg/test/integration/client/huge-numeric-tests.js b/packages/pg/test/integration/client/huge-numeric-tests.js index bdbfac261..ccd433f0a 100644 --- a/packages/pg/test/integration/client/huge-numeric-tests.js +++ b/packages/pg/test/integration/client/huge-numeric-tests.js @@ -3,13 +3,13 @@ var helper = require('./test-helper') const pool = new helper.pg.Pool() pool.connect( - assert.success(function (client, done) { + assert.success(function(client, done) { var types = require('pg-types') // 1231 = numericOID - types.setTypeParser(1700, function () { + types.setTypeParser(1700, function() { return 'yes' }) - types.setTypeParser(1700, 'binary', function () { + types.setTypeParser(1700, 'binary', function() { return 'yes' }) var bignum = '294733346389144765940638005275322203805' @@ -17,7 +17,7 @@ pool.connect( client.query('INSERT INTO bignumz(id) VALUES ($1)', [bignum]) client.query( 'SELECT * FROM bignumz', - assert.success(function (result) { + assert.success(function(result) { assert.equal(result.rows[0].id, 'yes') done() pool.end() diff --git a/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js b/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js index f970faaf2..a8db2fcb3 100644 --- a/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js +++ b/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js @@ -13,13 +13,13 @@ function getConInfo(override) { function testClientVersion(cb) { var client = new Client({}) client.connect( - assert.success(function () { + assert.success(function() { helper.versionGTE( client, 100000, - assert.success(function (isGreater) { + assert.success(function(isGreater) { return client.end( - assert.success(function () { + assert.success(function() { if (!isGreater) { console.log( 'skip idle_in_transaction_session_timeout at client-level is only available in v10 and above' @@ -38,10 +38,10 @@ function testClientVersion(cb) { function getIdleTransactionSessionTimeout(conf, cb) { var client = new Client(conf) client.connect( - assert.success(function () { + assert.success(function() { client.query( 'SHOW idle_in_transaction_session_timeout', - assert.success(function (res) { + assert.success(function(res) { var timeout = res.rows[0].idle_in_transaction_session_timeout cb(timeout) client.end() @@ -53,40 +53,40 @@ function getIdleTransactionSessionTimeout(conf, cb) { if (!helper.args.native) { // idle_in_transaction_session_timeout is not supported with the native client - testClientVersion(function () { - suite.test('No default idle_in_transaction_session_timeout ', function (done) { + testClientVersion(function() { + suite.test('No default idle_in_transaction_session_timeout ', function(done) { getConInfo() - getIdleTransactionSessionTimeout({}, function (res) { + getIdleTransactionSessionTimeout({}, function(res) { assert.strictEqual(res, '0') // 0 = no timeout done() }) }) - suite.test('idle_in_transaction_session_timeout integer is used', function (done) { + suite.test('idle_in_transaction_session_timeout integer is used', function(done) { var conf = getConInfo({ idle_in_transaction_session_timeout: 3000, }) - getIdleTransactionSessionTimeout(conf, function (res) { + getIdleTransactionSessionTimeout(conf, function(res) { assert.strictEqual(res, '3s') done() }) }) - suite.test('idle_in_transaction_session_timeout float is used', function (done) { + suite.test('idle_in_transaction_session_timeout float is used', function(done) { var conf = getConInfo({ idle_in_transaction_session_timeout: 3000.7, }) - getIdleTransactionSessionTimeout(conf, function (res) { + getIdleTransactionSessionTimeout(conf, function(res) { assert.strictEqual(res, '3s') done() }) }) - suite.test('idle_in_transaction_session_timeout string is used', function (done) { + suite.test('idle_in_transaction_session_timeout string is used', function(done) { var conf = getConInfo({ idle_in_transaction_session_timeout: '3000', }) - getIdleTransactionSessionTimeout(conf, function (res) { + getIdleTransactionSessionTimeout(conf, function(res) { assert.strictEqual(res, '3s') done() }) diff --git a/packages/pg/test/integration/client/json-type-parsing-tests.js b/packages/pg/test/integration/client/json-type-parsing-tests.js index ba7696020..f4d431d3f 100644 --- a/packages/pg/test/integration/client/json-type-parsing-tests.js +++ b/packages/pg/test/integration/client/json-type-parsing-tests.js @@ -4,11 +4,11 @@ var assert = require('assert') const pool = new helper.pg.Pool() pool.connect( - assert.success(function (client, done) { + assert.success(function(client, done) { helper.versionGTE( client, 90200, - assert.success(function (jsonSupported) { + assert.success(function(jsonSupported) { if (!jsonSupported) { console.log('skip json test on older versions of postgres') done() @@ -19,7 +19,7 @@ pool.connect( client.query('INSERT INTO stuff (data) VALUES ($1)', [value]) client.query( 'SELECT * FROM stuff', - assert.success(function (result) { + assert.success(function(result) { assert.equal(result.rows.length, 1) assert.equal(typeof result.rows[0].data, 'object') var row = result.rows[0].data diff --git a/packages/pg/test/integration/client/multiple-results-tests.js b/packages/pg/test/integration/client/multiple-results-tests.js index addca9b68..8a084d040 100644 --- a/packages/pg/test/integration/client/multiple-results-tests.js +++ b/packages/pg/test/integration/client/multiple-results-tests.js @@ -8,7 +8,7 @@ const suite = new helper.Suite('multiple result sets') suite.test( 'two select results work', - co.wrap(function* () { + co.wrap(function*() { const client = new helper.Client() yield client.connect() @@ -27,7 +27,7 @@ suite.test( suite.test( 'multiple selects work', - co.wrap(function* () { + co.wrap(function*() { const client = new helper.Client() yield client.connect() @@ -57,7 +57,7 @@ suite.test( suite.test( 'mixed queries and statements', - co.wrap(function* () { + co.wrap(function*() { const client = new helper.Client() yield client.connect() diff --git a/packages/pg/test/integration/client/network-partition-tests.js b/packages/pg/test/integration/client/network-partition-tests.js index 993396401..b0fa8bb71 100644 --- a/packages/pg/test/integration/client/network-partition-tests.js +++ b/packages/pg/test/integration/client/network-partition-tests.js @@ -5,24 +5,24 @@ var suite = new helper.Suite() var net = require('net') -var Server = function (response) { +var Server = function(response) { this.server = undefined this.socket = undefined this.response = response } -Server.prototype.start = function (cb) { +Server.prototype.start = function(cb) { // this is our fake postgres server // it responds with our specified response immediatley after receiving every buffer // this is sufficient into convincing the client its connectet to a valid backend // if we respond with a readyForQuery message this.server = net.createServer( - function (socket) { + function(socket) { this.socket = socket if (this.response) { this.socket.on( 'data', - function (data) { + function(data) { // deny request for SSL if (data.length == 8) { this.socket.write(Buffer.from('N', 'utf8')) @@ -45,22 +45,22 @@ Server.prototype.start = function (cb) { host: 'localhost', port: port, } - this.server.listen(options.port, options.host, function () { + this.server.listen(options.port, options.host, function() { cb(options) }) } -Server.prototype.drop = function () { +Server.prototype.drop = function() { this.socket.destroy() } -Server.prototype.close = function (cb) { +Server.prototype.close = function(cb) { this.server.close(cb) } -var testServer = function (server, cb) { +var testServer = function(server, cb) { // wait for our server to start - server.start(function (options) { + server.start(function(options) { // connect a client to it var client = new helper.Client(options) client.connect().catch((err) => { @@ -71,13 +71,13 @@ var testServer = function (server, cb) { server.server.on('connection', () => { // after 50 milliseconds, drop the client - setTimeout(function () { + setTimeout(function() { server.drop() }, 50) }) // blow up if we don't receive an error - var timeoutId = setTimeout(function () { + var timeoutId = setTimeout(function() { throw new Error('Client should have emitted an error but it did not.') }, 5000) }) diff --git a/packages/pg/test/integration/client/no-data-tests.js b/packages/pg/test/integration/client/no-data-tests.js index ad0f22be3..c4051d11e 100644 --- a/packages/pg/test/integration/client/no-data-tests.js +++ b/packages/pg/test/integration/client/no-data-tests.js @@ -2,7 +2,7 @@ var helper = require('./test-helper') const suite = new helper.Suite() -suite.test('noData message handling', function () { +suite.test('noData message handling', function() { var client = helper.client() var q = client.query({ @@ -16,7 +16,7 @@ suite.test('noData message handling', function () { text: 'insert into boom(size) values($1)', values: [100], }, - function (err, result) { + function(err, result) { if (err) { console.log(err) throw err diff --git a/packages/pg/test/integration/client/no-row-result-tests.js b/packages/pg/test/integration/client/no-row-result-tests.js index 6e8f52cf0..a4acf31ef 100644 --- a/packages/pg/test/integration/client/no-row-result-tests.js +++ b/packages/pg/test/integration/client/no-row-result-tests.js @@ -4,8 +4,8 @@ var pg = helper.pg const suite = new helper.Suite() const pool = new pg.Pool() -suite.test('can access results when no rows are returned', function (done) { - var checkResult = function (result) { +suite.test('can access results when no rows are returned', function(done) { + var checkResult = function(result) { assert(result.fields, 'should have fields definition') assert.equal(result.fields.length, 1) assert.equal(result.fields[0].name, 'val') @@ -13,11 +13,11 @@ suite.test('can access results when no rows are returned', function (done) { } pool.connect( - assert.success(function (client, release) { + assert.success(function(client, release) { const q = new pg.Query('select $1::text as val limit 0', ['hi']) var query = client.query( q, - assert.success(function (result) { + assert.success(function(result) { checkResult(result) release() pool.end(done) diff --git a/packages/pg/test/integration/client/notice-tests.js b/packages/pg/test/integration/client/notice-tests.js index b5d4f3d5e..1c232711b 100644 --- a/packages/pg/test/integration/client/notice-tests.js +++ b/packages/pg/test/integration/client/notice-tests.js @@ -3,19 +3,19 @@ const helper = require('./test-helper') const assert = require('assert') const suite = new helper.Suite() -suite.test('emits notify message', function (done) { +suite.test('emits notify message', function(done) { const client = helper.client() client.query( 'LISTEN boom', - assert.calls(function () { + assert.calls(function() { const otherClient = helper.client() let bothEmitted = -1 otherClient.query( 'LISTEN boom', - assert.calls(function () { - assert.emits(client, 'notification', function (msg) { + assert.calls(function() { + assert.emits(client, 'notification', function(msg) { // make sure PQfreemem doesn't invalidate string pointers - setTimeout(function () { + setTimeout(function() { assert.equal(msg.channel, 'boom') assert.ok( msg.payload == 'omg!' /* 9.x */ || msg.payload == '' /* 8.x */, @@ -24,12 +24,12 @@ suite.test('emits notify message', function (done) { client.end(++bothEmitted ? done : undefined) }, 100) }) - assert.emits(otherClient, 'notification', function (msg) { + assert.emits(otherClient, 'notification', function(msg) { assert.equal(msg.channel, 'boom') otherClient.end(++bothEmitted ? done : undefined) }) - client.query("NOTIFY boom, 'omg!'", function (err, q) { + client.query("NOTIFY boom, 'omg!'", function(err, q) { if (err) { // notify not supported with payload on 8.x client.query('NOTIFY boom') @@ -42,7 +42,7 @@ suite.test('emits notify message', function (done) { }) // this test fails on travis due to their config -suite.test('emits notice message', function (done) { +suite.test('emits notice message', function(done) { if (helper.args.native) { console.error('notice messages do not work curreintly with node-libpq') return done() @@ -62,7 +62,7 @@ $$; client.end() }) }) - assert.emits(client, 'notice', function (notice) { + assert.emits(client, 'notice', function(notice) { assert.ok(notice != null) // notice messages should not be error instances assert(notice instanceof Error === false) diff --git a/packages/pg/test/integration/client/parse-int-8-tests.js b/packages/pg/test/integration/client/parse-int-8-tests.js index 9f251de69..88ac8cf7c 100644 --- a/packages/pg/test/integration/client/parse-int-8-tests.js +++ b/packages/pg/test/integration/client/parse-int-8-tests.js @@ -5,15 +5,15 @@ var pg = helper.pg const suite = new helper.Suite() const pool = new pg.Pool(helper.config) -suite.test('ability to turn on and off parser', function () { +suite.test('ability to turn on and off parser', function() { if (helper.args.binary) return false pool.connect( - assert.success(function (client, done) { + assert.success(function(client, done) { pg.defaults.parseInt8 = true client.query('CREATE TEMP TABLE asdf(id SERIAL PRIMARY KEY)') client.query( 'SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', - assert.success(function (res) { + assert.success(function(res) { assert.strictEqual(0, res.rows[0].count) assert.strictEqual(1, res.rows[0].array[0]) assert.strictEqual(2, res.rows[0].array[1]) @@ -21,7 +21,7 @@ suite.test('ability to turn on and off parser', function () { pg.defaults.parseInt8 = false client.query( 'SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', - assert.success(function (res) { + assert.success(function(res) { done() assert.strictEqual('0', res.rows[0].count) assert.strictEqual('1', res.rows[0].array[0]) diff --git a/packages/pg/test/integration/client/prepared-statement-tests.js b/packages/pg/test/integration/client/prepared-statement-tests.js index 48d12f899..57286bd5e 100644 --- a/packages/pg/test/integration/client/prepared-statement-tests.js +++ b/packages/pg/test/integration/client/prepared-statement-tests.js @@ -4,14 +4,14 @@ var Query = helper.pg.Query var suite = new helper.Suite() -;(function () { +;(function() { var client = helper.client() client.on('drain', client.end.bind(client)) var queryName = 'user by age and like name' var parseCount = 0 - suite.test('first named prepared statement', function (done) { + suite.test('first named prepared statement', function(done) { var query = client.query( new Query({ text: 'select name from person where age <= $1 and name LIKE $2', @@ -20,14 +20,14 @@ var suite = new helper.Suite() }) ) - assert.emits(query, 'row', function (row) { + assert.emits(query, 'row', function(row) { assert.equal(row.name, 'Brian') }) query.on('end', () => done()) }) - suite.test('second named prepared statement with same name & text', function (done) { + suite.test('second named prepared statement with same name & text', function(done) { var cachedQuery = client.query( new Query({ text: 'select name from person where age <= $1 and name LIKE $2', @@ -36,14 +36,14 @@ var suite = new helper.Suite() }) ) - assert.emits(cachedQuery, 'row', function (row) { + assert.emits(cachedQuery, 'row', function(row) { assert.equal(row.name, 'Aaron') }) cachedQuery.on('end', () => done()) }) - suite.test('with same name, but without query text', function (done) { + suite.test('with same name, but without query text', function(done) { var q = client.query( new Query({ name: queryName, @@ -51,11 +51,11 @@ var suite = new helper.Suite() }) ) - assert.emits(q, 'row', function (row) { + assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Aaron') // test second row is emitted as well - assert.emits(q, 'row', function (row) { + assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Brian') }) }) @@ -63,7 +63,7 @@ var suite = new helper.Suite() q.on('end', () => done()) }) - suite.test('with same name, but with different text', function (done) { + suite.test('with same name, but with different text', function(done) { client.query( new Query({ text: 'select name from person where age >= $1 and name LIKE $2', @@ -80,7 +80,7 @@ var suite = new helper.Suite() ) }) })() -;(function () { +;(function() { var statementName = 'differ' var statement1 = 'select count(*)::int4 as count from person' var statement2 = 'select count(*)::int4 as count from person where age < $1' @@ -88,7 +88,7 @@ var suite = new helper.Suite() var client1 = helper.client() var client2 = helper.client() - suite.test('client 1 execution', function (done) { + suite.test('client 1 execution', function(done) { var query = client1.query( { name: statementName, @@ -102,7 +102,7 @@ var suite = new helper.Suite() ) }) - suite.test('client 2 execution', function (done) { + suite.test('client 2 execution', function(done) { var query = client2.query( new Query({ name: statementName, @@ -111,11 +111,11 @@ var suite = new helper.Suite() }) ) - assert.emits(query, 'row', function (row) { + assert.emits(query, 'row', function(row) { assert.equal(row.count, 1) }) - assert.emits(query, 'end', function () { + assert.emits(query, 'end', function() { done() }) }) @@ -124,28 +124,28 @@ var suite = new helper.Suite() return client1.end().then(() => client2.end()) }) })() -;(function () { +;(function() { var client = helper.client() client.query('CREATE TEMP TABLE zoom(name varchar(100));') client.query("INSERT INTO zoom (name) VALUES ('zed')") client.query("INSERT INTO zoom (name) VALUES ('postgres')") client.query("INSERT INTO zoom (name) VALUES ('node postgres')") - var checkForResults = function (q) { - assert.emits(q, 'row', function (row) { + var checkForResults = function(q) { + assert.emits(q, 'row', function(row) { assert.equal(row.name, 'node postgres') - assert.emits(q, 'row', function (row) { + assert.emits(q, 'row', function(row) { assert.equal(row.name, 'postgres') - assert.emits(q, 'row', function (row) { + assert.emits(q, 'row', function(row) { assert.equal(row.name, 'zed') }) }) }) } - suite.test('with small row count', function (done) { + suite.test('with small row count', function(done) { var query = client.query( new Query( { @@ -160,7 +160,7 @@ var suite = new helper.Suite() checkForResults(query) }) - suite.test('with large row count', function (done) { + suite.test('with large row count', function(done) { var query = client.query( new Query( { diff --git a/packages/pg/test/integration/client/query-as-promise-tests.js b/packages/pg/test/integration/client/query-as-promise-tests.js index 46365c6c0..6be886c74 100644 --- a/packages/pg/test/integration/client/query-as-promise-tests.js +++ b/packages/pg/test/integration/client/query-as-promise-tests.js @@ -3,7 +3,7 @@ var bluebird = require('bluebird') var helper = require(__dirname + '/../test-helper') var pg = helper.pg -process.on('unhandledRejection', function (e) { +process.on('unhandledRejection', function(e) { console.error(e, e.stack) process.exit(1) }) @@ -15,14 +15,14 @@ suite.test('promise API', (cb) => { pool.connect().then((client) => { client .query('SELECT $1::text as name', ['foo']) - .then(function (result) { + .then(function(result) { assert.equal(result.rows[0].name, 'foo') return client }) - .then(function (client) { - client.query('ALKJSDF').catch(function (e) { + .then(function(client) { + client.query('ALKJSDF').catch(function(e) { assert(e instanceof Error) - client.query('SELECT 1 as num').then(function (result) { + client.query('SELECT 1 as num').then(function(result) { assert.equal(result.rows[0].num, 1) client.release() pool.end(cb) diff --git a/packages/pg/test/integration/client/query-column-names-tests.js b/packages/pg/test/integration/client/query-column-names-tests.js index 6b32881e5..61469ec96 100644 --- a/packages/pg/test/integration/client/query-column-names-tests.js +++ b/packages/pg/test/integration/client/query-column-names-tests.js @@ -2,14 +2,14 @@ var helper = require(__dirname + '/../test-helper') var pg = helper.pg -new helper.Suite().test('support for complex column names', function () { +new helper.Suite().test('support for complex column names', function() { const pool = new pg.Pool() pool.connect( - assert.success(function (client, done) { + assert.success(function(client, done) { client.query('CREATE TEMP TABLE t ( "complex\'\'column" TEXT )') client.query( 'SELECT * FROM t', - assert.success(function (res) { + assert.success(function(res) { done() assert.strictEqual(res.fields[0].name, "complex''column") pool.end() diff --git a/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js b/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js index adef58d16..2930761dd 100644 --- a/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -5,10 +5,10 @@ var util = require('util') var suite = new helper.Suite() -suite.test('client end during query execution of prepared statement', function (done) { +suite.test('client end during query execution of prepared statement', function(done) { var client = new Client() client.connect( - assert.success(function () { + assert.success(function() { var sleepQuery = 'select pg_sleep($1)' var queryConfig = { @@ -19,7 +19,7 @@ suite.test('client end during query execution of prepared statement', function ( var queryInstance = new Query( queryConfig, - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert.equal(err.message, 'Connection terminated') done() }) @@ -27,15 +27,15 @@ suite.test('client end during query execution of prepared statement', function ( var query1 = client.query(queryInstance) - query1.on('error', function (err) { + query1.on('error', function(err) { assert.fail('Prepared statement should not emit error') }) - query1.on('row', function (row) { + query1.on('row', function(row) { assert.fail('Prepared statement should not emit row') }) - query1.on('end', function (err) { + query1.on('end', function(err) { assert.fail('Prepared statement when executed should not return before being killed') }) @@ -49,11 +49,11 @@ function killIdleQuery(targetQuery, cb) { var pidColName = 'procpid' var queryColName = 'current_query' client2.connect( - assert.success(function () { + assert.success(function() { helper.versionGTE( client2, 90200, - assert.success(function (isGreater) { + assert.success(function(isGreater) { if (isGreater) { pidColName = 'pid' queryColName = 'query' @@ -69,7 +69,7 @@ function killIdleQuery(targetQuery, cb) { client2.query( killIdleQuery, [targetQuery], - assert.calls(function (err, res) { + assert.calls(function(err, res) { assert.ifError(err) assert.equal(res.rows.length, 1) client2.end(cb) @@ -82,13 +82,13 @@ function killIdleQuery(targetQuery, cb) { ) } -suite.test('query killed during query execution of prepared statement', function (done) { +suite.test('query killed during query execution of prepared statement', function(done) { if (helper.args.native) { return done() } var client = new Client(helper.args) client.connect( - assert.success(function () { + assert.success(function() { var sleepQuery = 'select pg_sleep($1)' const queryConfig = { @@ -102,20 +102,20 @@ suite.test('query killed during query execution of prepared statement', function var query1 = client.query( new Query(queryConfig), - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert.equal(err.message, 'terminating connection due to administrator command') }) ) - query1.on('error', function (err) { + query1.on('error', function(err) { assert.fail('Prepared statement should not emit error') }) - query1.on('row', function (row) { + query1.on('row', function(row) { assert.fail('Prepared statement should not emit row') }) - query1.on('end', function (err) { + query1.on('end', function(err) { assert.fail('Prepared statement when executed should not return before being killed') }) diff --git a/packages/pg/test/integration/client/query-error-handling-tests.js b/packages/pg/test/integration/client/query-error-handling-tests.js index 34eab8f65..94891bf32 100644 --- a/packages/pg/test/integration/client/query-error-handling-tests.js +++ b/packages/pg/test/integration/client/query-error-handling-tests.js @@ -3,10 +3,10 @@ var helper = require('./test-helper') var util = require('util') var Query = helper.pg.Query -test('error during query execution', function () { +test('error during query execution', function() { var client = new Client(helper.args) client.connect( - assert.success(function () { + assert.success(function() { var queryText = 'select pg_sleep(10)' var sleepQuery = new Query(queryText) var pidColName = 'procpid' @@ -14,14 +14,14 @@ test('error during query execution', function () { helper.versionGTE( client, 90200, - assert.success(function (isGreater) { + assert.success(function(isGreater) { if (isGreater) { pidColName = 'pid' queryColName = 'query' } var query1 = client.query( sleepQuery, - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(err) client.end() }) @@ -29,18 +29,18 @@ test('error during query execution', function () { //ensure query1 does not emit an 'end' event //because it was killed and received an error //https://github.com/brianc/node-postgres/issues/547 - query1.on('end', function () { + query1.on('end', function() { assert.fail('Query with an error should not emit "end" event') }) - setTimeout(function () { + setTimeout(function() { var client2 = new Client(helper.args) client2.connect( - assert.success(function () { + assert.success(function() { var killIdleQuery = `SELECT ${pidColName}, (SELECT pg_cancel_backend(${pidColName})) AS killed FROM pg_stat_activity WHERE ${queryColName} LIKE $1` client2.query( killIdleQuery, [queryText], - assert.calls(function (err, res) { + assert.calls(function(err, res) { assert.ifError(err) assert(res.rows.length > 0) client2.end() @@ -60,20 +60,20 @@ if (helper.config.native) { return } -test('9.3 column error fields', function () { +test('9.3 column error fields', function() { var client = new Client(helper.args) client.connect( - assert.success(function () { + assert.success(function() { helper.versionGTE( client, 90300, - assert.success(function (isGreater) { + assert.success(function(isGreater) { if (!isGreater) { return client.end() } client.query('CREATE TEMP TABLE column_err_test(a int NOT NULL)') - client.query('INSERT INTO column_err_test(a) VALUES (NULL)', function (err) { + client.query('INSERT INTO column_err_test(a) VALUES (NULL)', function(err) { assert.equal(err.severity, 'ERROR') assert.equal(err.code, '23502') assert.equal(err.table, 'column_err_test') @@ -86,14 +86,14 @@ test('9.3 column error fields', function () { ) }) -test('9.3 constraint error fields', function () { +test('9.3 constraint error fields', function() { var client = new Client(helper.args) client.connect( - assert.success(function () { + assert.success(function() { helper.versionGTE( client, 90300, - assert.success(function (isGreater) { + assert.success(function(isGreater) { if (!isGreater) { console.log('skip 9.3 error field on older versions of postgres') return client.end() @@ -101,7 +101,7 @@ test('9.3 constraint error fields', function () { client.query('CREATE TEMP TABLE constraint_err_test(a int PRIMARY KEY)') client.query('INSERT INTO constraint_err_test(a) VALUES (1)') - client.query('INSERT INTO constraint_err_test(a) VALUES (1)', function (err) { + client.query('INSERT INTO constraint_err_test(a) VALUES (1)', function(err) { assert.equal(err.severity, 'ERROR') assert.equal(err.code, '23505') assert.equal(err.table, 'constraint_err_test') diff --git a/packages/pg/test/integration/client/result-metadata-tests.js b/packages/pg/test/integration/client/result-metadata-tests.js index 66d9ac4ae..352cce194 100644 --- a/packages/pg/test/integration/client/result-metadata-tests.js +++ b/packages/pg/test/integration/client/result-metadata-tests.js @@ -3,32 +3,32 @@ var helper = require('./test-helper') var pg = helper.pg const pool = new pg.Pool() -new helper.Suite().test('should return insert metadata', function () { +new helper.Suite().test('should return insert metadata', function() { pool.connect( - assert.calls(function (err, client, done) { + assert.calls(function(err, client, done) { assert(!err) helper.versionGTE( client, 90000, - assert.success(function (hasRowCount) { + assert.success(function(hasRowCount) { client.query( 'CREATE TEMP TABLE zugzug(name varchar(10))', - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) assert.equal(result.oid, null) assert.equal(result.command, 'CREATE') var q = client.query( "INSERT INTO zugzug(name) VALUES('more work?')", - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) assert.equal(result.command, 'INSERT') assert.equal(result.rowCount, 1) client.query( 'SELECT * FROM zugzug', - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) if (hasRowCount) assert.equal(result.rowCount, 1) assert.equal(result.command, 'SELECT') diff --git a/packages/pg/test/integration/client/results-as-array-tests.js b/packages/pg/test/integration/client/results-as-array-tests.js index 5ebb2a9d5..6b77ed5e6 100644 --- a/packages/pg/test/integration/client/results-as-array-tests.js +++ b/packages/pg/test/integration/client/results-as-array-tests.js @@ -6,9 +6,9 @@ var Client = helper.Client var conInfo = helper.config -test('returns results as array', function () { +test('returns results as array', function() { var client = new Client(conInfo) - var checkRow = function (row) { + var checkRow = function(row) { assert(util.isArray(row), 'row should be an array') assert.equal(row.length, 4) assert.equal(row[0].getFullYear(), new Date().getFullYear()) @@ -17,7 +17,7 @@ test('returns results as array', function () { assert.strictEqual(row[3], null) } client.connect( - assert.success(function () { + assert.success(function() { var config = { text: 'SELECT NOW(), 1::int, $1::text, null', values: ['hai'], @@ -25,7 +25,7 @@ test('returns results as array', function () { } var query = client.query( config, - assert.success(function (result) { + assert.success(function(result) { assert.equal(result.rows.length, 1) checkRow(result.rows[0]) client.end() diff --git a/packages/pg/test/integration/client/row-description-on-results-tests.js b/packages/pg/test/integration/client/row-description-on-results-tests.js index 688b96e6c..52966148d 100644 --- a/packages/pg/test/integration/client/row-description-on-results-tests.js +++ b/packages/pg/test/integration/client/row-description-on-results-tests.js @@ -5,7 +5,7 @@ var Client = helper.Client var conInfo = helper.config -var checkResult = function (result) { +var checkResult = function(result) { assert(result.fields) assert.equal(result.fields.length, 3) var fields = result.fields @@ -17,14 +17,14 @@ var checkResult = function (result) { assert.equal(fields[2].dataTypeID, 25) } -test('row descriptions on result object', function () { +test('row descriptions on result object', function() { var client = new Client(conInfo) client.connect( - assert.success(function () { + assert.success(function() { client.query( 'SELECT NOW() as now, 1::int as num, $1::text as texty', ['hello'], - assert.success(function (result) { + assert.success(function(result) { checkResult(result) client.end() }) @@ -33,14 +33,14 @@ test('row descriptions on result object', function () { ) }) -test('row description on no rows', function () { +test('row description on no rows', function() { var client = new Client(conInfo) client.connect( - assert.success(function () { + assert.success(function() { client.query( 'SELECT NOW() as now, 1::int as num, $1::text as texty LIMIT 0', ['hello'], - assert.success(function (result) { + assert.success(function(result) { checkResult(result) client.end() }) diff --git a/packages/pg/test/integration/client/simple-query-tests.js b/packages/pg/test/integration/client/simple-query-tests.js index d22d74742..e3071b837 100644 --- a/packages/pg/test/integration/client/simple-query-tests.js +++ b/packages/pg/test/integration/client/simple-query-tests.js @@ -3,7 +3,7 @@ var helper = require('./test-helper') var Query = helper.pg.Query // before running this test make sure you run the script create-test-tables -test('simple query interface', function () { +test('simple query interface', function() { var client = helper.client() var query = client.query(new Query('select name from person order by name collate "C"')) @@ -11,12 +11,12 @@ test('simple query interface', function () { client.on('drain', client.end.bind(client)) var rows = [] - query.on('row', function (row, result) { + query.on('row', function(row, result) { assert.ok(result) rows.push(row['name']) }) - query.once('row', function (row) { - test('Can iterate through columns', function () { + query.once('row', function(row) { + test('Can iterate through columns', function() { var columnCount = 0 for (var column in row) { columnCount++ @@ -31,18 +31,18 @@ test('simple query interface', function () { }) }) - assert.emits(query, 'end', function () { - test('returned right number of rows', function () { + assert.emits(query, 'end', function() { + test('returned right number of rows', function() { assert.lengthIs(rows, 26) }) - test('row ordering', function () { + test('row ordering', function() { assert.equal(rows[0], 'Aaron') assert.equal(rows[25], 'Zanzabar') }) }) }) -test('prepared statements do not mutate params', function () { +test('prepared statements do not mutate params', function() { var client = helper.client() var params = [1] @@ -54,12 +54,12 @@ test('prepared statements do not mutate params', function () { client.on('drain', client.end.bind(client)) const rows = [] - query.on('row', function (row, result) { + query.on('row', function(row, result) { assert.ok(result) rows.push(row) }) - query.on('end', function (result) { + query.on('end', function(result) { assert.lengthIs(rows, 26, 'result returned wrong number of rows') assert.lengthIs(rows, result.rowCount) assert.equal(rows[0].name, 'Aaron') @@ -67,30 +67,30 @@ test('prepared statements do not mutate params', function () { }) }) -test('multiple simple queries', function () { +test('multiple simple queries', function() { var client = helper.client() client.query({ text: "create temp table bang(id serial, name varchar(5));insert into bang(name) VALUES('boom');" }) client.query("insert into bang(name) VALUES ('yes');") var query = client.query(new Query('select name from bang')) - assert.emits(query, 'row', function (row) { + assert.emits(query, 'row', function(row) { assert.equal(row['name'], 'boom') - assert.emits(query, 'row', function (row) { + assert.emits(query, 'row', function(row) { assert.equal(row['name'], 'yes') }) }) client.on('drain', client.end.bind(client)) }) -test('multiple select statements', function () { +test('multiple select statements', function() { var client = helper.client() client.query( 'create temp table boom(age integer); insert into boom(age) values(1); insert into boom(age) values(2); insert into boom(age) values(3)' ) client.query({ text: "create temp table bang(name varchar(5)); insert into bang(name) values('zoom');" }) var result = client.query(new Query({ text: 'select age from boom where age < 2; select name from bang' })) - assert.emits(result, 'row', function (row) { + assert.emits(result, 'row', function(row) { assert.strictEqual(row['age'], 1) - assert.emits(result, 'row', function (row) { + assert.emits(result, 'row', function(row) { assert.strictEqual(row['name'], 'zoom') }) }) diff --git a/packages/pg/test/integration/client/ssl-tests.js b/packages/pg/test/integration/client/ssl-tests.js index 1d3c5015b..1e544bf56 100644 --- a/packages/pg/test/integration/client/ssl-tests.js +++ b/packages/pg/test/integration/client/ssl-tests.js @@ -1,18 +1,18 @@ 'use strict' var pg = require(__dirname + '/../../../lib') var config = require(__dirname + '/test-helper').config -test('can connect with ssl', function () { +test('can connect with ssl', function() { return false config.ssl = { rejectUnauthorized: false, } pg.connect( config, - assert.success(function (client) { + assert.success(function(client) { return false client.query( 'SELECT NOW()', - assert.success(function () { + assert.success(function() { pg.end() }) ) diff --git a/packages/pg/test/integration/client/statement_timeout-tests.js b/packages/pg/test/integration/client/statement_timeout-tests.js index e0898ccee..b59cb51c0 100644 --- a/packages/pg/test/integration/client/statement_timeout-tests.js +++ b/packages/pg/test/integration/client/statement_timeout-tests.js @@ -13,10 +13,10 @@ function getConInfo(override) { function getStatementTimeout(conf, cb) { var client = new Client(conf) client.connect( - assert.success(function () { + assert.success(function() { client.query( 'SHOW statement_timeout', - assert.success(function (res) { + assert.success(function(res) { var statementTimeout = res.rows[0].statement_timeout cb(statementTimeout) client.end() @@ -28,52 +28,52 @@ function getStatementTimeout(conf, cb) { if (!helper.args.native) { // statement_timeout is not supported with the native client - suite.test('No default statement_timeout ', function (done) { + suite.test('No default statement_timeout ', function(done) { getConInfo() - getStatementTimeout({}, function (res) { + getStatementTimeout({}, function(res) { assert.strictEqual(res, '0') // 0 = no timeout done() }) }) - suite.test('statement_timeout integer is used', function (done) { + suite.test('statement_timeout integer is used', function(done) { var conf = getConInfo({ statement_timeout: 3000, }) - getStatementTimeout(conf, function (res) { + getStatementTimeout(conf, function(res) { assert.strictEqual(res, '3s') done() }) }) - suite.test('statement_timeout float is used', function (done) { + suite.test('statement_timeout float is used', function(done) { var conf = getConInfo({ statement_timeout: 3000.7, }) - getStatementTimeout(conf, function (res) { + getStatementTimeout(conf, function(res) { assert.strictEqual(res, '3s') done() }) }) - suite.test('statement_timeout string is used', function (done) { + suite.test('statement_timeout string is used', function(done) { var conf = getConInfo({ statement_timeout: '3000', }) - getStatementTimeout(conf, function (res) { + getStatementTimeout(conf, function(res) { assert.strictEqual(res, '3s') done() }) }) - suite.test('statement_timeout actually cancels long running queries', function (done) { + suite.test('statement_timeout actually cancels long running queries', function(done) { var conf = getConInfo({ statement_timeout: '10', // 10ms to keep tests running fast }) var client = new Client(conf) client.connect( - assert.success(function () { - client.query('SELECT pg_sleep( 1 )', function (error) { + assert.success(function() { + client.query('SELECT pg_sleep( 1 )', function(error) { client.end() assert.strictEqual(error.code, '57014') // query_cancelled done() diff --git a/packages/pg/test/integration/client/timezone-tests.js b/packages/pg/test/integration/client/timezone-tests.js index c9f6a8c83..aa3f3442f 100644 --- a/packages/pg/test/integration/client/timezone-tests.js +++ b/packages/pg/test/integration/client/timezone-tests.js @@ -10,19 +10,19 @@ var date = new Date() const pool = new helper.pg.Pool() const suite = new helper.Suite() -pool.connect(function (err, client, done) { +pool.connect(function(err, client, done) { assert(!err) - suite.test('timestamp without time zone', function (cb) { - client.query('SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS "val"', [date], function (err, result) { + suite.test('timestamp without time zone', function(cb) { + client.query('SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS "val"', [date], function(err, result) { assert(!err) assert.equal(result.rows[0].val.getTime(), date.getTime()) cb() }) }) - suite.test('timestamp with time zone', function (cb) { - client.query('SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS "val"', [date], function (err, result) { + suite.test('timestamp with time zone', function(cb) { + client.query('SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS "val"', [date], function(err, result) { assert(!err) assert.equal(result.rows[0].val.getTime(), date.getTime()) diff --git a/packages/pg/test/integration/client/transaction-tests.js b/packages/pg/test/integration/client/transaction-tests.js index 18f8ff095..f227da720 100644 --- a/packages/pg/test/integration/client/transaction-tests.js +++ b/packages/pg/test/integration/client/transaction-tests.js @@ -5,7 +5,7 @@ const pg = helper.pg const client = new pg.Client() client.connect( - assert.success(function () { + assert.success(function() { client.query('begin') var getZed = { @@ -13,10 +13,10 @@ client.connect( values: ['Zed'], } - suite.test('name should not exist in the database', function (done) { + suite.test('name should not exist in the database', function(done) { client.query( getZed, - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) assert.empty(result.rows) done() @@ -28,17 +28,17 @@ client.connect( client.query( 'INSERT INTO person(name, age) VALUES($1, $2)', ['Zed', 270], - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) done() }) ) }) - suite.test('name should exist in the database', function (done) { + suite.test('name should exist in the database', function(done) { client.query( getZed, - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) assert.equal(result.rows[0].name, 'Zed') done() @@ -50,10 +50,10 @@ client.connect( client.query('rollback', done) }) - suite.test('name should not exist in the database', function (done) { + suite.test('name should not exist in the database', function(done) { client.query( getZed, - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) assert.empty(result.rows) client.end(done) @@ -63,10 +63,10 @@ client.connect( }) ) -suite.test('gh#36', function (cb) { +suite.test('gh#36', function(cb) { const pool = new pg.Pool() pool.connect( - assert.success(function (client, done) { + assert.success(function(client, done) { client.query('BEGIN') client.query( { @@ -74,7 +74,7 @@ suite.test('gh#36', function (cb) { text: 'SELECT $1::INTEGER', values: [0], }, - assert.calls(function (err, result) { + assert.calls(function(err, result) { if (err) throw err assert.equal(result.rows.length, 1) }) @@ -85,12 +85,12 @@ suite.test('gh#36', function (cb) { text: 'SELECT $1::INTEGER', values: [0], }, - assert.calls(function (err, result) { + assert.calls(function(err, result) { if (err) throw err assert.equal(result.rows.length, 1) }) ) - client.query('COMMIT', function () { + client.query('COMMIT', function() { done() pool.end(cb) }) diff --git a/packages/pg/test/integration/client/type-coercion-tests.js b/packages/pg/test/integration/client/type-coercion-tests.js index 96f57b08c..d2be87b87 100644 --- a/packages/pg/test/integration/client/type-coercion-tests.js +++ b/packages/pg/test/integration/client/type-coercion-tests.js @@ -4,21 +4,21 @@ var pg = helper.pg var sink const suite = new helper.Suite() -var testForTypeCoercion = function (type) { +var testForTypeCoercion = function(type) { const pool = new pg.Pool() suite.test(`test type coercion ${type.name}`, (cb) => { - pool.connect(function (err, client, done) { + pool.connect(function(err, client, done) { assert(!err) client.query( 'create temp table test_type(col ' + type.name + ')', - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) - type.values.forEach(function (val) { + type.values.forEach(function(val) { var insertQuery = client.query( 'insert into test_type(col) VALUES($1)', [val], - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) }) ) @@ -30,7 +30,7 @@ var testForTypeCoercion = function (type) { }) ) - query.on('error', function (err) { + query.on('error', function(err) { console.log(err) throw err }) @@ -38,7 +38,7 @@ var testForTypeCoercion = function (type) { assert.emits( query, 'row', - function (row) { + function(row) { var expected = val + ' (' + typeof val + ')' var returned = row.col + ' (' + typeof row.col + ')' assert.strictEqual(row.col, val, 'expected ' + type.name + ' of ' + expected + ' but got ' + returned) @@ -49,7 +49,7 @@ var testForTypeCoercion = function (type) { client.query('delete from test_type') }) - client.query('drop table test_type', function () { + client.query('drop table test_type', function() { done() pool.end(cb) }) @@ -131,18 +131,18 @@ var types = [ // ignore some tests in binary mode if (helper.config.binary) { - types = types.filter(function (type) { + types = types.filter(function(type) { return !(type.name in { real: 1, timetz: 1, time: 1, numeric: 1, bigint: 1 }) }) } var valueCount = 0 -types.forEach(function (type) { +types.forEach(function(type) { testForTypeCoercion(type) }) -suite.test('timestampz round trip', function (cb) { +suite.test('timestampz round trip', function(cb) { var now = new Date() var client = helper.client() client.query('create temp table date_tests(name varchar(10), tstz timestamptz(3))') @@ -159,7 +159,7 @@ suite.test('timestampz round trip', function (cb) { }) ) - assert.emits(result, 'row', function (row) { + assert.emits(result, 'row', function(row) { var date = row.tstz assert.equal(date.getYear(), now.getYear()) assert.equal(date.getMonth(), now.getMonth()) @@ -178,16 +178,16 @@ suite.test('timestampz round trip', function (cb) { suite.test('selecting nulls', (cb) => { const pool = new pg.Pool() pool.connect( - assert.calls(function (err, client, done) { + assert.calls(function(err, client, done) { assert.ifError(err) client.query( 'select null as res;', - assert.calls(function (err, res) { + assert.calls(function(err, res) { assert(!err) assert.strictEqual(res.rows[0].res, null) }) ) - client.query('select 7 <> $1 as res;', [null], function (err, res) { + client.query('select 7 <> $1 as res;', [null], function(err, res) { assert(!err) assert.strictEqual(res.rows[0].res, null) done() @@ -197,7 +197,7 @@ suite.test('selecting nulls', (cb) => { ) }) -suite.test('date range extremes', function (done) { +suite.test('date range extremes', function(done) { var client = helper.client() // Set the server timeszone to the same as used for the test, @@ -206,7 +206,7 @@ suite.test('date range extremes', function (done) { // in the case of "275760-09-13 00:00:00 GMT" the timevalue overflows. client.query( 'SET TIMEZONE TO GMT', - assert.success(function (res) { + assert.success(function(res) { // PostgreSQL supports date range of 4713 BCE to 294276 CE // http://www.postgresql.org/docs/9.2/static/datatype-datetime.html // ECMAScript supports date range of Apr 20 271821 BCE to Sep 13 275760 CE @@ -214,7 +214,7 @@ suite.test('date range extremes', function (done) { client.query( 'SELECT $1::TIMESTAMPTZ as when', ['275760-09-13 00:00:00 GMT'], - assert.success(function (res) { + assert.success(function(res) { assert.equal(res.rows[0].when.getFullYear(), 275760) }) ) @@ -222,7 +222,7 @@ suite.test('date range extremes', function (done) { client.query( 'SELECT $1::TIMESTAMPTZ as when', ['4713-12-31 12:31:59 BC GMT'], - assert.success(function (res) { + assert.success(function(res) { assert.equal(res.rows[0].when.getFullYear(), -4712) }) ) @@ -230,7 +230,7 @@ suite.test('date range extremes', function (done) { client.query( 'SELECT $1::TIMESTAMPTZ as when', ['275760-09-13 00:00:00 -15:00'], - assert.success(function (res) { + assert.success(function(res) { assert(isNaN(res.rows[0].when.getTime())) }) ) diff --git a/packages/pg/test/integration/client/type-parser-override-tests.js b/packages/pg/test/integration/client/type-parser-override-tests.js index 42c3dafba..c55aba3a3 100644 --- a/packages/pg/test/integration/client/type-parser-override-tests.js +++ b/packages/pg/test/integration/client/type-parser-override-tests.js @@ -7,7 +7,7 @@ function testTypeParser(client, expectedResult, done) { client.query('INSERT INTO parserOverrideTest(id) VALUES ($1)', [boolValue]) client.query( 'SELECT * FROM parserOverrideTest', - assert.success(function (result) { + assert.success(function(result) { assert.equal(result.rows[0].id, expectedResult) done() }) @@ -16,21 +16,21 @@ function testTypeParser(client, expectedResult, done) { const pool = new helper.pg.Pool(helper.config) pool.connect( - assert.success(function (client1, done1) { + assert.success(function(client1, done1) { pool.connect( - assert.success(function (client2, done2) { + assert.success(function(client2, done2) { var boolTypeOID = 16 - client1.setTypeParser(boolTypeOID, function () { + client1.setTypeParser(boolTypeOID, function() { return 'first client' }) - client2.setTypeParser(boolTypeOID, function () { + client2.setTypeParser(boolTypeOID, function() { return 'second client' }) - client1.setTypeParser(boolTypeOID, 'binary', function () { + client1.setTypeParser(boolTypeOID, 'binary', function() { return 'first client binary' }) - client2.setTypeParser(boolTypeOID, 'binary', function () { + client2.setTypeParser(boolTypeOID, 'binary', function() { return 'second client binary' }) diff --git a/packages/pg/test/integration/connection-pool/error-tests.js b/packages/pg/test/integration/connection-pool/error-tests.js index f3f9cdcaa..143e694d6 100644 --- a/packages/pg/test/integration/connection-pool/error-tests.js +++ b/packages/pg/test/integration/connection-pool/error-tests.js @@ -14,15 +14,15 @@ suite.test('errors emitted on checked-out clients', (cb) => { const pool = new pg.Pool({ max: 2 }) // get first client pool.connect( - assert.success(function (client, done) { - client.query('SELECT NOW()', function () { + assert.success(function(client, done) { + client.query('SELECT NOW()', function() { pool.connect( - assert.success(function (client2, done2) { + assert.success(function(client2, done2) { var pidColName = 'procpid' helper.versionGTE( client2, 90200, - assert.success(function (isGreater) { + assert.success(function(isGreater) { var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1' var params = ['idle'] @@ -42,7 +42,7 @@ suite.test('errors emitted on checked-out clients', (cb) => { client2.query( killIdleQuery, params, - assert.success(function (res) { + assert.success(function(res) { // check to make sure client connection actually was killed // return client2 to the pool done2() diff --git a/packages/pg/test/integration/connection-pool/idle-timeout-tests.js b/packages/pg/test/integration/connection-pool/idle-timeout-tests.js index f36b6938e..ca2a24447 100644 --- a/packages/pg/test/integration/connection-pool/idle-timeout-tests.js +++ b/packages/pg/test/integration/connection-pool/idle-timeout-tests.js @@ -1,11 +1,11 @@ 'use strict' var helper = require('./test-helper') -new helper.Suite().test('idle timeout', function () { +new helper.Suite().test('idle timeout', function() { const config = Object.assign({}, helper.config, { idleTimeoutMillis: 50 }) const pool = new helper.pg.Pool(config) pool.connect( - assert.calls(function (err, client, done) { + assert.calls(function(err, client, done) { assert(!err) client.query('SELECT NOW()') done() diff --git a/packages/pg/test/integration/connection-pool/native-instance-tests.js b/packages/pg/test/integration/connection-pool/native-instance-tests.js index a981503e8..49084828d 100644 --- a/packages/pg/test/integration/connection-pool/native-instance-tests.js +++ b/packages/pg/test/integration/connection-pool/native-instance-tests.js @@ -6,7 +6,7 @@ var native = helper.args.native var pool = new pg.Pool() pool.connect( - assert.calls(function (err, client, done) { + assert.calls(function(err, client, done) { if (native) { assert(client.native) } else { diff --git a/packages/pg/test/integration/connection-pool/test-helper.js b/packages/pg/test/integration/connection-pool/test-helper.js index 97a177a62..854d74c84 100644 --- a/packages/pg/test/integration/connection-pool/test-helper.js +++ b/packages/pg/test/integration/connection-pool/test-helper.js @@ -3,19 +3,19 @@ var helper = require('./../test-helper') const suite = new helper.Suite() -helper.testPoolSize = function (max) { +helper.testPoolSize = function(max) { suite.test(`test ${max} queries executed on a pool rapidly`, (cb) => { const pool = new helper.pg.Pool({ max: 10 }) - var sink = new helper.Sink(max, function () { + var sink = new helper.Sink(max, function() { pool.end(cb) }) for (var i = 0; i < max; i++) { - pool.connect(function (err, client, done) { + pool.connect(function(err, client, done) { assert(!err) client.query('SELECT * FROM NOW()') - client.query('select generate_series(0, 25)', function (err, result) { + client.query('select generate_series(0, 25)', function(err, result) { assert.equal(result.rows.length, 26) }) var query = client.query('SELECT * FROM NOW()', (err) => { diff --git a/packages/pg/test/integration/connection-pool/yield-support-tests.js b/packages/pg/test/integration/connection-pool/yield-support-tests.js index 00508f5d6..af7db97a9 100644 --- a/packages/pg/test/integration/connection-pool/yield-support-tests.js +++ b/packages/pg/test/integration/connection-pool/yield-support-tests.js @@ -5,7 +5,7 @@ var co = require('co') const pool = new helper.pg.Pool() new helper.Suite().test( 'using coroutines works with promises', - co.wrap(function* () { + co.wrap(function*() { var client = yield pool.connect() var res = yield client.query('SELECT $1::text as name', ['foo']) assert.equal(res.rows[0].name, 'foo') diff --git a/packages/pg/test/integration/connection/bound-command-tests.js b/packages/pg/test/integration/connection/bound-command-tests.js index a707bc4b1..e422fca3d 100644 --- a/packages/pg/test/integration/connection/bound-command-tests.js +++ b/packages/pg/test/integration/connection/bound-command-tests.js @@ -2,8 +2,8 @@ var helper = require(__dirname + '/test-helper') // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY -test('flushing once', function () { - helper.connect(function (con) { +test('flushing once', function() { + helper.connect(function(con) { con.parse({ text: 'select * from ids', }) @@ -15,35 +15,35 @@ test('flushing once', function () { assert.emits(con, 'parseComplete') assert.emits(con, 'bindComplete') assert.emits(con, 'dataRow') - assert.emits(con, 'commandComplete', function () { + assert.emits(con, 'commandComplete', function() { con.sync() }) - assert.emits(con, 'readyForQuery', function () { + assert.emits(con, 'readyForQuery', function() { con.end() }) }) }) -test('sending many flushes', function () { - helper.connect(function (con) { - assert.emits(con, 'parseComplete', function () { +test('sending many flushes', function() { + helper.connect(function(con) { + assert.emits(con, 'parseComplete', function() { con.bind() con.flush() }) - assert.emits(con, 'bindComplete', function () { + assert.emits(con, 'bindComplete', function() { con.execute() con.flush() }) - assert.emits(con, 'dataRow', function (msg) { + assert.emits(con, 'dataRow', function(msg) { assert.equal(msg.fields[0], 1) - assert.emits(con, 'dataRow', function (msg) { + assert.emits(con, 'dataRow', function(msg) { assert.equal(msg.fields[0], 2) - assert.emits(con, 'commandComplete', function () { + assert.emits(con, 'commandComplete', function() { con.sync() }) - assert.emits(con, 'readyForQuery', function () { + assert.emits(con, 'readyForQuery', function() { con.end() }) }) diff --git a/packages/pg/test/integration/connection/copy-tests.js b/packages/pg/test/integration/connection/copy-tests.js index 1b7d06ed1..78bcd3c20 100644 --- a/packages/pg/test/integration/connection/copy-tests.js +++ b/packages/pg/test/integration/connection/copy-tests.js @@ -2,16 +2,16 @@ var helper = require(__dirname + '/test-helper') var assert = require('assert') -test('COPY FROM events check', function () { - helper.connect(function (con) { +test('COPY FROM events check', function() { + helper.connect(function(con) { var stdinStream = con.query('COPY person FROM STDIN') - con.on('copyInResponse', function () { + con.on('copyInResponse', function() { con.endCopyFrom() }) assert.emits( con, 'copyInResponse', - function () { + function() { con.endCopyFrom() }, 'backend should emit copyInResponse after COPY FROM query' @@ -19,22 +19,22 @@ test('COPY FROM events check', function () { assert.emits( con, 'commandComplete', - function () { + function() { con.end() }, 'backend should emit commandComplete after COPY FROM stream ends' ) }) }) -test('COPY TO events check', function () { - helper.connect(function (con) { +test('COPY TO events check', function() { + helper.connect(function(con) { var stdoutStream = con.query('COPY person TO STDOUT') - assert.emits(con, 'copyOutResponse', function () {}, 'backend should emit copyOutResponse after COPY TO query') - assert.emits(con, 'copyData', function () {}, 'backend should emit copyData on every data row') + assert.emits(con, 'copyOutResponse', function() {}, 'backend should emit copyOutResponse after COPY TO query') + assert.emits(con, 'copyData', function() {}, 'backend should emit copyData on every data row') assert.emits( con, 'copyDone', - function () { + function() { con.end() }, 'backend should emit copyDone after all data rows' diff --git a/packages/pg/test/integration/connection/notification-tests.js b/packages/pg/test/integration/connection/notification-tests.js index 347b7ee89..700fdabae 100644 --- a/packages/pg/test/integration/connection/notification-tests.js +++ b/packages/pg/test/integration/connection/notification-tests.js @@ -1,12 +1,12 @@ 'use strict' var helper = require(__dirname + '/test-helper') // http://www.postgresql.org/docs/8.3/static/libpq-notify.html -test('recieves notification from same connection with no payload', function () { - helper.connect(function (con) { +test('recieves notification from same connection with no payload', function() { + helper.connect(function(con) { con.query('LISTEN boom') - assert.emits(con, 'readyForQuery', function () { + assert.emits(con, 'readyForQuery', function() { con.query('NOTIFY boom') - assert.emits(con, 'notification', function (msg) { + assert.emits(con, 'notification', function(msg) { assert.equal(msg.payload, '') assert.equal(msg.channel, 'boom') con.end() diff --git a/packages/pg/test/integration/connection/query-tests.js b/packages/pg/test/integration/connection/query-tests.js index 70c39c322..661019558 100644 --- a/packages/pg/test/integration/connection/query-tests.js +++ b/packages/pg/test/integration/connection/query-tests.js @@ -5,20 +5,20 @@ var assert = require('assert') var rows = [] // testing the low level 1-1 mapping api of client to postgres messages // it's cumbersome to use the api this way -test('simple query', function () { - helper.connect(function (con) { +test('simple query', function() { + helper.connect(function(con) { con.query('select * from ids') assert.emits(con, 'dataRow') - con.on('dataRow', function (msg) { + con.on('dataRow', function(msg) { rows.push(msg.fields) }) - assert.emits(con, 'readyForQuery', function () { + assert.emits(con, 'readyForQuery', function() { con.end() }) }) }) -process.on('exit', function () { +process.on('exit', function() { assert.equal(rows.length, 2) assert.equal(rows[0].length, 1) assert.strictEqual(String(rows[0][0]), '1') diff --git a/packages/pg/test/integration/connection/test-helper.js b/packages/pg/test/integration/connection/test-helper.js index ca978af4f..ae88bfc4d 100644 --- a/packages/pg/test/integration/connection/test-helper.js +++ b/packages/pg/test/integration/connection/test-helper.js @@ -3,31 +3,31 @@ var net = require('net') var helper = require(__dirname + '/../test-helper') var Connection = require(__dirname + '/../../../lib/connection') var utils = require(__dirname + '/../../../lib/utils') -var connect = function (callback) { +var connect = function(callback) { var username = helper.args.user var database = helper.args.database var con = new Connection({ stream: new net.Stream() }) - con.on('error', function (error) { + con.on('error', function(error) { console.log(error) throw new Error('Connection error') }) con.connect(helper.args.port || '5432', helper.args.host || 'localhost') - con.once('connect', function () { + con.once('connect', function() { con.startup({ user: username, database: database, }) - con.once('authenticationCleartextPassword', function () { + con.once('authenticationCleartextPassword', function() { con.password(helper.args.password) }) - con.once('authenticationMD5Password', function (msg) { + con.once('authenticationMD5Password', function(msg) { con.password(utils.postgresMd5PasswordHash(helper.args.user, helper.args.password, msg.salt)) }) - con.once('readyForQuery', function () { + con.once('readyForQuery', function() { con.query('create temp table ids(id integer)') - con.once('readyForQuery', function () { + con.once('readyForQuery', function() { con.query('insert into ids(id) values(1); insert into ids(id) values(2);') - con.once('readyForQuery', function () { + con.once('readyForQuery', function() { callback(con) }) }) diff --git a/packages/pg/test/integration/domain-tests.js b/packages/pg/test/integration/domain-tests.js index ce46eb8a4..6d3f2f71f 100644 --- a/packages/pg/test/integration/domain-tests.js +++ b/packages/pg/test/integration/domain-tests.js @@ -7,11 +7,11 @@ var suite = new helper.Suite() const Pool = helper.pg.Pool -suite.test('no domain', function (cb) { +suite.test('no domain', function(cb) { assert(!process.domain) const pool = new Pool() pool.connect( - assert.success(function (client, done) { + assert.success(function(client, done) { assert(!process.domain) done() pool.end(cb) @@ -19,20 +19,20 @@ suite.test('no domain', function (cb) { ) }) -suite.test('with domain', function (cb) { +suite.test('with domain', function(cb) { assert(!process.domain) const pool = new Pool() var domain = require('domain').create() - domain.run(function () { + domain.run(function() { var startingDomain = process.domain assert(startingDomain) pool.connect( - assert.success(function (client, done) { + assert.success(function(client, done) { assert(process.domain, 'no domain exists in connect callback') assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') var query = client.query( 'SELECT NOW()', - assert.success(function () { + assert.success(function() { assert(process.domain, 'no domain exists in query callback') assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') done(true) @@ -45,15 +45,15 @@ suite.test('with domain', function (cb) { }) }) -suite.test('error on domain', function (cb) { +suite.test('error on domain', function(cb) { var domain = require('domain').create() const pool = new Pool() - domain.on('error', function () { + domain.on('error', function() { pool.end(cb) }) - domain.run(function () { + domain.run(function() { pool.connect( - assert.success(function (client, done) { + assert.success(function(client, done) { client.query(new Query('SELECT SLDKJFLSKDJF')) client.on('drain', done) }) diff --git a/packages/pg/test/integration/gh-issues/130-tests.js b/packages/pg/test/integration/gh-issues/130-tests.js index 8b097b99b..252d75768 100644 --- a/packages/pg/test/integration/gh-issues/130-tests.js +++ b/packages/pg/test/integration/gh-issues/130-tests.js @@ -5,13 +5,13 @@ var exec = require('child_process').exec helper.pg.defaults.poolIdleTimeout = 1000 const pool = new helper.pg.Pool() -pool.connect(function (err, client, done) { +pool.connect(function(err, client, done) { assert.ifError(err) - client.once('error', function (err) { + client.once('error', function(err) { client.on('error', (err) => {}) done(err) }) - client.query('SELECT pg_backend_pid()', function (err, result) { + client.query('SELECT pg_backend_pid()', function(err, result) { assert.ifError(err) var pid = result.rows[0].pg_backend_pid var psql = 'psql' @@ -20,7 +20,7 @@ pool.connect(function (err, client, done) { if (helper.args.user) psql = psql + ' -U ' + helper.args.user exec( psql + ' -c "select pg_terminate_backend(' + pid + ')" template1', - assert.calls(function (error, stdout, stderr) { + assert.calls(function(error, stdout, stderr) { assert.ifError(error) }) ) diff --git a/packages/pg/test/integration/gh-issues/131-tests.js b/packages/pg/test/integration/gh-issues/131-tests.js index 5838067fc..0ebad8d97 100644 --- a/packages/pg/test/integration/gh-issues/131-tests.js +++ b/packages/pg/test/integration/gh-issues/131-tests.js @@ -4,10 +4,10 @@ var pg = helper.pg var suite = new helper.Suite() -suite.test('parsing array decimal results', function (done) { +suite.test('parsing array decimal results', function(done) { const pool = new pg.Pool() pool.connect( - assert.calls(function (err, client, release) { + assert.calls(function(err, client, release) { assert(!err) client.query('CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])') client @@ -19,7 +19,7 @@ suite.test('parsing array decimal results', function (done) { .on('error', console.log) client.query( 'SELECT decimals FROM why', - assert.success(function (result) { + assert.success(function(result) { assert.lengthIs(result.rows[0].decimals, 3) assert.equal(result.rows[0].decimals[0], 0.1) assert.equal(result.rows[0].decimals[1], 0.05) diff --git a/packages/pg/test/integration/gh-issues/1854-tests.js b/packages/pg/test/integration/gh-issues/1854-tests.js index 92ac6ec35..e63df5c6f 100644 --- a/packages/pg/test/integration/gh-issues/1854-tests.js +++ b/packages/pg/test/integration/gh-issues/1854-tests.js @@ -14,7 +14,7 @@ suite.test('Parameter serialization errors should not cause query to hang', (don .connect() .then(() => { const obj = { - toPostgres: function () { + toPostgres: function() { throw expectedErr }, } diff --git a/packages/pg/test/integration/gh-issues/199-tests.js b/packages/pg/test/integration/gh-issues/199-tests.js index 2710020c5..dc74963f1 100644 --- a/packages/pg/test/integration/gh-issues/199-tests.js +++ b/packages/pg/test/integration/gh-issues/199-tests.js @@ -12,7 +12,7 @@ ARRAY['xx', 'yy', 'zz'] AS c,\ ARRAY(SELECT n FROM arrtest) AS d,\ ARRAY(SELECT s FROM arrtest) AS e;" -client.query(qText, function (err, result) { +client.query(qText, function(err, result) { if (err) throw err var row = result.rows[0] for (var key in row) { diff --git a/packages/pg/test/integration/gh-issues/507-tests.js b/packages/pg/test/integration/gh-issues/507-tests.js index 9c3409199..958e28241 100644 --- a/packages/pg/test/integration/gh-issues/507-tests.js +++ b/packages/pg/test/integration/gh-issues/507-tests.js @@ -2,13 +2,13 @@ var helper = require(__dirname + '/../test-helper') var pg = helper.pg -new helper.Suite().test('parsing array results', function (cb) { +new helper.Suite().test('parsing array results', function(cb) { const pool = new pg.Pool() pool.connect( - assert.success(function (client, done) { + assert.success(function(client, done) { client.query('CREATE TEMP TABLE test_table(bar integer, "baz\'s" integer)') client.query('INSERT INTO test_table(bar, "baz\'s") VALUES(1, 1), (2, 2)') - client.query('SELECT * FROM test_table', function (err, res) { + client.query('SELECT * FROM test_table', function(err, res) { assert.equal(res.rows[0]["baz's"], 1) assert.equal(res.rows[1]["baz's"], 2) done() diff --git a/packages/pg/test/integration/gh-issues/600-tests.js b/packages/pg/test/integration/gh-issues/600-tests.js index af679ee8e..84a7124bd 100644 --- a/packages/pg/test/integration/gh-issues/600-tests.js +++ b/packages/pg/test/integration/gh-issues/600-tests.js @@ -45,9 +45,9 @@ function endTransaction(callback) { function doTransaction(callback) { // The transaction runs startTransaction, then all queries, then endTransaction, // no matter if there has been an error in a query in the middle. - startTransaction(function () { - insertDataFoo(function () { - insertDataBar(function () { + startTransaction(function() { + insertDataFoo(function() { + insertDataBar(function() { endTransaction(callback) }) }) @@ -56,17 +56,17 @@ function doTransaction(callback) { var steps = [createTableFoo, createTableBar, doTransaction, insertDataBar] -suite.test('test if query fails', function (done) { +suite.test('test if query fails', function(done) { async.series( steps, - assert.success(function () { + assert.success(function() { db.end() done() }) ) }) -suite.test('test if prepare works but bind fails', function (done) { +suite.test('test if prepare works but bind fails', function(done) { var client = helper.client() var q = { text: 'SELECT $1::int as name', @@ -75,11 +75,11 @@ suite.test('test if prepare works but bind fails', function (done) { } client.query( q, - assert.calls(function (err, res) { + assert.calls(function(err, res) { q.values = [1] client.query( q, - assert.calls(function (err, res) { + assert.calls(function(err, res) { assert.ifError(err) client.end() done() diff --git a/packages/pg/test/integration/gh-issues/675-tests.js b/packages/pg/test/integration/gh-issues/675-tests.js index 2e281ecc6..31f57589d 100644 --- a/packages/pg/test/integration/gh-issues/675-tests.js +++ b/packages/pg/test/integration/gh-issues/675-tests.js @@ -3,22 +3,22 @@ var helper = require('../test-helper') var assert = require('assert') const pool = new helper.pg.Pool() -pool.connect(function (err, client, done) { +pool.connect(function(err, client, done) { if (err) throw err var c = 'CREATE TEMP TABLE posts (body TEXT)' - client.query(c, function (err) { + client.query(c, function(err) { if (err) throw err c = 'INSERT INTO posts (body) VALUES ($1) RETURNING *' var body = Buffer.from('foo') - client.query(c, [body], function (err) { + client.query(c, [body], function(err) { if (err) throw err body = Buffer.from([]) - client.query(c, [body], function (err, res) { + client.query(c, [body], function(err, res) { done() if (err) throw err diff --git a/packages/pg/test/integration/gh-issues/699-tests.js b/packages/pg/test/integration/gh-issues/699-tests.js index c9be63bfa..2ce1d0069 100644 --- a/packages/pg/test/integration/gh-issues/699-tests.js +++ b/packages/pg/test/integration/gh-issues/699-tests.js @@ -6,16 +6,16 @@ var copyFrom = require('pg-copy-streams').from if (helper.args.native) return const pool = new helper.pg.Pool() -pool.connect(function (err, client, done) { +pool.connect(function(err, client, done) { if (err) throw err var c = 'CREATE TEMP TABLE employee (id integer, fname varchar(400), lname varchar(400))' - client.query(c, function (err) { + client.query(c, function(err) { if (err) throw err var stream = client.query(copyFrom('COPY employee FROM STDIN')) - stream.on('end', function () { + stream.on('end', function() { done() setTimeout(() => { pool.end() diff --git a/packages/pg/test/integration/gh-issues/787-tests.js b/packages/pg/test/integration/gh-issues/787-tests.js index 9a3198f52..81fb27705 100644 --- a/packages/pg/test/integration/gh-issues/787-tests.js +++ b/packages/pg/test/integration/gh-issues/787-tests.js @@ -2,13 +2,13 @@ var helper = require('../test-helper') const pool = new helper.pg.Pool() -pool.connect(function (err, client) { +pool.connect(function(err, client) { var q = { name: 'This is a super long query name just so I can test that an error message is properly spit out to console.error without throwing an exception or anything', text: 'SELECT NOW()', } - client.query(q, function () { + client.query(q, function() { client.end() }) }) diff --git a/packages/pg/test/integration/gh-issues/882-tests.js b/packages/pg/test/integration/gh-issues/882-tests.js index 4a8ef6474..324de2e6f 100644 --- a/packages/pg/test/integration/gh-issues/882-tests.js +++ b/packages/pg/test/integration/gh-issues/882-tests.js @@ -4,6 +4,6 @@ var helper = require('../test-helper') var client = helper.client() client.query({ name: 'foo1', text: null }) client.query({ name: 'foo2', text: ' ' }) -client.query({ name: 'foo3', text: '' }, function (err, res) { +client.query({ name: 'foo3', text: '' }, function(err, res) { client.end() }) diff --git a/packages/pg/test/integration/gh-issues/981-tests.js b/packages/pg/test/integration/gh-issues/981-tests.js index 998adea3a..49ac7916c 100644 --- a/packages/pg/test/integration/gh-issues/981-tests.js +++ b/packages/pg/test/integration/gh-issues/981-tests.js @@ -21,7 +21,7 @@ const nativePool = new native.Pool() const suite = new helper.Suite() suite.test('js pool returns js client', (cb) => { - jsPool.connect(function (err, client, done) { + jsPool.connect(function(err, client, done) { assert(client instanceof JsClient) done() jsPool.end(cb) @@ -29,7 +29,7 @@ suite.test('js pool returns js client', (cb) => { }) suite.test('native pool returns native client', (cb) => { - nativePool.connect(function (err, client, done) { + nativePool.connect(function(err, client, done) { assert(client instanceof NativeClient) done() nativePool.end(cb) diff --git a/packages/pg/test/integration/test-helper.js b/packages/pg/test/integration/test-helper.js index 9b8b58c60..5a603946d 100644 --- a/packages/pg/test/integration/test-helper.js +++ b/packages/pg/test/integration/test-helper.js @@ -8,16 +8,16 @@ if (helper.args.native) { } // creates a client from cli parameters -helper.client = function (cb) { +helper.client = function(cb) { var client = new Client() client.connect(cb) return client } -helper.versionGTE = function (client, testVersion, callback) { +helper.versionGTE = function(client, testVersion, callback) { client.query( 'SHOW server_version_num', - assert.calls(function (err, result) { + assert.calls(function(err, result) { if (err) return callback(err) var version = parseInt(result.rows[0].server_version_num, 10) return callback(null, version >= testVersion) diff --git a/packages/pg/test/native/callback-api-tests.js b/packages/pg/test/native/callback-api-tests.js index 80fdcdf56..d4be9d473 100644 --- a/packages/pg/test/native/callback-api-tests.js +++ b/packages/pg/test/native/callback-api-tests.js @@ -4,19 +4,19 @@ var helper = require('./../test-helper') var Client = require('./../../lib/native') const suite = new helper.Suite() -suite.test('fires callback with results', function (done) { +suite.test('fires callback with results', function(done) { var client = new Client(helper.config) client.connect() client.query( 'SELECT 1 as num', - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) assert.equal(result.rows[0].num, 1) assert.strictEqual(result.rowCount, 1) client.query( 'SELECT * FROM person WHERE name = $1', ['Brian'], - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(!err) assert.equal(result.rows[0].name, 'Brian') client.end(done) @@ -26,14 +26,14 @@ suite.test('fires callback with results', function (done) { ) }) -suite.test('preserves domain', function (done) { +suite.test('preserves domain', function(done) { var dom = domain.create() - dom.run(function () { + dom.run(function() { var client = new Client(helper.config) assert.ok(dom === require('domain').active, 'domain is active') client.connect() - client.query('select 1', function () { + client.query('select 1', function() { assert.ok(dom === require('domain').active, 'domain is still active') client.end(done) }) diff --git a/packages/pg/test/native/evented-api-tests.js b/packages/pg/test/native/evented-api-tests.js index ba0496eff..7bed1632a 100644 --- a/packages/pg/test/native/evented-api-tests.js +++ b/packages/pg/test/native/evented-api-tests.js @@ -3,7 +3,7 @@ var helper = require('../test-helper') var Client = require('../../lib/native') var Query = Client.Query -var setupClient = function () { +var setupClient = function() { var client = new Client(helper.config) client.connect() client.query('CREATE TEMP TABLE boom(name varchar(10), age integer)') @@ -12,22 +12,22 @@ var setupClient = function () { return client } -test('multiple results', function () { - test('queued queries', function () { +test('multiple results', function() { + test('queued queries', function() { var client = setupClient() var q = client.query(new Query('SELECT name FROM BOOM')) - assert.emits(q, 'row', function (row) { + assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Aaron') - assert.emits(q, 'row', function (row) { + assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Brian') }) }) - assert.emits(q, 'end', function () { - test('query with config', function () { + assert.emits(q, 'end', function() { + test('query with config', function() { var q2 = client.query(new Query({ text: 'SELECT 1 as num' })) - assert.emits(q2, 'row', function (row) { + assert.emits(q2, 'row', function(row) { assert.strictEqual(row.num, 1) - assert.emits(q2, 'end', function () { + assert.emits(q2, 'end', function() { client.end() }) }) @@ -36,19 +36,19 @@ test('multiple results', function () { }) }) -test('parameterized queries', function () { - test('with a single string param', function () { +test('parameterized queries', function() { + test('with a single string param', function() { var client = setupClient() var q = client.query(new Query('SELECT * FROM boom WHERE name = $1', ['Aaron'])) - assert.emits(q, 'row', function (row) { + assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Aaron') }) - assert.emits(q, 'end', function () { + assert.emits(q, 'end', function() { client.end() }) }) - test('with object config for query', function () { + test('with object config for query', function() { var client = setupClient() var q = client.query( new Query({ @@ -56,38 +56,38 @@ test('parameterized queries', function () { values: ['Brian'], }) ) - assert.emits(q, 'row', function (row) { + assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Brian') }) - assert.emits(q, 'end', function () { + assert.emits(q, 'end', function() { client.end() }) }) - test('multiple parameters', function () { + test('multiple parameters', function() { var client = setupClient() var q = client.query( new Query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name COLLATE "C"', ['Aaron', 'Brian']) ) - assert.emits(q, 'row', function (row) { + assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Aaron') - assert.emits(q, 'row', function (row) { + assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Brian') - assert.emits(q, 'end', function () { + assert.emits(q, 'end', function() { client.end() }) }) }) }) - test('integer parameters', function () { + test('integer parameters', function() { var client = setupClient() var q = client.query(new Query('SELECT * FROM boom WHERE age > $1', [27])) - assert.emits(q, 'row', function (row) { + assert.emits(q, 'row', function(row) { assert.equal(row.name, 'Brian') assert.equal(row.age, 28) }) - assert.emits(q, 'end', function () { + assert.emits(q, 'end', function() { client.end() }) }) diff --git a/packages/pg/test/native/stress-tests.js b/packages/pg/test/native/stress-tests.js index 49904b12a..c6a8cac88 100644 --- a/packages/pg/test/native/stress-tests.js +++ b/packages/pg/test/native/stress-tests.js @@ -3,48 +3,48 @@ var helper = require(__dirname + '/../test-helper') var Client = require(__dirname + '/../../lib/native') var Query = Client.Query -test('many rows', function () { +test('many rows', function() { var client = new Client(helper.config) client.connect() var q = client.query(new Query('SELECT * FROM person')) var rows = [] - q.on('row', function (row) { + q.on('row', function(row) { rows.push(row) }) - assert.emits(q, 'end', function () { + assert.emits(q, 'end', function() { client.end() assert.lengthIs(rows, 26) }) }) -test('many queries', function () { +test('many queries', function() { var client = new Client(helper.config) client.connect() var count = 0 var expected = 100 for (var i = 0; i < expected; i++) { var q = client.query(new Query('SELECT * FROM person')) - assert.emits(q, 'end', function () { + assert.emits(q, 'end', function() { count++ }) } - assert.emits(client, 'drain', function () { + assert.emits(client, 'drain', function() { client.end() assert.equal(count, expected) }) }) -test('many clients', function () { +test('many clients', function() { var clients = [] for (var i = 0; i < 10; i++) { clients.push(new Client(helper.config)) } - clients.forEach(function (client) { + clients.forEach(function(client) { client.connect() for (var i = 0; i < 20; i++) { client.query('SELECT * FROM person') } - assert.emits(client, 'drain', function () { + assert.emits(client, 'drain', function() { client.end() }) }) diff --git a/packages/pg/test/test-buffers.js b/packages/pg/test/test-buffers.js index 9fdd889d4..573056bce 100644 --- a/packages/pg/test/test-buffers.js +++ b/packages/pg/test/test-buffers.js @@ -3,54 +3,70 @@ require(__dirname + '/test-helper') // http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html var buffers = {} -buffers.readyForQuery = function () { +buffers.readyForQuery = function() { return new BufferList().add(Buffer.from('I')).join(true, 'Z') } -buffers.authenticationOk = function () { +buffers.authenticationOk = function() { return new BufferList().addInt32(0).join(true, 'R') } -buffers.authenticationCleartextPassword = function () { +buffers.authenticationCleartextPassword = function() { return new BufferList().addInt32(3).join(true, 'R') } -buffers.authenticationMD5Password = function () { +buffers.authenticationMD5Password = function() { return new BufferList() .addInt32(5) .add(Buffer.from([1, 2, 3, 4])) .join(true, 'R') } -buffers.authenticationSASL = function () { - return new BufferList().addInt32(10).addCString('SCRAM-SHA-256').addCString('').join(true, 'R') +buffers.authenticationSASL = function() { + return new BufferList() + .addInt32(10) + .addCString('SCRAM-SHA-256') + .addCString('') + .join(true, 'R') } -buffers.authenticationSASLContinue = function () { - return new BufferList().addInt32(11).addString('data').join(true, 'R') +buffers.authenticationSASLContinue = function() { + return new BufferList() + .addInt32(11) + .addString('data') + .join(true, 'R') } -buffers.authenticationSASLFinal = function () { - return new BufferList().addInt32(12).addString('data').join(true, 'R') +buffers.authenticationSASLFinal = function() { + return new BufferList() + .addInt32(12) + .addString('data') + .join(true, 'R') } -buffers.parameterStatus = function (name, value) { - return new BufferList().addCString(name).addCString(value).join(true, 'S') +buffers.parameterStatus = function(name, value) { + return new BufferList() + .addCString(name) + .addCString(value) + .join(true, 'S') } -buffers.backendKeyData = function (processID, secretKey) { - return new BufferList().addInt32(processID).addInt32(secretKey).join(true, 'K') +buffers.backendKeyData = function(processID, secretKey) { + return new BufferList() + .addInt32(processID) + .addInt32(secretKey) + .join(true, 'K') } -buffers.commandComplete = function (string) { +buffers.commandComplete = function(string) { return new BufferList().addCString(string).join(true, 'C') } -buffers.rowDescription = function (fields) { +buffers.rowDescription = function(fields) { fields = fields || [] var buf = new BufferList() buf.addInt16(fields.length) - fields.forEach(function (field) { + fields.forEach(function(field) { buf .addCString(field.name) .addInt32(field.tableID || 0) @@ -63,11 +79,11 @@ buffers.rowDescription = function (fields) { return buf.join(true, 'T') } -buffers.dataRow = function (columns) { +buffers.dataRow = function(columns) { columns = columns || [] var buf = new BufferList() buf.addInt16(columns.length) - columns.forEach(function (col) { + columns.forEach(function(col) { if (col == null) { buf.addInt32(-1) } else { @@ -79,41 +95,45 @@ buffers.dataRow = function (columns) { return buf.join(true, 'D') } -buffers.error = function (fields) { +buffers.error = function(fields) { return errorOrNotice(fields).join(true, 'E') } -buffers.notice = function (fields) { +buffers.notice = function(fields) { return errorOrNotice(fields).join(true, 'N') } -var errorOrNotice = function (fields) { +var errorOrNotice = function(fields) { fields = fields || [] var buf = new BufferList() - fields.forEach(function (field) { + fields.forEach(function(field) { buf.addChar(field.type) buf.addCString(field.value) }) return buf.add(Buffer.from([0])) // terminator } -buffers.parseComplete = function () { +buffers.parseComplete = function() { return new BufferList().join(true, '1') } -buffers.bindComplete = function () { +buffers.bindComplete = function() { return new BufferList().join(true, '2') } -buffers.notification = function (id, channel, payload) { - return new BufferList().addInt32(id).addCString(channel).addCString(payload).join(true, 'A') +buffers.notification = function(id, channel, payload) { + return new BufferList() + .addInt32(id) + .addCString(channel) + .addCString(payload) + .join(true, 'A') } -buffers.emptyQuery = function () { +buffers.emptyQuery = function() { return new BufferList().join(true, 'I') } -buffers.portalSuspended = function () { +buffers.portalSuspended = function() { return new BufferList().join(true, 's') } diff --git a/packages/pg/test/test-helper.js b/packages/pg/test/test-helper.js index 8159e387c..0fd6b222e 100644 --- a/packages/pg/test/test-helper.js +++ b/packages/pg/test/test-helper.js @@ -12,7 +12,7 @@ var Connection = require('./../lib/connection') global.Client = require('./../lib').Client -process.on('uncaughtException', function (d) { +process.on('uncaughtException', function(d) { if ('stack' in d && 'message' in d) { console.log('Message: ' + d.message) console.log(d.stack) @@ -22,21 +22,21 @@ process.on('uncaughtException', function (d) { process.exit(-1) }) -assert.same = function (actual, expected) { +assert.same = function(actual, expected) { for (var key in expected) { assert.equal(actual[key], expected[key]) } } -assert.emits = function (item, eventName, callback, message) { +assert.emits = function(item, eventName, callback, message) { var called = false - var id = setTimeout(function () { - test("Should have called '" + eventName + "' event", function () { + var id = setTimeout(function() { + test("Should have called '" + eventName + "' event", function() { assert.ok(called, message || "Expected '" + eventName + "' to be called.") }) }, 5000) - item.once(eventName, function () { + item.once(eventName, function() { if (eventName === 'error') { // belt and braces test to ensure all error events return an error assert.ok( @@ -53,7 +53,7 @@ assert.emits = function (item, eventName, callback, message) { }) } -assert.UTCDate = function (actual, year, month, day, hours, min, sec, milisecond) { +assert.UTCDate = function(actual, year, month, day, hours, min, sec, milisecond) { var actualYear = actual.getUTCFullYear() assert.equal(actualYear, year, 'expected year ' + year + ' but got ' + actualYear) @@ -76,7 +76,7 @@ assert.UTCDate = function (actual, year, month, day, hours, min, sec, milisecond assert.equal(actualMili, milisecond, 'expected milisecond ' + milisecond + ' but got ' + actualMili) } -assert.equalBuffers = function (actual, expected) { +assert.equalBuffers = function(actual, expected) { if (actual.length != expected.length) { spit(actual, expected) assert.equal(actual.length, expected.length) @@ -89,13 +89,13 @@ assert.equalBuffers = function (actual, expected) { } } -assert.empty = function (actual) { +assert.empty = function(actual) { assert.lengthIs(actual, 0) } -assert.success = function (callback) { +assert.success = function(callback) { if (callback.length === 1 || callback.length === 0) { - return assert.calls(function (err, arg) { + return assert.calls(function(err, arg) { if (err) { console.log(err) } @@ -103,7 +103,7 @@ assert.success = function (callback) { callback(arg) }) } else if (callback.length === 2) { - return assert.calls(function (err, arg1, arg2) { + return assert.calls(function(err, arg1, arg2) { if (err) { console.log(err) } @@ -115,7 +115,7 @@ assert.success = function (callback) { } } -assert.throws = function (offender) { +assert.throws = function(offender) { try { offender() } catch (e) { @@ -125,14 +125,14 @@ assert.throws = function (offender) { assert.ok(false, 'Expected ' + offender + ' to throw exception') } -assert.lengthIs = function (actual, expectedLength) { +assert.lengthIs = function(actual, expectedLength) { assert.equal(actual.length, expectedLength) } -var expect = function (callback, timeout) { +var expect = function(callback, timeout) { var executed = false timeout = timeout || parseInt(process.env.TEST_TIMEOUT) || 5000 - var id = setTimeout(function () { + var id = setTimeout(function() { assert.ok( executed, 'Expected execution of function to be fired within ' + @@ -145,7 +145,7 @@ var expect = function (callback, timeout) { }, timeout) if (callback.length < 3) { - return function (err, queryResult) { + return function(err, queryResult) { clearTimeout(id) if (err) { assert.ok(err instanceof Error, 'Expected errors to be instances of Error: ' + sys.inspect(err)) @@ -153,7 +153,7 @@ var expect = function (callback, timeout) { callback.apply(this, arguments) } } else if (callback.length == 3) { - return function (err, arg1, arg2) { + return function(err, arg1, arg2) { clearTimeout(id) if (err) { assert.ok(err instanceof Error, 'Expected errors to be instances of Error: ' + sys.inspect(err)) @@ -166,7 +166,7 @@ var expect = function (callback, timeout) { } assert.calls = expect -assert.isNull = function (item, message) { +assert.isNull = function(item, message) { message = message || 'expected ' + item + ' to be null' assert.ok(item === null, message) } @@ -177,7 +177,7 @@ const getMode = () => { return '' } -global.test = function (name, action) { +global.test = function(name, action) { test.testCount++ test[name] = action var result = test[name]() @@ -193,11 +193,11 @@ process.stdout.write(require('path').basename(process.argv[1])) if (args.binary) process.stdout.write(' (binary)') if (args.native) process.stdout.write(' (native)') -process.on('exit', function () { +process.on('exit', function() { console.log('') }) -process.on('uncaughtException', function (err) { +process.on('uncaughtException', function(err) { console.error('\n %s', err.stack || err.toString()) // causes xargs to abort right away process.exit(255) @@ -205,7 +205,7 @@ process.on('uncaughtException', function (err) { var count = 0 -var Sink = function (expected, timeout, callback) { +var Sink = function(expected, timeout, callback) { var defaultTimeout = 5000 if (typeof timeout === 'function') { callback = timeout @@ -213,12 +213,12 @@ var Sink = function (expected, timeout, callback) { } timeout = timeout || defaultTimeout var internalCount = 0 - var kill = function () { + var kill = function() { assert.ok(false, 'Did not reach expected ' + expected + ' with an idle timeout of ' + timeout) } var killTimeout = setTimeout(kill, timeout) return { - add: function (count) { + add: function(count) { count = count || 1 internalCount += count clearTimeout(killTimeout) @@ -234,13 +234,13 @@ var Sink = function (expected, timeout, callback) { var getTimezoneOffset = Date.prototype.getTimezoneOffset -var setTimezoneOffset = function (minutesOffset) { - Date.prototype.getTimezoneOffset = function () { +var setTimezoneOffset = function(minutesOffset) { + Date.prototype.getTimezoneOffset = function() { return minutesOffset } } -var resetTimezoneOffset = function () { +var resetTimezoneOffset = function() { Date.prototype.getTimezoneOffset = getTimezoneOffset } diff --git a/packages/pg/test/unit/client/cleartext-password-tests.js b/packages/pg/test/unit/client/cleartext-password-tests.js index cd8dbb005..de28136e0 100644 --- a/packages/pg/test/unit/client/cleartext-password-tests.js +++ b/packages/pg/test/unit/client/cleartext-password-tests.js @@ -7,12 +7,12 @@ const createClient = require('./test-helper').createClient * code-being-tested works behind the scenes. */ -test('cleartext password authentication', function () { +test('cleartext password authentication', function() { var client = createClient() client.password = '!' client.connection.stream.packets = [] client.connection.emit('authenticationCleartextPassword') - test('responds with password', function () { + test('responds with password', function() { var packets = client.connection.stream.packets assert.lengthIs(packets, 1) var packet = packets[0] diff --git a/packages/pg/test/unit/client/configuration-tests.js b/packages/pg/test/unit/client/configuration-tests.js index e6cbc0dcc..f51e9a9e4 100644 --- a/packages/pg/test/unit/client/configuration-tests.js +++ b/packages/pg/test/unit/client/configuration-tests.js @@ -5,8 +5,8 @@ var pguser = process.env['PGUSER'] || process.env.USER var pgdatabase = process.env['PGDATABASE'] || process.env.USER var pgport = process.env['PGPORT'] || 5432 -test('client settings', function () { - test('defaults', function () { +test('client settings', function() { + test('defaults', function() { var client = new Client() assert.equal(client.user, pguser) assert.equal(client.database, pgdatabase) @@ -14,7 +14,7 @@ test('client settings', function () { assert.equal(client.ssl, false) }) - test('custom', function () { + test('custom', function() { var user = 'brian' var database = 'pgjstest' var password = 'boom' @@ -33,7 +33,7 @@ test('client settings', function () { assert.equal(client.ssl, true) }) - test('custom ssl default on', function () { + test('custom ssl default on', function() { var old = process.env.PGSSLMODE process.env.PGSSLMODE = 'prefer' @@ -43,7 +43,7 @@ test('client settings', function () { assert.equal(client.ssl, true) }) - test('custom ssl force off', function () { + test('custom ssl force off', function() { var old = process.env.PGSSLMODE process.env.PGSSLMODE = 'prefer' @@ -56,8 +56,8 @@ test('client settings', function () { }) }) -test('initializing from a config string', function () { - test('uses connectionString property', function () { +test('initializing from a config string', function() { + test('uses connectionString property', function() { var client = new Client({ connectionString: 'postgres://brian:pass@host1:333/databasename', }) @@ -68,7 +68,7 @@ test('initializing from a config string', function () { assert.equal(client.database, 'databasename') }) - test('uses the correct values from the config string', function () { + test('uses the correct values from the config string', function() { var client = new Client('postgres://brian:pass@host1:333/databasename') assert.equal(client.user, 'brian') assert.equal(client.password, 'pass') @@ -77,7 +77,7 @@ test('initializing from a config string', function () { assert.equal(client.database, 'databasename') }) - test('uses the correct values from the config string with space in password', function () { + test('uses the correct values from the config string with space in password', function() { var client = new Client('postgres://brian:pass word@host1:333/databasename') assert.equal(client.user, 'brian') assert.equal(client.password, 'pass word') @@ -86,7 +86,7 @@ test('initializing from a config string', function () { assert.equal(client.database, 'databasename') }) - test('when not including all values the defaults are used', function () { + test('when not including all values the defaults are used', function() { var client = new Client('postgres://host1') assert.equal(client.user, process.env['PGUSER'] || process.env.USER) assert.equal(client.password, process.env['PGPASSWORD'] || null) @@ -95,7 +95,7 @@ test('initializing from a config string', function () { assert.equal(client.database, process.env['PGDATABASE'] || process.env.USER) }) - test('when not including all values the environment variables are used', function () { + test('when not including all values the environment variables are used', function() { var envUserDefined = process.env['PGUSER'] !== undefined var envPasswordDefined = process.env['PGPASSWORD'] !== undefined var envDBDefined = process.env['PGDATABASE'] !== undefined @@ -153,11 +153,11 @@ test('initializing from a config string', function () { }) }) -test('calls connect correctly on connection', function () { +test('calls connect correctly on connection', function() { var client = new Client('/tmp') var usedPort = '' var usedHost = '' - client.connection.connect = function (port, host) { + client.connection.connect = function(port, host) { usedPort = port usedHost = host } diff --git a/packages/pg/test/unit/client/early-disconnect-tests.js b/packages/pg/test/unit/client/early-disconnect-tests.js index 494482845..a741a0c68 100644 --- a/packages/pg/test/unit/client/early-disconnect-tests.js +++ b/packages/pg/test/unit/client/early-disconnect-tests.js @@ -4,15 +4,15 @@ var net = require('net') var pg = require('../../../lib/index.js') /* console.log() messages show up in `make test` output. TODO: fix it. */ -var server = net.createServer(function (c) { +var server = net.createServer(function(c) { c.destroy() server.close() }) -server.listen(7777, function () { +server.listen(7777, function() { var client = new pg.Client('postgres://localhost:7777') client.connect( - assert.calls(function (err) { + assert.calls(function(err) { assert(err) }) ) diff --git a/packages/pg/test/unit/client/escape-tests.js b/packages/pg/test/unit/client/escape-tests.js index 7f96a832d..dae361ffe 100644 --- a/packages/pg/test/unit/client/escape-tests.js +++ b/packages/pg/test/unit/client/escape-tests.js @@ -3,21 +3,21 @@ var helper = require(__dirname + '/test-helper') function createClient(callback) { var client = new Client(helper.config) - client.connect(function (err) { + client.connect(function(err) { return callback(client) }) } -var testLit = function (testName, input, expected) { - test(testName, function () { +var testLit = function(testName, input, expected) { + test(testName, function() { var client = new Client(helper.config) var actual = client.escapeLiteral(input) assert.equal(expected, actual) }) } -var testIdent = function (testName, input, expected) { - test(testName, function () { +var testIdent = function(testName, input, expected) { + test(testName, function() { var client = new Client(helper.config) var actual = client.escapeIdentifier(input) assert.equal(expected, actual) diff --git a/packages/pg/test/unit/client/md5-password-tests.js b/packages/pg/test/unit/client/md5-password-tests.js index a55e955bc..5fdd44706 100644 --- a/packages/pg/test/unit/client/md5-password-tests.js +++ b/packages/pg/test/unit/client/md5-password-tests.js @@ -2,15 +2,15 @@ var helper = require('./test-helper') var utils = require('../../../lib/utils') -test('md5 authentication', function () { +test('md5 authentication', function() { var client = helper.createClient() client.password = '!' var salt = Buffer.from([1, 2, 3, 4]) client.connection.emit('authenticationMD5Password', { salt: salt }) - test('responds', function () { + test('responds', function() { assert.lengthIs(client.connection.stream.packets, 1) - test('should have correct encrypted data', function () { + test('should have correct encrypted data', function() { var password = utils.postgresMd5PasswordHash(client.user, client.password, salt) // how do we want to test this? assert.equalBuffers(client.connection.stream.packets[0], new BufferList().addCString(password).join(true, 'p')) @@ -18,6 +18,6 @@ test('md5 authentication', function () { }) }) -test('md5 of utf-8 strings', function () { +test('md5 of utf-8 strings', function() { assert.equal(utils.md5('😊'), '5deda34cd95f304948d2bc1b4a62c11e') }) diff --git a/packages/pg/test/unit/client/notification-tests.js b/packages/pg/test/unit/client/notification-tests.js index 5ca9df226..fd33b34a6 100644 --- a/packages/pg/test/unit/client/notification-tests.js +++ b/packages/pg/test/unit/client/notification-tests.js @@ -1,9 +1,9 @@ 'use strict' var helper = require(__dirname + '/test-helper') -test('passes connection notification', function () { +test('passes connection notification', function() { var client = helper.client() - assert.emits(client, 'notice', function (msg) { + assert.emits(client, 'notice', function(msg) { assert.equal(msg, 'HAY!!') }) client.connection.emit('notice', 'HAY!!') diff --git a/packages/pg/test/unit/client/prepared-statement-tests.js b/packages/pg/test/unit/client/prepared-statement-tests.js index 2499808f7..afcf10f7d 100644 --- a/packages/pg/test/unit/client/prepared-statement-tests.js +++ b/packages/pg/test/unit/client/prepared-statement-tests.js @@ -5,49 +5,49 @@ var Query = require('../../../lib/query') var client = helper.client() var con = client.connection var parseArg = null -con.parse = function (arg) { +con.parse = function(arg) { parseArg = arg - process.nextTick(function () { + process.nextTick(function() { con.emit('parseComplete') }) } var bindArg = null -con.bind = function (arg) { +con.bind = function(arg) { bindArg = arg - process.nextTick(function () { + process.nextTick(function() { con.emit('bindComplete') }) } var executeArg = null -con.execute = function (arg) { +con.execute = function(arg) { executeArg = arg - process.nextTick(function () { + process.nextTick(function() { con.emit('rowData', { fields: [] }) con.emit('commandComplete', { text: '' }) }) } var describeArg = null -con.describe = function (arg) { +con.describe = function(arg) { describeArg = arg - process.nextTick(function () { + process.nextTick(function() { con.emit('rowDescription', { fields: [] }) }) } var syncCalled = false -con.flush = function () {} -con.sync = function () { +con.flush = function() {} +con.sync = function() { syncCalled = true - process.nextTick(function () { + process.nextTick(function() { con.emit('readyForQuery') }) } -test('bound command', function () { - test('simple, unnamed bound command', function () { +test('bound command', function() { + test('simple, unnamed bound command', function() { assert.ok(client.connection.emit('readyForQuery')) var query = client.query( @@ -57,31 +57,31 @@ test('bound command', function () { }) ) - assert.emits(query, 'end', function () { - test('parse argument', function () { + assert.emits(query, 'end', function() { + test('parse argument', function() { assert.equal(parseArg.name, null) assert.equal(parseArg.text, 'select * from X where name = $1') assert.equal(parseArg.types, null) }) - test('bind argument', function () { + test('bind argument', function() { assert.equal(bindArg.statement, null) assert.equal(bindArg.portal, '') assert.lengthIs(bindArg.values, 1) assert.equal(bindArg.values[0], 'hi') }) - test('describe argument', function () { + test('describe argument', function() { assert.equal(describeArg.type, 'P') assert.equal(describeArg.name, '') }) - test('execute argument', function () { + test('execute argument', function() { assert.equal(executeArg.portal, '') assert.equal(executeArg.rows, null) }) - test('sync called', function () { + test('sync called', function() { assert.ok(syncCalled) }) }) @@ -91,46 +91,46 @@ test('bound command', function () { var portalClient = helper.client() var portalCon = portalClient.connection var portalParseArg = null -portalCon.parse = function (arg) { +portalCon.parse = function(arg) { portalParseArg = arg - process.nextTick(function () { + process.nextTick(function() { portalCon.emit('parseComplete') }) } var portalBindArg = null -portalCon.bind = function (arg) { +portalCon.bind = function(arg) { portalBindArg = arg - process.nextTick(function () { + process.nextTick(function() { portalCon.emit('bindComplete') }) } var portalExecuteArg = null -portalCon.execute = function (arg) { +portalCon.execute = function(arg) { portalExecuteArg = arg - process.nextTick(function () { + process.nextTick(function() { portalCon.emit('rowData', { fields: [] }) portalCon.emit('commandComplete', { text: '' }) }) } var portalDescribeArg = null -portalCon.describe = function (arg) { +portalCon.describe = function(arg) { portalDescribeArg = arg - process.nextTick(function () { + process.nextTick(function() { portalCon.emit('rowDescription', { fields: [] }) }) } -portalCon.flush = function () {} -portalCon.sync = function () { - process.nextTick(function () { +portalCon.flush = function() {} +portalCon.sync = function() { + process.nextTick(function() { portalCon.emit('readyForQuery') }) } -test('prepared statement with explicit portal', function () { +test('prepared statement with explicit portal', function() { assert.ok(portalClient.connection.emit('readyForQuery')) var query = portalClient.query( @@ -141,16 +141,16 @@ test('prepared statement with explicit portal', function () { }) ) - assert.emits(query, 'end', function () { - test('bind argument', function () { + assert.emits(query, 'end', function() { + test('bind argument', function() { assert.equal(portalBindArg.portal, 'myportal') }) - test('describe argument', function () { + test('describe argument', function() { assert.equal(portalDescribeArg.name, 'myportal') }) - test('execute argument', function () { + test('execute argument', function() { assert.equal(portalExecuteArg.portal, 'myportal') }) }) diff --git a/packages/pg/test/unit/client/query-queue-tests.js b/packages/pg/test/unit/client/query-queue-tests.js index 9364ce822..c02a698d9 100644 --- a/packages/pg/test/unit/client/query-queue-tests.js +++ b/packages/pg/test/unit/client/query-queue-tests.js @@ -2,17 +2,17 @@ var helper = require(__dirname + '/test-helper') var Connection = require(__dirname + '/../../../lib/connection') -test('drain', function () { +test('drain', function() { var con = new Connection({ stream: 'NO' }) var client = new Client({ connection: con }) - con.connect = function () { + con.connect = function() { con.emit('connect') } - con.query = function () {} + con.query = function() {} client.connect() var raisedDrain = false - client.on('drain', function () { + client.on('drain', function() { raisedDrain = true }) @@ -20,31 +20,31 @@ test('drain', function () { client.query('sup') client.query('boom') - test('with pending queries', function () { - test('does not emit drain', function () { + test('with pending queries', function() { + test('does not emit drain', function() { assert.equal(raisedDrain, false) }) }) - test('after some queries executed', function () { + test('after some queries executed', function() { con.emit('readyForQuery') - test('does not emit drain', function () { + test('does not emit drain', function() { assert.equal(raisedDrain, false) }) }) - test('when all queries are sent', function () { + test('when all queries are sent', function() { con.emit('readyForQuery') con.emit('readyForQuery') - test('does not emit drain', function () { + test('does not emit drain', function() { assert.equal(raisedDrain, false) }) }) - test('after last query finishes', function () { + test('after last query finishes', function() { con.emit('readyForQuery') - test('emits drain', function () { - process.nextTick(function () { + test('emits drain', function() { + process.nextTick(function() { assert.ok(raisedDrain) }) }) diff --git a/packages/pg/test/unit/client/result-metadata-tests.js b/packages/pg/test/unit/client/result-metadata-tests.js index f3e005949..4dc3a0162 100644 --- a/packages/pg/test/unit/client/result-metadata-tests.js +++ b/packages/pg/test/unit/client/result-metadata-tests.js @@ -1,8 +1,8 @@ 'use strict' var helper = require(__dirname + '/test-helper') -var testForTag = function (tagText, callback) { - test('includes command tag data for tag ' + tagText, function () { +var testForTag = function(tagText, callback) { + test('includes command tag data for tag ' + tagText, function() { var client = helper.client() client.connection.emit('readyForQuery') @@ -23,8 +23,8 @@ var testForTag = function (tagText, callback) { }) } -var check = function (oid, rowCount, command) { - return function (result) { +var check = function(oid, rowCount, command) { + return function(result) { if (oid != null) { assert.equal(result.oid, oid) } diff --git a/packages/pg/test/unit/client/sasl-scram-tests.js b/packages/pg/test/unit/client/sasl-scram-tests.js index f60c8c4c9..f0d17dadb 100644 --- a/packages/pg/test/unit/client/sasl-scram-tests.js +++ b/packages/pg/test/unit/client/sasl-scram-tests.js @@ -3,11 +3,11 @@ require('./test-helper') var sasl = require('../../../lib/sasl') -test('sasl/scram', function () { - test('startSession', function () { - test('fails when mechanisms does not include SCRAM-SHA-256', function () { +test('sasl/scram', function() { + test('startSession', function() { + test('fails when mechanisms does not include SCRAM-SHA-256', function() { assert.throws( - function () { + function() { sasl.startSession([]) }, { @@ -16,7 +16,7 @@ test('sasl/scram', function () { ) }) - test('returns expected session data', function () { + test('returns expected session data', function() { const session = sasl.startSession(['SCRAM-SHA-256']) assert.equal(session.mechanism, 'SCRAM-SHA-256') @@ -26,7 +26,7 @@ test('sasl/scram', function () { assert(session.response.match(/^n,,n=\*,r=.{24}/)) }) - test('creates random nonces', function () { + test('creates random nonces', function() { const session1 = sasl.startSession(['SCRAM-SHA-256']) const session2 = sasl.startSession(['SCRAM-SHA-256']) @@ -34,10 +34,10 @@ test('sasl/scram', function () { }) }) - test('continueSession', function () { - test('fails when last session message was not SASLInitialResponse', function () { + test('continueSession', function() { + test('fails when last session message was not SASLInitialResponse', function() { assert.throws( - function () { + function() { sasl.continueSession({}) }, { @@ -46,9 +46,9 @@ test('sasl/scram', function () { ) }) - test('fails when nonce is missing in server message', function () { + test('fails when nonce is missing in server message', function() { assert.throws( - function () { + function() { sasl.continueSession( { message: 'SASLInitialResponse', @@ -62,9 +62,9 @@ test('sasl/scram', function () { ) }) - test('fails when salt is missing in server message', function () { + test('fails when salt is missing in server message', function() { assert.throws( - function () { + function() { sasl.continueSession( { message: 'SASLInitialResponse', @@ -78,9 +78,9 @@ test('sasl/scram', function () { ) }) - test('fails when iteration is missing in server message', function () { + test('fails when iteration is missing in server message', function() { assert.throws( - function () { + function() { sasl.continueSession( { message: 'SASLInitialResponse', @@ -94,9 +94,9 @@ test('sasl/scram', function () { ) }) - test('fails when server nonce does not start with client nonce', function () { + test('fails when server nonce does not start with client nonce', function() { assert.throws( - function () { + function() { sasl.continueSession( { message: 'SASLInitialResponse', @@ -111,7 +111,7 @@ test('sasl/scram', function () { ) }) - test('sets expected session data', function () { + test('sets expected session data', function() { const session = { message: 'SASLInitialResponse', clientNonce: 'a', @@ -126,10 +126,10 @@ test('sasl/scram', function () { }) }) - test('continueSession', function () { - test('fails when last session message was not SASLResponse', function () { + test('continueSession', function() { + test('fails when last session message was not SASLResponse', function() { assert.throws( - function () { + function() { sasl.finalizeSession({}) }, { @@ -138,9 +138,9 @@ test('sasl/scram', function () { ) }) - test('fails when server signature does not match', function () { + test('fails when server signature does not match', function() { assert.throws( - function () { + function() { sasl.finalizeSession( { message: 'SASLResponse', @@ -155,7 +155,7 @@ test('sasl/scram', function () { ) }) - test('does not fail when eveything is ok', function () { + test('does not fail when eveything is ok', function() { sasl.finalizeSession( { message: 'SASLResponse', diff --git a/packages/pg/test/unit/client/simple-query-tests.js b/packages/pg/test/unit/client/simple-query-tests.js index b0d5b8674..be709bd19 100644 --- a/packages/pg/test/unit/client/simple-query-tests.js +++ b/packages/pg/test/unit/client/simple-query-tests.js @@ -2,9 +2,9 @@ var helper = require(__dirname + '/test-helper') var Query = require('../../../lib/query') -test('executing query', function () { - test('queing query', function () { - test('when connection is ready', function () { +test('executing query', function() { + test('queing query', function() { + test('when connection is ready', function() { var client = helper.client() assert.empty(client.connection.queries) client.connection.emit('readyForQuery') @@ -13,22 +13,22 @@ test('executing query', function () { assert.equal(client.connection.queries, 'yes') }) - test('when connection is not ready', function () { + test('when connection is not ready', function() { var client = helper.client() - test('query is not sent', function () { + test('query is not sent', function() { client.query('boom') assert.empty(client.connection.queries) }) - test('sends query to connection once ready', function () { + test('sends query to connection once ready', function() { assert.ok(client.connection.emit('readyForQuery')) assert.lengthIs(client.connection.queries, 1) assert.equal(client.connection.queries[0], 'boom') }) }) - test('multiple in the queue', function () { + test('multiple in the queue', function() { var client = helper.client() var connection = client.connection var queries = connection.queries @@ -37,18 +37,18 @@ test('executing query', function () { client.query('three') assert.empty(queries) - test('after one ready for query', function () { + test('after one ready for query', function() { connection.emit('readyForQuery') assert.lengthIs(queries, 1) assert.equal(queries[0], 'one') }) - test('after two ready for query', function () { + test('after two ready for query', function() { connection.emit('readyForQuery') assert.lengthIs(queries, 2) }) - test('after a bunch more', function () { + test('after a bunch more', function() { connection.emit('readyForQuery') connection.emit('readyForQuery') connection.emit('readyForQuery') @@ -60,22 +60,22 @@ test('executing query', function () { }) }) - test('query event binding and flow', function () { + test('query event binding and flow', function() { var client = helper.client() var con = client.connection var query = client.query(new Query('whatever')) - test('has no queries sent before ready', function () { + test('has no queries sent before ready', function() { assert.empty(con.queries) }) - test('sends query on readyForQuery event', function () { + test('sends query on readyForQuery event', function() { con.emit('readyForQuery') assert.lengthIs(con.queries, 1) assert.equal(con.queries[0], 'whatever') }) - test('handles rowDescription message', function () { + test('handles rowDescription message', function() { var handled = con.emit('rowDescription', { fields: [ { @@ -86,15 +86,15 @@ test('executing query', function () { assert.ok(handled, 'should have handlded rowDescription') }) - test('handles dataRow messages', function () { - assert.emits(query, 'row', function (row) { + test('handles dataRow messages', function() { + assert.emits(query, 'row', function(row) { assert.equal(row['boom'], 'hi') }) var handled = con.emit('dataRow', { fields: ['hi'] }) assert.ok(handled, 'should have handled first data row message') - assert.emits(query, 'row', function (row) { + assert.emits(query, 'row', function(row) { assert.equal(row['boom'], 'bye') }) @@ -104,29 +104,29 @@ test('executing query', function () { // multiple command complete messages will be sent // when multiple queries are in a simple command - test('handles command complete messages', function () { + test('handles command complete messages', function() { con.emit('commandComplete', { text: 'INSERT 31 1', }) }) - test('removes itself after another readyForQuery message', function () { + test('removes itself after another readyForQuery message', function() { return false - assert.emits(query, 'end', function (msg) { + assert.emits(query, 'end', function(msg) { // TODO do we want to check the complete messages? }) con.emit('readyForQuery') // this would never actually happen - ;['dataRow', 'rowDescription', 'commandComplete'].forEach(function (msg) { + ;['dataRow', 'rowDescription', 'commandComplete'].forEach(function(msg) { assert.equal(con.emit(msg), false, "Should no longer be picking up '" + msg + "' messages") }) }) }) - test('handles errors', function () { + test('handles errors', function() { var client = helper.client() - test('throws an error when config is null', function () { + test('throws an error when config is null', function() { try { client.query(null, undefined) } catch (error) { @@ -138,7 +138,7 @@ test('executing query', function () { } }) - test('throws an error when config is undefined', function () { + test('throws an error when config is undefined', function() { try { client.query() } catch (error) { diff --git a/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js index 9b0a3560b..5a73486c9 100644 --- a/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js +++ b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js @@ -3,18 +3,18 @@ var helper = require(__dirname + '/test-helper') var Connection = require(__dirname + '/../../../lib/connection') var Client = require(__dirname + '/../../../lib/client') -test('emits end when not in query', function () { +test('emits end when not in query', function() { var stream = new (require('events').EventEmitter)() - stream.write = function () { + stream.write = function() { // NOOP } var client = new Client({ connection: new Connection({ stream: stream }) }) client.connect( - assert.calls(function () { + assert.calls(function() { client.query( 'SELECT NOW()', - assert.calls(function (err, result) { + assert.calls(function(err, result) { assert(err) }) ) @@ -23,11 +23,11 @@ test('emits end when not in query', function () { assert.emits(client, 'error') assert.emits(client, 'end') client.connection.emit('connect') - process.nextTick(function () { + process.nextTick(function() { client.connection.emit('readyForQuery') assert.equal(client.queryQueue.length, 0) assert(client.activeQuery, 'client should have issued query') - process.nextTick(function () { + process.nextTick(function() { stream.emit('close') }) }) diff --git a/packages/pg/test/unit/client/test-helper.js b/packages/pg/test/unit/client/test-helper.js index 8d1859033..814e94a94 100644 --- a/packages/pg/test/unit/client/test-helper.js +++ b/packages/pg/test/unit/client/test-helper.js @@ -2,11 +2,11 @@ var helper = require('../test-helper') var Connection = require('../../../lib/connection') -var makeClient = function () { +var makeClient = function() { var connection = new Connection({ stream: 'no' }) - connection.startup = function () {} - connection.connect = function () {} - connection.query = function (text) { + connection.startup = function() {} + connection.connect = function() {} + connection.query = function(text) { this.queries.push(text) } connection.queries = [] diff --git a/packages/pg/test/unit/client/throw-in-type-parser-tests.js b/packages/pg/test/unit/client/throw-in-type-parser-tests.js index 8f71fdc02..cc8ec3c74 100644 --- a/packages/pg/test/unit/client/throw-in-type-parser-tests.js +++ b/packages/pg/test/unit/client/throw-in-type-parser-tests.js @@ -7,7 +7,7 @@ const suite = new helper.Suite() var typeParserError = new Error('TEST: Throw in type parsers') -types.setTypeParser('special oid that will throw', function () { +types.setTypeParser('special oid that will throw', function() { throw typeParserError }) @@ -31,20 +31,20 @@ const emitFakeEvents = (con) => { }) } -suite.test('emits error', function (done) { +suite.test('emits error', function(done) { var handled var client = helper.client() var con = client.connection var query = client.query(new Query('whatever')) emitFakeEvents(con) - assert.emits(query, 'error', function (err) { + assert.emits(query, 'error', function(err) { assert.equal(err, typeParserError) done() }) }) -suite.test('calls callback with error', function (done) { +suite.test('calls callback with error', function(done) { var handled var callbackCalled = 0 @@ -52,13 +52,13 @@ suite.test('calls callback with error', function (done) { var client = helper.client() var con = client.connection emitFakeEvents(con) - var query = client.query('whatever', function (err) { + var query = client.query('whatever', function(err) { assert.equal(err, typeParserError) done() }) }) -suite.test('rejects promise with error', function (done) { +suite.test('rejects promise with error', function(done) { var client = helper.client() var con = client.connection emitFakeEvents(con) diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index 820b320a5..30b510fc5 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -9,13 +9,13 @@ for (var key in process.env) { delete process.env[key] } -test('ConnectionParameters construction', function () { +test('ConnectionParameters construction', function() { assert.ok(new ConnectionParameters(), 'with null config') assert.ok(new ConnectionParameters({ user: 'asdf' }), 'with config object') assert.ok(new ConnectionParameters('postgres://localhost/postgres'), 'with connection string') }) -var compare = function (actual, expected, type) { +var compare = function(actual, expected, type) { const expectedDatabase = expected.database === undefined ? expected.user : expected.database assert.equal(actual.user, expected.user, type + ' user') @@ -32,13 +32,13 @@ var compare = function (actual, expected, type) { ) } -test('ConnectionParameters initializing from defaults', function () { +test('ConnectionParameters initializing from defaults', function() { var subject = new ConnectionParameters() compare(subject, defaults, 'defaults') assert.ok(subject.isDomainSocket === false) }) -test('ConnectionParameters initializing from defaults with connectionString set', function () { +test('ConnectionParameters initializing from defaults with connectionString set', function() { var config = { user: 'brians-are-the-best', database: 'scoobysnacks', @@ -59,7 +59,7 @@ test('ConnectionParameters initializing from defaults with connectionString set' compare(subject, config, 'defaults-connectionString') }) -test('ConnectionParameters initializing from config', function () { +test('ConnectionParameters initializing from config', function() { var config = { user: 'brian', database: 'home', @@ -79,7 +79,7 @@ test('ConnectionParameters initializing from config', function () { assert.ok(subject.isDomainSocket === false) }) -test('ConnectionParameters initializing from config and config.connectionString', function () { +test('ConnectionParameters initializing from config and config.connectionString', function() { var subject1 = new ConnectionParameters({ connectionString: 'postgres://test@host/db', }) @@ -101,31 +101,31 @@ test('ConnectionParameters initializing from config and config.connectionString' assert.equal(subject4.ssl, true) }) -test('escape spaces if present', function () { +test('escape spaces if present', function() { var subject = new ConnectionParameters('postgres://localhost/post gres') assert.equal(subject.database, 'post gres') }) -test('do not double escape spaces', function () { +test('do not double escape spaces', function() { var subject = new ConnectionParameters('postgres://localhost/post%20gres') assert.equal(subject.database, 'post gres') }) -test('initializing with unix domain socket', function () { +test('initializing with unix domain socket', function() { var subject = new ConnectionParameters('/var/run/') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/var/run/') assert.equal(subject.database, defaults.user) }) -test('initializing with unix domain socket and a specific database, the simple way', function () { +test('initializing with unix domain socket and a specific database, the simple way', function() { var subject = new ConnectionParameters('/var/run/ mydb') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/var/run/') assert.equal(subject.database, 'mydb') }) -test('initializing with unix domain socket, the health way', function () { +test('initializing with unix domain socket, the health way', function() { var subject = new ConnectionParameters('socket:/some path/?db=my[db]&encoding=utf8') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/some path/') @@ -133,7 +133,7 @@ test('initializing with unix domain socket, the health way', function () { assert.equal(subject.client_encoding, 'utf8') }) -test('initializing with unix domain socket, the escaped health way', function () { +test('initializing with unix domain socket, the escaped health way', function() { var subject = new ConnectionParameters('socket:/some%20path/?db=my%2Bdb&encoding=utf8') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/some path/') @@ -141,12 +141,12 @@ test('initializing with unix domain socket, the escaped health way', function () assert.equal(subject.client_encoding, 'utf8') }) -test('libpq connection string building', function () { - var checkForPart = function (array, part) { +test('libpq connection string building', function() { + var checkForPart = function(array, part) { assert.ok(array.indexOf(part) > -1, array.join(' ') + ' did not contain ' + part) } - test('builds simple string', function () { + test('builds simple string', function() { var config = { user: 'brian', password: 'xyz', @@ -156,7 +156,7 @@ test('libpq connection string building', function () { } var subject = new ConnectionParameters(config) subject.getLibpqConnectionString( - assert.calls(function (err, constring) { + assert.calls(function(err, constring) { assert(!err) var parts = constring.split(' ') checkForPart(parts, "user='brian'") @@ -168,7 +168,7 @@ test('libpq connection string building', function () { ) }) - test('builds dns string', function () { + test('builds dns string', function() { var config = { user: 'brian', password: 'asdf', @@ -177,7 +177,7 @@ test('libpq connection string building', function () { } var subject = new ConnectionParameters(config) subject.getLibpqConnectionString( - assert.calls(function (err, constring) { + assert.calls(function(err, constring) { assert(!err) var parts = constring.split(' ') checkForPart(parts, "user='brian'") @@ -186,7 +186,7 @@ test('libpq connection string building', function () { ) }) - test('error when dns fails', function () { + test('error when dns fails', function() { var config = { user: 'brian', password: 'asf', @@ -195,14 +195,14 @@ test('libpq connection string building', function () { } var subject = new ConnectionParameters(config) subject.getLibpqConnectionString( - assert.calls(function (err, constring) { + assert.calls(function(err, constring) { assert.ok(err) assert.isNull(constring) }) ) }) - test('connecting to unix domain socket', function () { + test('connecting to unix domain socket', function() { var config = { user: 'brian', password: 'asf', @@ -211,7 +211,7 @@ test('libpq connection string building', function () { } var subject = new ConnectionParameters(config) subject.getLibpqConnectionString( - assert.calls(function (err, constring) { + assert.calls(function(err, constring) { assert(!err) var parts = constring.split(' ') checkForPart(parts, "user='brian'") @@ -220,7 +220,7 @@ test('libpq connection string building', function () { ) }) - test('config contains quotes and backslashes', function () { + test('config contains quotes and backslashes', function() { var config = { user: 'not\\brian', password: "bad'chars", @@ -229,7 +229,7 @@ test('libpq connection string building', function () { } var subject = new ConnectionParameters(config) subject.getLibpqConnectionString( - assert.calls(function (err, constring) { + assert.calls(function(err, constring) { assert(!err) var parts = constring.split(' ') checkForPart(parts, "user='not\\\\brian'") @@ -238,13 +238,13 @@ test('libpq connection string building', function () { ) }) - test('encoding can be specified by config', function () { + test('encoding can be specified by config', function() { var config = { client_encoding: 'utf-8', } var subject = new ConnectionParameters(config) subject.getLibpqConnectionString( - assert.calls(function (err, constring) { + assert.calls(function(err, constring) { assert(!err) var parts = constring.split(' ') checkForPart(parts, "client_encoding='utf-8'") @@ -252,7 +252,7 @@ test('libpq connection string building', function () { ) }) - test('password contains < and/or > characters', function () { + test('password contains < and/or > characters', function() { return false var sourceConfig = { user: 'brian', @@ -276,7 +276,7 @@ test('libpq connection string building', function () { assert.equal(subject.password, sourceConfig.password) }) - test('username or password contains weird characters', function () { + test('username or password contains weird characters', function() { var defaults = require('../../../lib/defaults') defaults.ssl = true var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000' @@ -287,7 +287,7 @@ test('libpq connection string building', function () { assert.equal(subject.ssl, true) }) - test('url is properly encoded', function () { + test('url is properly encoded', function() { var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl' var subject = new ConnectionParameters(encoded) assert.equal(subject.user, 'bi%na%%ry ') @@ -296,7 +296,7 @@ test('libpq connection string building', function () { assert.equal(subject.database, ' u%20rl') }) - test('ssl is set on client', function () { + test('ssl is set on client', function() { var Client = require('../../../lib/client') var defaults = require('../../../lib/defaults') defaults.ssl = true @@ -304,7 +304,7 @@ test('libpq connection string building', function () { assert(c.ssl, 'Client should have ssl enabled via defaults') }) - test('ssl is set on client', function () { + test('ssl is set on client', function() { var sourceConfig = { user: 'brian', password: 'helloe', @@ -324,7 +324,7 @@ test('libpq connection string building', function () { defaults.ssl = true var c = new ConnectionParameters(sourceConfig) c.getLibpqConnectionString( - assert.calls(function (err, pgCString) { + assert.calls(function(err, pgCString) { assert(!err) assert.equal( pgCString.indexOf("sslrootcert='/path/root.crt'") !== -1, diff --git a/packages/pg/test/unit/connection-parameters/environment-variable-tests.js b/packages/pg/test/unit/connection-parameters/environment-variable-tests.js index 45d481e30..e1decf625 100644 --- a/packages/pg/test/unit/connection-parameters/environment-variable-tests.js +++ b/packages/pg/test/unit/connection-parameters/environment-variable-tests.js @@ -11,7 +11,7 @@ for (var key in process.env) { delete process.env[key] } -test('ConnectionParameters initialized from environment variables', function (t) { +test('ConnectionParameters initialized from environment variables', function(t) { process.env['PGHOST'] = 'local' process.env['PGUSER'] = 'bmc2' process.env['PGPORT'] = 7890 @@ -26,7 +26,7 @@ test('ConnectionParameters initialized from environment variables', function (t) assert.equal(subject.password, 'open', 'env password') }) -test('ConnectionParameters initialized from mix', function (t) { +test('ConnectionParameters initialized from mix', function(t) { delete process.env['PGPASSWORD'] delete process.env['PGDATABASE'] var subject = new ConnectionParameters({ @@ -45,7 +45,7 @@ for (var key in process.env) { delete process.env[key] } -test('connection string parsing', function (t) { +test('connection string parsing', function(t) { var string = 'postgres://brian:pw@boom:381/lala' var subject = new ConnectionParameters(string) assert.equal(subject.host, 'boom', 'string host') @@ -55,7 +55,7 @@ test('connection string parsing', function (t) { assert.equal(subject.database, 'lala', 'string database') }) -test('connection string parsing - ssl', function (t) { +test('connection string parsing - ssl', function(t) { var string = 'postgres://brian:pw@boom:381/lala?ssl=true' var subject = new ConnectionParameters(string) assert.equal(subject.ssl, true, 'ssl') @@ -82,18 +82,18 @@ for (var key in process.env) { delete process.env[key] } -test('ssl is false by default', function () { +test('ssl is false by default', function() { var subject = new ConnectionParameters() assert.equal(subject.ssl, false) }) -var testVal = function (mode, expected) { +var testVal = function(mode, expected) { // clear process.env for (var key in process.env) { delete process.env[key] } process.env.PGSSLMODE = mode - test('ssl is ' + expected + ' when $PGSSLMODE=' + mode, function () { + test('ssl is ' + expected + ' when $PGSSLMODE=' + mode, function() { var subject = new ConnectionParameters() assert.equal(subject.ssl, expected) }) diff --git a/packages/pg/test/unit/connection/error-tests.js b/packages/pg/test/unit/connection/error-tests.js index 5075c770d..43c06cc3c 100644 --- a/packages/pg/test/unit/connection/error-tests.js +++ b/packages/pg/test/unit/connection/error-tests.js @@ -5,9 +5,9 @@ var net = require('net') const suite = new helper.Suite() -suite.test('connection emits stream errors', function (done) { +suite.test('connection emits stream errors', function(done) { var con = new Connection({ stream: new MemoryStream() }) - assert.emits(con, 'error', function (err) { + assert.emits(con, 'error', function(err) { assert.equal(err.message, 'OMG!') done() }) @@ -15,10 +15,10 @@ suite.test('connection emits stream errors', function (done) { con.stream.emit('error', new Error('OMG!')) }) -suite.test('connection emits ECONNRESET errors during normal operation', function (done) { +suite.test('connection emits ECONNRESET errors during normal operation', function(done) { var con = new Connection({ stream: new MemoryStream() }) con.connect() - assert.emits(con, 'error', function (err) { + assert.emits(con, 'error', function(err) { assert.equal(err.code, 'ECONNRESET') done() }) @@ -27,7 +27,7 @@ suite.test('connection emits ECONNRESET errors during normal operation', functio con.stream.emit('error', e) }) -suite.test('connection does not emit ECONNRESET errors during disconnect', function (done) { +suite.test('connection does not emit ECONNRESET errors during disconnect', function(done) { var con = new Connection({ stream: new MemoryStream() }) con.connect() var e = new Error('Connection Reset') @@ -60,20 +60,20 @@ var SSLNegotiationPacketTests = [ for (var i = 0; i < SSLNegotiationPacketTests.length; i++) { var tc = SSLNegotiationPacketTests[i] - suite.test(tc.testName, function (done) { + suite.test(tc.testName, function(done) { // our fake postgres server var socket - var server = net.createServer(function (c) { + var server = net.createServer(function(c) { socket = c - c.once('data', function (data) { + c.once('data', function(data) { c.write(Buffer.from(tc.response)) }) }) - server.listen(7778, function () { + server.listen(7778, function() { var con = new Connection({ ssl: true }) con.connect(7778, 'localhost') - assert.emits(con, tc.responseType, function (err) { + assert.emits(con, tc.responseType, function(err) { if (tc.errorMessage !== null || err) { assert.equal(err.message, tc.errorMessage) } diff --git a/packages/pg/test/unit/connection/inbound-parser-tests.js b/packages/pg/test/unit/connection/inbound-parser-tests.js index 5f92cdc52..866c614ab 100644 --- a/packages/pg/test/unit/connection/inbound-parser-tests.js +++ b/packages/pg/test/unit/connection/inbound-parser-tests.js @@ -2,7 +2,7 @@ require(__dirname + '/test-helper') var Connection = require(__dirname + '/../../../lib/connection') var buffers = require(__dirname + '/../../test-buffers') -var PARSE = function (buffer) { +var PARSE = function(buffer) { return new Parser(buffer).parse() } @@ -15,7 +15,7 @@ var parseCompleteBuffer = buffers.parseComplete() var bindCompleteBuffer = buffers.bindComplete() var portalSuspendedBuffer = buffers.portalSuspended() -var addRow = function (bufferList, name, offset) { +var addRow = function(bufferList, name, offset) { return bufferList .addCString(name) // field name .addInt32(offset++) // table id @@ -112,20 +112,20 @@ var expectedTwoRowMessage = { fieldCount: 2, } -var testForMessage = function (buffer, expectedMessage) { +var testForMessage = function(buffer, expectedMessage) { var lastMessage = {} - test('recieves and parses ' + expectedMessage.name, function () { + test('recieves and parses ' + expectedMessage.name, function() { var stream = new MemoryStream() var client = new Connection({ stream: stream, }) client.connect() - client.on('message', function (msg) { + client.on('message', function(msg) { lastMessage = msg }) - client.on(expectedMessage.name, function () { + client.on(expectedMessage.name, function() { client.removeAllListeners(expectedMessage.name) }) @@ -171,16 +171,16 @@ var expectedNotificationResponseMessage = { payload: 'boom', } -test('Connection', function () { +test('Connection', function() { testForMessage(authOkBuffer, expectedAuthenticationOkayMessage) testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage) var msgMD5 = testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage) - test('md5 has right salt', function () { + test('md5 has right salt', function() { assert.equalBuffers(msgMD5.salt, Buffer.from([1, 2, 3, 4])) }) var msgSASL = testForMessage(SASLBuffer, expectedSASLMessage) - test('SASL has the right mechanisms', function () { + test('SASL has the right mechanisms', function() { assert.deepStrictEqual(msgSASL.mechanisms, ['SCRAM-SHA-256']) }) testForMessage(SASLContinueBuffer, expectedSASLContinueMessage) @@ -191,25 +191,25 @@ test('Connection', function () { testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage) testForMessage(commandCompleteBuffer, expectedCommandCompleteMessage) testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage) - test('empty row message', function () { + test('empty row message', function() { var message = testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage) - test('has no fields', function () { + test('has no fields', function() { assert.equal(message.fields.length, 0) }) }) - test('no data message', function () { + test('no data message', function() { testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), { name: 'noData', }) }) - test('one row message', function () { + test('one row message', function() { var message = testForMessage(oneRowDescBuff, expectedOneRowMessage) - test('has one field', function () { + test('has one field', function() { assert.equal(message.fields.length, 1) }) - test('has correct field info', function () { + test('has correct field info', function() { assert.same(message.fields[0], { name: 'id', tableID: 1, @@ -222,12 +222,12 @@ test('Connection', function () { }) }) - test('two row message', function () { + test('two row message', function() { var message = testForMessage(twoRowBuf, expectedTwoRowMessage) - test('has two fields', function () { + test('has two fields', function() { assert.equal(message.fields.length, 2) }) - test('has correct first field', function () { + test('has correct first field', function() { assert.same(message.fields[0], { name: 'bang', tableID: 1, @@ -238,7 +238,7 @@ test('Connection', function () { format: 'text', }) }) - test('has correct second field', function () { + test('has correct second field', function() { assert.same(message.fields[1], { name: 'whoah', tableID: 10, @@ -251,33 +251,33 @@ test('Connection', function () { }) }) - test('parsing rows', function () { - test('parsing empty row', function () { + test('parsing rows', function() { + test('parsing empty row', function() { var message = testForMessage(emptyRowFieldBuf, { name: 'dataRow', fieldCount: 0, }) - test('has 0 fields', function () { + test('has 0 fields', function() { assert.equal(message.fields.length, 0) }) }) - test('parsing data row with fields', function () { + test('parsing data row with fields', function() { var message = testForMessage(oneFieldBuf, { name: 'dataRow', fieldCount: 1, }) - test('has 1 field', function () { + test('has 1 field', function() { assert.equal(message.fields.length, 1) }) - test('field is correct', function () { + test('field is correct', function() { assert.equal(message.fields[0], 'test') }) }) }) - test('notice message', function () { + test('notice message', function() { // this uses the same logic as error message var buff = buffers.notice([{ type: 'C', value: 'code' }]) testForMessage(buff, { @@ -286,14 +286,14 @@ test('Connection', function () { }) }) - test('error messages', function () { - test('with no fields', function () { + test('error messages', function() { + test('with no fields', function() { var msg = testForMessage(buffers.error(), { name: 'error', }) }) - test('with all the fields', function () { + test('with all the fields', function() { var buffer = buffers.error([ { type: 'S', @@ -367,25 +367,25 @@ test('Connection', function () { }) }) - test('parses parse complete command', function () { + test('parses parse complete command', function() { testForMessage(parseCompleteBuffer, { name: 'parseComplete', }) }) - test('parses bind complete command', function () { + test('parses bind complete command', function() { testForMessage(bindCompleteBuffer, { name: 'bindComplete', }) }) - test('parses portal suspended message', function () { + test('parses portal suspended message', function() { testForMessage(portalSuspendedBuffer, { name: 'portalSuspended', }) }) - test('parses replication start message', function () { + test('parses replication start message', function() { testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { name: 'replicationStart', length: 4, @@ -396,7 +396,7 @@ test('Connection', function () { // since the data message on a stream can randomly divide the incomming // tcp packets anywhere, we need to make sure we can parse every single // split on a tcp message -test('split buffer, single message parsing', function () { +test('split buffer, single message parsing', function() { var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']) var stream = new MemoryStream() stream.readyState = 'open' @@ -405,11 +405,11 @@ test('split buffer, single message parsing', function () { }) client.connect() var message = null - client.on('message', function (msg) { + client.on('message', function(msg) { message = msg }) - test('parses when full buffer comes in', function () { + test('parses when full buffer comes in', function() { stream.emit('data', fullBuffer) assert.lengthIs(message.fields, 5) assert.equal(message.fields[0], null) @@ -419,7 +419,7 @@ test('split buffer, single message parsing', function () { assert.equal(message.fields[4], '!') }) - var testMessageRecievedAfterSpiltAt = function (split) { + var testMessageRecievedAfterSpiltAt = function(split) { var firstBuffer = Buffer.alloc(fullBuffer.length - split) var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) fullBuffer.copy(firstBuffer, 0, 0) @@ -434,22 +434,22 @@ test('split buffer, single message parsing', function () { assert.equal(message.fields[4], '!') } - test('parses when split in the middle', function () { + test('parses when split in the middle', function() { testMessageRecievedAfterSpiltAt(6) }) - test('parses when split at end', function () { + test('parses when split at end', function() { testMessageRecievedAfterSpiltAt(2) }) - test('parses when split at beginning', function () { + test('parses when split at beginning', function() { testMessageRecievedAfterSpiltAt(fullBuffer.length - 2) testMessageRecievedAfterSpiltAt(fullBuffer.length - 1) testMessageRecievedAfterSpiltAt(fullBuffer.length - 5) }) }) -test('split buffer, multiple message parsing', function () { +test('split buffer, multiple message parsing', function() { var dataRowBuffer = buffers.dataRow(['!']) var readyForQueryBuffer = buffers.readyForQuery() var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length) @@ -462,11 +462,11 @@ test('split buffer, multiple message parsing', function () { stream: stream, }) client.connect() - client.on('message', function (msg) { + client.on('message', function(msg) { messages.push(msg) }) - var verifyMessages = function () { + var verifyMessages = function() { assert.lengthIs(messages, 2) assert.same(messages[0], { name: 'dataRow', @@ -479,11 +479,11 @@ test('split buffer, multiple message parsing', function () { messages = [] } // sanity check - test('recieves both messages when packet is not split', function () { + test('recieves both messages when packet is not split', function() { stream.emit('data', fullBuffer) verifyMessages() }) - var splitAndVerifyTwoMessages = function (split) { + var splitAndVerifyTwoMessages = function(split) { var firstBuffer = Buffer.alloc(fullBuffer.length - split) var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) fullBuffer.copy(firstBuffer, 0, 0) @@ -492,17 +492,17 @@ test('split buffer, multiple message parsing', function () { stream.emit('data', secondBuffer) } - test('recieves both messages when packet is split', function () { - test('in the middle', function () { + test('recieves both messages when packet is split', function() { + test('in the middle', function() { splitAndVerifyTwoMessages(11) }) - test('at the front', function () { + test('at the front', function() { splitAndVerifyTwoMessages(fullBuffer.length - 1) splitAndVerifyTwoMessages(fullBuffer.length - 4) splitAndVerifyTwoMessages(fullBuffer.length - 6) }) - test('at the end', function () { + test('at the end', function() { splitAndVerifyTwoMessages(8) splitAndVerifyTwoMessages(1) }) diff --git a/packages/pg/test/unit/connection/outbound-sending-tests.js b/packages/pg/test/unit/connection/outbound-sending-tests.js index b40af0005..c6c8e90c2 100644 --- a/packages/pg/test/unit/connection/outbound-sending-tests.js +++ b/packages/pg/test/unit/connection/outbound-sending-tests.js @@ -6,13 +6,13 @@ var con = new Connection({ stream: stream, }) -assert.received = function (stream, buffer) { +assert.received = function(stream, buffer) { assert.lengthIs(stream.packets, 1) var packet = stream.packets.pop() assert.equalBuffers(packet, buffer) } -test('sends startup message', function () { +test('sends startup message', function() { con.startup({ user: 'brian', database: 'bang', @@ -33,43 +33,58 @@ test('sends startup message', function () { ) }) -test('sends password message', function () { +test('sends password message', function() { con.password('!') assert.received(stream, new BufferList().addCString('!').join(true, 'p')) }) -test('sends SASLInitialResponseMessage message', function () { +test('sends SASLInitialResponseMessage message', function() { con.sendSASLInitialResponseMessage('mech', 'data') - assert.received(stream, new BufferList().addCString('mech').addInt32(4).addString('data').join(true, 'p')) + assert.received( + stream, + new BufferList() + .addCString('mech') + .addInt32(4) + .addString('data') + .join(true, 'p') + ) }) -test('sends SCRAMClientFinalMessage message', function () { +test('sends SCRAMClientFinalMessage message', function() { con.sendSCRAMClientFinalMessage('data') assert.received(stream, new BufferList().addString('data').join(true, 'p')) }) -test('sends query message', function () { +test('sends query message', function() { var txt = 'select * from boom' con.query(txt) assert.received(stream, new BufferList().addCString(txt).join(true, 'Q')) }) -test('sends parse message', function () { +test('sends parse message', function() { con.parse({ text: '!' }) - var expected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P') + var expected = new BufferList() + .addCString('') + .addCString('!') + .addInt16(0) + .join(true, 'P') assert.received(stream, expected) }) -test('sends parse message with named query', function () { +test('sends parse message with named query', function() { con.parse({ name: 'boom', text: 'select * from boom', types: [], }) - var expected = new BufferList().addCString('boom').addCString('select * from boom').addInt16(0).join(true, 'P') + var expected = new BufferList() + .addCString('boom') + .addCString('select * from boom') + .addInt16(0) + .join(true, 'P') assert.received(stream, expected) - test('with multiple parameters', function () { + test('with multiple parameters', function() { con.parse({ name: 'force', text: 'select * from bang where name = $1', @@ -88,8 +103,8 @@ test('sends parse message with named query', function () { }) }) -test('bind messages', function () { - test('with no values', function () { +test('bind messages', function() { + test('with no values', function() { con.bind() var expectedBuffer = new BufferList() @@ -102,7 +117,7 @@ test('bind messages', function () { assert.received(stream, expectedBuffer) }) - test('with named statement, portal, and values', function () { + test('with named statement, portal, and values', function() { con.bind({ portal: 'bang', statement: 'woo', @@ -126,7 +141,7 @@ test('bind messages', function () { }) }) -test('with named statement, portal, and buffer value', function () { +test('with named statement, portal, and buffer value', function() { con.bind({ portal: 'bang', statement: 'woo', @@ -153,52 +168,64 @@ test('with named statement, portal, and buffer value', function () { assert.received(stream, expectedBuffer) }) -test('sends execute message', function () { - test('for unamed portal with no row limit', function () { +test('sends execute message', function() { + test('for unamed portal with no row limit', function() { con.execute() - var expectedBuffer = new BufferList().addCString('').addInt32(0).join(true, 'E') + var expectedBuffer = new BufferList() + .addCString('') + .addInt32(0) + .join(true, 'E') assert.received(stream, expectedBuffer) }) - test('for named portal with row limit', function () { + test('for named portal with row limit', function() { con.execute({ portal: 'my favorite portal', rows: 100, }) - var expectedBuffer = new BufferList().addCString('my favorite portal').addInt32(100).join(true, 'E') + var expectedBuffer = new BufferList() + .addCString('my favorite portal') + .addInt32(100) + .join(true, 'E') assert.received(stream, expectedBuffer) }) }) -test('sends flush command', function () { +test('sends flush command', function() { con.flush() var expected = new BufferList().join(true, 'H') assert.received(stream, expected) }) -test('sends sync command', function () { +test('sends sync command', function() { con.sync() var expected = new BufferList().join(true, 'S') assert.received(stream, expected) }) -test('sends end command', function () { +test('sends end command', function() { con.end() var expected = Buffer.from([0x58, 0, 0, 0, 4]) assert.received(stream, expected) assert.equal(stream.closed, true) }) -test('sends describe command', function () { - test('describe statement', function () { +test('sends describe command', function() { + test('describe statement', function() { con.describe({ type: 'S', name: 'bang' }) - var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D') + var expected = new BufferList() + .addChar('S') + .addCString('bang') + .join(true, 'D') assert.received(stream, expected) }) - test('describe unnamed portal', function () { + test('describe unnamed portal', function() { con.describe({ type: 'P' }) - var expected = new BufferList().addChar('P').addCString('').join(true, 'D') + var expected = new BufferList() + .addChar('P') + .addCString('') + .join(true, 'D') assert.received(stream, expected) }) }) diff --git a/packages/pg/test/unit/connection/startup-tests.js b/packages/pg/test/unit/connection/startup-tests.js index 09a710c7a..9bf973d35 100644 --- a/packages/pg/test/unit/connection/startup-tests.js +++ b/packages/pg/test/unit/connection/startup-tests.js @@ -1,17 +1,17 @@ 'use strict' require(__dirname + '/test-helper') var Connection = require(__dirname + '/../../../lib/connection') -test('connection can take existing stream', function () { +test('connection can take existing stream', function() { var stream = new MemoryStream() var con = new Connection({ stream: stream }) assert.equal(con.stream, stream) }) -test('using closed stream', function () { - var makeStream = function () { +test('using closed stream', function() { + var makeStream = function() { var stream = new MemoryStream() stream.readyState = 'closed' - stream.connect = function (port, host) { + stream.connect = function(port, host) { this.connectCalled = true this.port = port this.host = host @@ -25,22 +25,22 @@ test('using closed stream', function () { con.connect(1234, 'bang') - test('makes stream connect', function () { + test('makes stream connect', function() { assert.equal(stream.connectCalled, true) }) - test('uses configured port', function () { + test('uses configured port', function() { assert.equal(stream.port, 1234) }) - test('uses configured host', function () { + test('uses configured host', function() { assert.equal(stream.host, 'bang') }) - test('after stream connects client emits connected event', function () { + test('after stream connects client emits connected event', function() { var hit = false - con.once('connect', function () { + con.once('connect', function() { hit = true }) @@ -48,34 +48,34 @@ test('using closed stream', function () { assert.ok(hit) }) - test('after stream emits connected event init TCP-keepalive', function () { + test('after stream emits connected event init TCP-keepalive', function() { var stream = makeStream() var con = new Connection({ stream: stream, keepAlive: true }) con.connect(123, 'test') var res = false - stream.setKeepAlive = function (bit) { + stream.setKeepAlive = function(bit) { res = bit } assert.ok(stream.emit('connect')) - setTimeout(function () { + setTimeout(function() { assert.equal(res, true) }) }) }) -test('using opened stream', function () { +test('using opened stream', function() { var stream = new MemoryStream() stream.readyState = 'open' - stream.connect = function () { + stream.connect = function() { assert.ok(false, 'Should not call open') } var con = new Connection({ stream: stream }) - test('does not call open', function () { + test('does not call open', function() { var hit = false - con.once('connect', function () { + con.once('connect', function() { hit = true }) con.connect() diff --git a/packages/pg/test/unit/test-helper.js b/packages/pg/test/unit/test-helper.js index 5793251b5..0b149cec0 100644 --- a/packages/pg/test/unit/test-helper.js +++ b/packages/pg/test/unit/test-helper.js @@ -4,7 +4,7 @@ var EventEmitter = require('events').EventEmitter var helper = require('../test-helper') var Connection = require('../../lib/connection') -global.MemoryStream = function () { +global.MemoryStream = function() { EventEmitter.call(this) this.packets = [] } @@ -13,22 +13,22 @@ helper.sys.inherits(MemoryStream, EventEmitter) var p = MemoryStream.prototype -p.write = function (packet, cb) { +p.write = function(packet, cb) { this.packets.push(packet) if (cb) { cb() } } -p.end = function () { +p.end = function() { p.closed = true } -p.setKeepAlive = function () {} +p.setKeepAlive = function() {} p.closed = false p.writable = true -const createClient = function () { +const createClient = function() { var stream = new MemoryStream() stream.readyState = 'open' var client = new Client({ diff --git a/packages/pg/test/unit/utils-tests.js b/packages/pg/test/unit/utils-tests.js index 3d087ad0d..3ebc9a55a 100644 --- a/packages/pg/test/unit/utils-tests.js +++ b/packages/pg/test/unit/utils-tests.js @@ -3,7 +3,7 @@ var helper = require('./test-helper') var utils = require('./../../lib/utils') var defaults = require('./../../lib').defaults -test('ensure types is exported on root object', function () { +test('ensure types is exported on root object', function() { var pg = require('../../lib') assert(pg.types) assert(pg.types.getTypeParser) @@ -13,12 +13,12 @@ test('ensure types is exported on root object', function () { // this tests the monkey patching // to ensure comptability with older // versions of node -test('EventEmitter.once', function (t) { +test('EventEmitter.once', function(t) { // an event emitter var stream = new MemoryStream() var callCount = 0 - stream.once('single', function () { + stream.once('single', function() { callCount++ }) @@ -27,9 +27,9 @@ test('EventEmitter.once', function (t) { assert.equal(callCount, 1) }) -test('normalizing query configs', function () { +test('normalizing query configs', function() { var config - var callback = function () {} + var callback = function() {} config = utils.normalizeQueryConfig({ text: 'TEXT' }) assert.same(config, { text: 'TEXT' }) @@ -47,13 +47,13 @@ test('normalizing query configs', function () { assert.deepEqual(config, { text: 'TEXT', values: [10], callback: callback }) }) -test('prepareValues: buffer prepared properly', function () { +test('prepareValues: buffer prepared properly', function() { var buf = Buffer.from('quack') var out = utils.prepareValue(buf) assert.strictEqual(buf, out) }) -test('prepareValues: Uint8Array prepared properly', function () { +test('prepareValues: Uint8Array prepared properly', function() { var buf = new Uint8Array([1, 2, 3]).subarray(1, 2) var out = utils.prepareValue(buf) assert.ok(Buffer.isBuffer(out)) @@ -61,7 +61,7 @@ test('prepareValues: Uint8Array prepared properly', function () { assert.deepEqual(out[0], 2) }) -test('prepareValues: date prepared properly', function () { +test('prepareValues: date prepared properly', function() { helper.setTimezoneOffset(-330) var date = new Date(2014, 1, 1, 11, 11, 1, 7) @@ -71,7 +71,7 @@ test('prepareValues: date prepared properly', function () { helper.resetTimezoneOffset() }) -test('prepareValues: date prepared properly as UTC', function () { +test('prepareValues: date prepared properly as UTC', function() { defaults.parseInputDatesAsUTC = true // make a date in the local timezone that represents a specific UTC point in time @@ -82,7 +82,7 @@ test('prepareValues: date prepared properly as UTC', function () { defaults.parseInputDatesAsUTC = false }) -test('prepareValues: BC date prepared properly', function () { +test('prepareValues: BC date prepared properly', function() { helper.setTimezoneOffset(-330) var date = new Date(-3245, 1, 1, 11, 11, 1, 7) @@ -92,7 +92,7 @@ test('prepareValues: BC date prepared properly', function () { helper.resetTimezoneOffset() }) -test('prepareValues: 1 BC date prepared properly', function () { +test('prepareValues: 1 BC date prepared properly', function() { helper.setTimezoneOffset(-330) // can't use the multi-argument constructor as year 0 would be interpreted as 1900 @@ -103,47 +103,47 @@ test('prepareValues: 1 BC date prepared properly', function () { helper.resetTimezoneOffset() }) -test('prepareValues: undefined prepared properly', function () { +test('prepareValues: undefined prepared properly', function() { var out = utils.prepareValue(void 0) assert.strictEqual(out, null) }) -test('prepareValue: null prepared properly', function () { +test('prepareValue: null prepared properly', function() { var out = utils.prepareValue(null) assert.strictEqual(out, null) }) -test('prepareValue: true prepared properly', function () { +test('prepareValue: true prepared properly', function() { var out = utils.prepareValue(true) assert.strictEqual(out, 'true') }) -test('prepareValue: false prepared properly', function () { +test('prepareValue: false prepared properly', function() { var out = utils.prepareValue(false) assert.strictEqual(out, 'false') }) -test('prepareValue: number prepared properly', function () { +test('prepareValue: number prepared properly', function() { var out = utils.prepareValue(3.042) assert.strictEqual(out, '3.042') }) -test('prepareValue: string prepared properly', function () { +test('prepareValue: string prepared properly', function() { var out = utils.prepareValue('big bad wolf') assert.strictEqual(out, 'big bad wolf') }) -test('prepareValue: simple array prepared properly', function () { +test('prepareValue: simple array prepared properly', function() { var out = utils.prepareValue([1, null, 3, undefined, [5, 6, 'squ,awk']]) assert.strictEqual(out, '{"1",NULL,"3",NULL,{"5","6","squ,awk"}}') }) -test('prepareValue: complex array prepared properly', function () { +test('prepareValue: complex array prepared properly', function() { var out = utils.prepareValue([{ x: 42 }, { y: 84 }]) assert.strictEqual(out, '{"{\\"x\\":42}","{\\"y\\":84}"}') }) -test('prepareValue: date array prepared properly', function () { +test('prepareValue: date array prepared properly', function() { helper.setTimezoneOffset(-330) var date = new Date(2014, 1, 1, 11, 11, 1, 7) @@ -153,14 +153,14 @@ test('prepareValue: date array prepared properly', function () { helper.resetTimezoneOffset() }) -test('prepareValue: arbitrary objects prepared properly', function () { +test('prepareValue: arbitrary objects prepared properly', function() { var out = utils.prepareValue({ x: 42 }) assert.strictEqual(out, '{"x":42}') }) -test('prepareValue: objects with simple toPostgres prepared properly', function () { +test('prepareValue: objects with simple toPostgres prepared properly', function() { var customType = { - toPostgres: function () { + toPostgres: function() { return 'zomgcustom!' }, } @@ -168,17 +168,17 @@ test('prepareValue: objects with simple toPostgres prepared properly', function assert.strictEqual(out, 'zomgcustom!') }) -test('prepareValue: buffer array prepared properly', function () { +test('prepareValue: buffer array prepared properly', function() { var buffer1 = Buffer.from('dead', 'hex') var buffer2 = Buffer.from('beef', 'hex') var out = utils.prepareValue([buffer1, buffer2]) assert.strictEqual(out, '{\\\\xdead,\\\\xbeef}') }) -test('prepareValue: objects with complex toPostgres prepared properly', function () { +test('prepareValue: objects with complex toPostgres prepared properly', function() { var buf = Buffer.from('zomgcustom!') var customType = { - toPostgres: function () { + toPostgres: function() { return [1, 2] }, } @@ -186,19 +186,19 @@ test('prepareValue: objects with complex toPostgres prepared properly', function assert.strictEqual(out, '{"1","2"}') }) -test('prepareValue: objects with toPostgres receive prepareValue', function () { +test('prepareValue: objects with toPostgres receive prepareValue', function() { var customRange = { lower: { - toPostgres: function () { + toPostgres: function() { return 5 }, }, upper: { - toPostgres: function () { + toPostgres: function() { return 10 }, }, - toPostgres: function (prepare) { + toPostgres: function(prepare) { return '[' + prepare(this.lower) + ',' + prepare(this.upper) + ']' }, } @@ -206,12 +206,12 @@ test('prepareValue: objects with toPostgres receive prepareValue', function () { assert.strictEqual(out, '[5,10]') }) -test('prepareValue: objects with circular toPostgres rejected', function () { +test('prepareValue: objects with circular toPostgres rejected', function() { var buf = Buffer.from('zomgcustom!') var customType = { - toPostgres: function () { + toPostgres: function() { return { - toPostgres: function () { + toPostgres: function() { return customType }, } @@ -229,9 +229,9 @@ test('prepareValue: objects with circular toPostgres rejected', function () { throw new Error('Expected prepareValue to throw exception') }) -test('prepareValue: can safely be used to map an array of values including those with toPostgres functions', function () { +test('prepareValue: can safely be used to map an array of values including those with toPostgres functions', function() { var customType = { - toPostgres: function () { + toPostgres: function() { return 'zomgcustom!' }, } diff --git a/yarn.lock b/yarn.lock index 60f2b1bca..a127d9cc6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4632,10 +4632,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.4.tgz#2d1bae173e355996ee355ec9830a7a1ee05457ef" - integrity sha512-SVJIQ51spzFDvh4fIbCLvciiDMCrRhlN3mbZvv/+ycjvmF5E73bKdGfU8QDLNmjYJf+lsGnDBC4UUnvTe5OO0w== +prettier@1.19.1: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== process-nextick-args@~2.0.0: version "2.0.1" From 8591d94fccb6bf5435ae8c1b7e3edb242e616a5a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 10 Apr 2020 11:31:03 -0500 Subject: [PATCH 0622/1037] Re-upgrade to prettier@2.x --- package.json | 8 +- packages/pg-cursor/index.js | 36 ++--- packages/pg-cursor/test/close.js | 22 +-- packages/pg-cursor/test/error-handling.js | 26 ++-- packages/pg-cursor/test/index.js | 68 ++++----- packages/pg-cursor/test/no-data-handling.js | 14 +- packages/pg-cursor/test/pool.js | 20 +-- packages/pg-pool/index.js | 10 +- .../pg-pool/test/bring-your-own-promise.js | 6 +- packages/pg-pool/test/connection-strings.js | 12 +- packages/pg-pool/test/connection-timeout.js | 6 +- packages/pg-pool/test/ending.js | 4 +- packages/pg-pool/test/error-handling.js | 26 ++-- packages/pg-pool/test/events.js | 32 ++-- packages/pg-pool/test/idle-timeout.js | 6 +- packages/pg-pool/test/index.js | 92 ++++++------ packages/pg-pool/test/logging.js | 8 +- packages/pg-pool/test/max-uses.js | 12 +- packages/pg-pool/test/sizing.js | 6 +- .../pg-protocol/src/inbound-parser.test.ts | 50 +++--- .../src/outbound-serializer.test.ts | 110 +++++--------- packages/pg-protocol/src/serializer.ts | 14 +- .../pg-protocol/src/testing/buffer-list.ts | 4 +- .../pg-protocol/src/testing/test-buffers.ts | 88 +++++------ packages/pg-query-stream/test/close.js | 26 ++-- packages/pg-query-stream/test/concat.js | 10 +- packages/pg-query-stream/test/empty-query.js | 10 +- packages/pg-query-stream/test/error.js | 10 +- packages/pg-query-stream/test/fast-reader.js | 10 +- packages/pg-query-stream/test/helper.js | 8 +- packages/pg-query-stream/test/instant.js | 6 +- packages/pg-query-stream/test/issue-3.js | 12 +- .../pg-query-stream/test/passing-options.js | 6 +- packages/pg-query-stream/test/pauses.js | 6 +- packages/pg-query-stream/test/slow-reader.js | 10 +- .../test/stream-tester-timestamp.js | 13 +- .../pg-query-stream/test/stream-tester.js | 9 +- packages/pg/lib/client.js | 74 ++++----- packages/pg/lib/connection-fast.js | 54 +++---- packages/pg/lib/connection-parameters.js | 14 +- packages/pg/lib/connection.js | 142 ++++++++---------- packages/pg/lib/defaults.js | 2 +- packages/pg/lib/index.js | 2 +- packages/pg/lib/native/client.js | 38 ++--- packages/pg/lib/native/query.js | 24 +-- packages/pg/lib/result.js | 12 +- packages/pg/lib/sasl.js | 14 +- packages/pg/lib/type-overrides.js | 6 +- packages/pg/lib/utils.js | 11 +- packages/pg/script/dump-db-types.js | 4 +- packages/pg/script/list-db-types.js | 2 +- packages/pg/test/buffer-list.js | 24 +-- .../pg/test/integration/client/api-tests.js | 54 +++---- .../test/integration/client/appname-tests.js | 28 ++-- .../pg/test/integration/client/array-tests.js | 56 +++---- .../client/big-simple-query-tests.js | 30 ++-- .../integration/client/configuration-tests.js | 4 +- .../integration/client/custom-types-tests.js | 4 +- .../integration/client/empty-query-tests.js | 8 +- .../client/error-handling-tests.js | 38 ++--- .../client/field-name-escape-tests.js | 2 +- .../integration/client/huge-numeric-tests.js | 8 +- ...le_in_transaction_session_timeout-tests.js | 28 ++-- .../client/json-type-parsing-tests.js | 6 +- .../client/multiple-results-tests.js | 6 +- .../client/network-partition-tests.js | 22 +-- .../test/integration/client/no-data-tests.js | 4 +- .../integration/client/no-row-result-tests.js | 8 +- .../test/integration/client/notice-tests.js | 18 +-- .../integration/client/parse-int-8-tests.js | 8 +- .../client/prepared-statement-tests.js | 42 +++--- .../client/query-as-promise-tests.js | 10 +- .../client/query-column-names-tests.js | 6 +- ...error-handling-prepared-statement-tests.js | 30 ++-- .../client/query-error-handling-tests.js | 32 ++-- .../client/result-metadata-tests.js | 12 +- .../client/results-as-array-tests.js | 8 +- .../row-description-on-results-tests.js | 14 +- .../integration/client/simple-query-tests.js | 32 ++-- .../pg/test/integration/client/ssl-tests.js | 6 +- .../client/statement_timeout-tests.js | 26 ++-- .../test/integration/client/timezone-tests.js | 10 +- .../integration/client/transaction-tests.js | 26 ++-- .../integration/client/type-coercion-tests.js | 40 ++--- .../client/type-parser-override-tests.js | 14 +- .../connection-pool/error-tests.js | 10 +- .../connection-pool/idle-timeout-tests.js | 4 +- .../connection-pool/native-instance-tests.js | 2 +- .../connection-pool/test-helper.js | 8 +- .../connection-pool/yield-support-tests.js | 2 +- .../connection/bound-command-tests.js | 24 +-- .../test/integration/connection/copy-tests.js | 20 +-- .../connection/notification-tests.js | 8 +- .../integration/connection/query-tests.js | 10 +- .../integration/connection/test-helper.js | 16 +- packages/pg/test/integration/domain-tests.js | 20 +-- .../test/integration/gh-issues/130-tests.js | 8 +- .../test/integration/gh-issues/131-tests.js | 6 +- .../test/integration/gh-issues/1854-tests.js | 2 +- .../test/integration/gh-issues/199-tests.js | 2 +- .../test/integration/gh-issues/507-tests.js | 6 +- .../test/integration/gh-issues/600-tests.js | 16 +- .../test/integration/gh-issues/675-tests.js | 8 +- .../test/integration/gh-issues/699-tests.js | 6 +- .../test/integration/gh-issues/787-tests.js | 4 +- .../test/integration/gh-issues/882-tests.js | 2 +- .../test/integration/gh-issues/981-tests.js | 4 +- packages/pg/test/integration/test-helper.js | 6 +- packages/pg/test/native/callback-api-tests.js | 12 +- packages/pg/test/native/evented-api-tests.js | 46 +++--- packages/pg/test/native/stress-tests.js | 18 +-- packages/pg/test/test-buffers.js | 78 ++++------ packages/pg/test/test-helper.js | 56 +++---- .../unit/client/cleartext-password-tests.js | 4 +- .../test/unit/client/configuration-tests.js | 26 ++-- .../unit/client/early-disconnect-tests.js | 6 +- packages/pg/test/unit/client/escape-tests.js | 10 +- .../pg/test/unit/client/md5-password-tests.js | 8 +- .../pg/test/unit/client/notification-tests.js | 4 +- .../unit/client/prepared-statement-tests.js | 70 ++++----- .../pg/test/unit/client/query-queue-tests.js | 26 ++-- .../test/unit/client/result-metadata-tests.js | 8 +- .../pg/test/unit/client/sasl-scram-tests.js | 48 +++--- .../pg/test/unit/client/simple-query-tests.js | 48 +++--- ...tream-and-query-error-interaction-tests.js | 12 +- packages/pg/test/unit/client/test-helper.js | 8 +- .../unit/client/throw-in-type-parser-tests.js | 12 +- .../connection-parameters/creation-tests.js | 64 ++++---- .../environment-variable-tests.js | 14 +- .../pg/test/unit/connection/error-tests.js | 20 +-- .../unit/connection/inbound-parser-tests.js | 98 ++++++------ .../unit/connection/outbound-sending-tests.js | 85 ++++------- .../pg/test/unit/connection/startup-tests.js | 32 ++-- packages/pg/test/unit/test-helper.js | 10 +- packages/pg/test/unit/utils-tests.js | 70 ++++----- yarn.lock | 8 +- 136 files changed, 1415 insertions(+), 1559 deletions(-) diff --git a/package.json b/package.json index 4eb352834..9ab3733fc 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "test": "yarn lerna exec yarn test", "build": "yarn lerna exec --scope pg-protocol yarn build", "pretest": "yarn build", - "lint": "eslint '*/**/*.{js,ts,tsx}'" + "lint": "!([[ -e node_modules/.bin/prettier ]]) || eslint '*/**/*.{js,ts,tsx}'" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^2.27.0", @@ -22,8 +22,10 @@ "eslint-config-prettier": "^6.10.1", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^3.1.2", - "lerna": "^3.19.0", - "prettier": "1.19.1" + "lerna": "^3.19.0" + }, + "optionalDependencies": { + "prettier": "2.0.4" }, "prettier": { "semi": false, diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index 1750b34c8..9d672dbff 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -25,18 +25,18 @@ function Cursor(text, values, config) { util.inherits(Cursor, EventEmitter) -Cursor.prototype._ifNoData = function() { +Cursor.prototype._ifNoData = function () { this.state = 'idle' this._shiftQueue() } -Cursor.prototype._rowDescription = function() { +Cursor.prototype._rowDescription = function () { if (this.connection) { this.connection.removeListener('noData', this._ifNoData) } } -Cursor.prototype.submit = function(connection) { +Cursor.prototype.submit = function (connection) { this.connection = connection this._portal = 'C_' + nextUniqueID++ @@ -75,13 +75,13 @@ Cursor.prototype.submit = function(connection) { con.once('rowDescription', this._rowDescription) } -Cursor.prototype._shiftQueue = function() { +Cursor.prototype._shiftQueue = function () { if (this._queue.length) { this._getRows.apply(this, this._queue.shift()) } } -Cursor.prototype._closePortal = function() { +Cursor.prototype._closePortal = function () { // because we opened a named portal to stream results // we need to close the same named portal. Leaving a named portal // open can lock tables for modification if inside a transaction. @@ -90,19 +90,19 @@ Cursor.prototype._closePortal = function() { this.connection.sync() } -Cursor.prototype.handleRowDescription = function(msg) { +Cursor.prototype.handleRowDescription = function (msg) { this._result.addFields(msg.fields) this.state = 'idle' this._shiftQueue() } -Cursor.prototype.handleDataRow = function(msg) { +Cursor.prototype.handleDataRow = function (msg) { const row = this._result.parseRow(msg.fields) this.emit('row', row, this._result) this._rows.push(row) } -Cursor.prototype._sendRows = function() { +Cursor.prototype._sendRows = function () { this.state = 'idle' setImmediate(() => { const cb = this._cb @@ -118,26 +118,26 @@ Cursor.prototype._sendRows = function() { }) } -Cursor.prototype.handleCommandComplete = function(msg) { +Cursor.prototype.handleCommandComplete = function (msg) { this._result.addCommandComplete(msg) this._closePortal() } -Cursor.prototype.handlePortalSuspended = function() { +Cursor.prototype.handlePortalSuspended = function () { this._sendRows() } -Cursor.prototype.handleReadyForQuery = function() { +Cursor.prototype.handleReadyForQuery = function () { this._sendRows() this.state = 'done' this.emit('end', this._result) } -Cursor.prototype.handleEmptyQuery = function() { +Cursor.prototype.handleEmptyQuery = function () { this.connection.sync() } -Cursor.prototype.handleError = function(msg) { +Cursor.prototype.handleError = function (msg) { this.connection.removeListener('noData', this._ifNoData) this.connection.removeListener('rowDescription', this._rowDescription) this.state = 'error' @@ -159,7 +159,7 @@ Cursor.prototype.handleError = function(msg) { this.connection.sync() } -Cursor.prototype._getRows = function(rows, cb) { +Cursor.prototype._getRows = function (rows, cb) { this.state = 'busy' this._cb = cb this._rows = [] @@ -173,7 +173,7 @@ Cursor.prototype._getRows = function(rows, cb) { // users really shouldn't be calling 'end' here and terminating a connection to postgres // via the low level connection.end api -Cursor.prototype.end = util.deprecate(function(cb) { +Cursor.prototype.end = util.deprecate(function (cb) { if (this.state !== 'initialized') { this.connection.sync() } @@ -181,7 +181,7 @@ Cursor.prototype.end = util.deprecate(function(cb) { this.connection.end() }, 'Cursor.end is deprecated. Call end on the client itself to end a connection to the database.') -Cursor.prototype.close = function(cb) { +Cursor.prototype.close = function (cb) { if (!this.connection || this.state === 'done') { if (cb) { return setImmediate(cb) @@ -192,13 +192,13 @@ Cursor.prototype.close = function(cb) { this._closePortal() this.state = 'done' if (cb) { - this.connection.once('readyForQuery', function() { + this.connection.once('readyForQuery', function () { cb() }) } } -Cursor.prototype.read = function(rows, cb) { +Cursor.prototype.read = function (rows, cb) { if (this.state === 'idle') { return this._getRows(rows, cb) } diff --git a/packages/pg-cursor/test/close.js b/packages/pg-cursor/test/close.js index fbaa68069..e63512abd 100644 --- a/packages/pg-cursor/test/close.js +++ b/packages/pg-cursor/test/close.js @@ -3,51 +3,51 @@ const Cursor = require('../') const pg = require('pg') const text = 'SELECT generate_series as num FROM generate_series(0, 50)' -describe('close', function() { - beforeEach(function(done) { +describe('close', function () { + beforeEach(function (done) { const client = (this.client = new pg.Client()) client.connect(done) }) - this.afterEach(function(done) { + this.afterEach(function (done) { this.client.end(done) }) - it('can close a finished cursor without a callback', function(done) { + it('can close a finished cursor without a callback', function (done) { const cursor = new Cursor(text) this.client.query(cursor) this.client.query('SELECT NOW()', done) - cursor.read(100, function(err) { + cursor.read(100, function (err) { assert.ifError(err) cursor.close() }) }) - it('closes cursor early', function(done) { + it('closes cursor early', function (done) { const cursor = new Cursor(text) this.client.query(cursor) this.client.query('SELECT NOW()', done) - cursor.read(25, function(err) { + cursor.read(25, function (err) { assert.ifError(err) cursor.close() }) }) - it('works with callback style', function(done) { + it('works with callback style', function (done) { const cursor = new Cursor(text) const client = this.client client.query(cursor) - cursor.read(25, function(err, rows) { + cursor.read(25, function (err, rows) { assert.ifError(err) assert.strictEqual(rows.length, 25) - cursor.close(function(err) { + cursor.close(function (err) { assert.ifError(err) client.query('SELECT NOW()', done) }) }) }) - it('is a no-op to "close" the cursor before submitting it', function(done) { + it('is a no-op to "close" the cursor before submitting it', function (done) { const cursor = new Cursor(text) cursor.close(done) }) diff --git a/packages/pg-cursor/test/error-handling.js b/packages/pg-cursor/test/error-handling.js index a6c38342e..f6edef6d5 100644 --- a/packages/pg-cursor/test/error-handling.js +++ b/packages/pg-cursor/test/error-handling.js @@ -5,14 +5,14 @@ const pg = require('pg') const text = 'SELECT generate_series as num FROM generate_series(0, 4)' -describe('error handling', function() { - it('can continue after error', function(done) { +describe('error handling', function () { + it('can continue after error', function (done) { const client = new pg.Client() client.connect() const cursor = client.query(new Cursor('asdfdffsdf')) - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(err) - client.query('SELECT NOW()', function(err) { + client.query('SELECT NOW()', function (err) { assert.ifError(err) client.end() done() @@ -27,11 +27,11 @@ describe('read callback does not fire sync', () => { client.connect() const cursor = client.query(new Cursor('asdfdffsdf')) let after = false - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(err, 'error should be returned') assert.strictEqual(after, true, 'should not call read sync') after = false - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(err, 'error should be returned') assert.strictEqual(after, true, 'should not call read sync') client.end() @@ -47,13 +47,13 @@ describe('read callback does not fire sync', () => { client.connect() const cursor = client.query(new Cursor('SELECT NOW()')) let after = false - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(!err) assert.strictEqual(after, true, 'should not call read sync') - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(!err) after = false - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(!err) assert.strictEqual(after, true, 'should not call read sync') client.end() @@ -66,16 +66,16 @@ describe('read callback does not fire sync', () => { }) }) -describe('proper cleanup', function() { - it('can issue multiple cursors on one client', function(done) { +describe('proper cleanup', function () { + it('can issue multiple cursors on one client', function (done) { const client = new pg.Client() client.connect() const cursor1 = client.query(new Cursor(text)) - cursor1.read(8, function(err, rows) { + cursor1.read(8, function (err, rows) { assert.ifError(err) assert.strictEqual(rows.length, 5) const cursor2 = client.query(new Cursor(text)) - cursor2.read(8, function(err, rows) { + cursor2.read(8, function (err, rows) { assert.ifError(err) assert.strictEqual(rows.length, 5) client.end() diff --git a/packages/pg-cursor/test/index.js b/packages/pg-cursor/test/index.js index 462442235..24d3cfd79 100644 --- a/packages/pg-cursor/test/index.js +++ b/packages/pg-cursor/test/index.js @@ -4,58 +4,58 @@ const pg = require('pg') const text = 'SELECT generate_series as num FROM generate_series(0, 5)' -describe('cursor', function() { - beforeEach(function(done) { +describe('cursor', function () { + beforeEach(function (done) { const client = (this.client = new pg.Client()) client.connect(done) - this.pgCursor = function(text, values) { + this.pgCursor = function (text, values) { return client.query(new Cursor(text, values || [])) } }) - afterEach(function() { + afterEach(function () { this.client.end() }) - it('fetch 6 when asking for 10', function(done) { + it('fetch 6 when asking for 10', function (done) { const cursor = this.pgCursor(text) - cursor.read(10, function(err, res) { + cursor.read(10, function (err, res) { assert.ifError(err) assert.strictEqual(res.length, 6) done() }) }) - it('end before reading to end', function(done) { + it('end before reading to end', function (done) { const cursor = this.pgCursor(text) - cursor.read(3, function(err, res) { + cursor.read(3, function (err, res) { assert.ifError(err) assert.strictEqual(res.length, 3) done() }) }) - it('callback with error', function(done) { + it('callback with error', function (done) { const cursor = this.pgCursor('select asdfasdf') - cursor.read(1, function(err) { + cursor.read(1, function (err) { assert(err) done() }) }) - it('read a partial chunk of data', function(done) { + it('read a partial chunk of data', function (done) { const cursor = this.pgCursor(text) - cursor.read(2, function(err, res) { + cursor.read(2, function (err, res) { assert.ifError(err) assert.strictEqual(res.length, 2) - cursor.read(3, function(err, res) { + cursor.read(3, function (err, res) { assert(!err) assert.strictEqual(res.length, 3) - cursor.read(1, function(err, res) { + cursor.read(1, function (err, res) { assert(!err) assert.strictEqual(res.length, 1) - cursor.read(1, function(err, res) { + cursor.read(1, function (err, res) { assert(!err) assert.ifError(err) assert.strictEqual(res.length, 0) @@ -66,14 +66,14 @@ describe('cursor', function() { }) }) - it('read return length 0 past the end', function(done) { + it('read return length 0 past the end', function (done) { const cursor = this.pgCursor(text) - cursor.read(2, function(err) { + cursor.read(2, function (err) { assert(!err) - cursor.read(100, function(err, res) { + cursor.read(100, function (err, res) { assert(!err) assert.strictEqual(res.length, 4) - cursor.read(100, function(err, res) { + cursor.read(100, function (err, res) { assert(!err) assert.strictEqual(res.length, 0) done() @@ -82,14 +82,14 @@ describe('cursor', function() { }) }) - it('read huge result', function(done) { + it('read huge result', function (done) { this.timeout(10000) const text = 'SELECT generate_series as num FROM generate_series(0, 100000)' const values = [] const cursor = this.pgCursor(text, values) let count = 0 - const read = function() { - cursor.read(100, function(err, rows) { + const read = function () { + cursor.read(100, function (err, rows) { if (err) return done(err) if (!rows.length) { assert.strictEqual(count, 100001) @@ -105,14 +105,14 @@ describe('cursor', function() { read() }) - it('normalizes parameter values', function(done) { + it('normalizes parameter values', function (done) { const text = 'SELECT $1::json me' const values = [{ name: 'brian' }] const cursor = this.pgCursor(text, values) - cursor.read(1, function(err, rows) { + cursor.read(1, function (err, rows) { if (err) return done(err) assert.strictEqual(rows[0].me.name, 'brian') - cursor.read(1, function(err, rows) { + cursor.read(1, function (err, rows) { assert(!err) assert.strictEqual(rows.length, 0) done() @@ -120,9 +120,9 @@ describe('cursor', function() { }) }) - it('returns result along with rows', function(done) { + it('returns result along with rows', function (done) { const cursor = this.pgCursor(text) - cursor.read(1, function(err, rows, result) { + cursor.read(1, function (err, rows, result) { assert.ifError(err) assert.strictEqual(rows.length, 1) assert.strictEqual(rows, result.rows) @@ -134,7 +134,7 @@ describe('cursor', function() { }) }) - it('emits row events', function(done) { + it('emits row events', function (done) { const cursor = this.pgCursor(text) cursor.read(10) cursor.on('row', (row, result) => result.addRow(row)) @@ -144,7 +144,7 @@ describe('cursor', function() { }) }) - it('emits row events when cursor is closed manually', function(done) { + it('emits row events when cursor is closed manually', function (done) { const cursor = this.pgCursor(text) cursor.on('row', (row, result) => result.addRow(row)) cursor.on('end', (result) => { @@ -155,21 +155,21 @@ describe('cursor', function() { cursor.read(3, () => cursor.close()) }) - it('emits error events', function(done) { + it('emits error events', function (done) { const cursor = this.pgCursor('select asdfasdf') - cursor.on('error', function(err) { + cursor.on('error', function (err) { assert(err) done() }) }) - it('returns rowCount on insert', function(done) { + it('returns rowCount on insert', function (done) { const pgCursor = this.pgCursor this.client .query('CREATE TEMPORARY TABLE pg_cursor_test (foo VARCHAR(1), bar VARCHAR(1))') - .then(function() { + .then(function () { const cursor = pgCursor('insert into pg_cursor_test values($1, $2)', ['a', 'b']) - cursor.read(1, function(err, rows, result) { + cursor.read(1, function (err, rows, result) { assert.ifError(err) assert.strictEqual(rows.length, 0) assert.strictEqual(result.rowCount, 1) diff --git a/packages/pg-cursor/test/no-data-handling.js b/packages/pg-cursor/test/no-data-handling.js index 755658746..9c860b9cd 100644 --- a/packages/pg-cursor/test/no-data-handling.js +++ b/packages/pg-cursor/test/no-data-handling.js @@ -2,30 +2,30 @@ const assert = require('assert') const pg = require('pg') const Cursor = require('../') -describe('queries with no data', function() { - beforeEach(function(done) { +describe('queries with no data', function () { + beforeEach(function (done) { const client = (this.client = new pg.Client()) client.connect(done) }) - afterEach(function() { + afterEach(function () { this.client.end() }) - it('handles queries that return no data', function(done) { + it('handles queries that return no data', function (done) { const cursor = new Cursor('CREATE TEMPORARY TABLE whatwhat (thing int)') this.client.query(cursor) - cursor.read(100, function(err, rows) { + cursor.read(100, function (err, rows) { assert.ifError(err) assert.strictEqual(rows.length, 0) done() }) }) - it('handles empty query', function(done) { + it('handles empty query', function (done) { let cursor = new Cursor('-- this is a comment') cursor = this.client.query(cursor) - cursor.read(100, function(err, rows) { + cursor.read(100, function (err, rows) { assert.ifError(err) assert.strictEqual(rows.length, 0) done() diff --git a/packages/pg-cursor/test/pool.js b/packages/pg-cursor/test/pool.js index 9562ca8ae..9d8ca772f 100644 --- a/packages/pg-cursor/test/pool.js +++ b/packages/pg-cursor/test/pool.js @@ -31,16 +31,16 @@ function poolQueryPromise(pool, readRowCount) { }) } -describe('pool', function() { - beforeEach(function() { +describe('pool', function () { + beforeEach(function () { this.pool = new pg.Pool({ max: 1 }) }) - afterEach(function() { + afterEach(function () { this.pool.end() }) - it('closes cursor early, single pool query', function(done) { + it('closes cursor early, single pool query', function (done) { poolQueryPromise(this.pool, 25) .then(() => done()) .catch((err) => { @@ -49,7 +49,7 @@ describe('pool', function() { }) }) - it('closes cursor early, saturated pool', function(done) { + it('closes cursor early, saturated pool', function (done) { const promises = [] for (let i = 0; i < 10; i++) { promises.push(poolQueryPromise(this.pool, 25)) @@ -62,7 +62,7 @@ describe('pool', function() { }) }) - it('closes exhausted cursor, single pool query', function(done) { + it('closes exhausted cursor, single pool query', function (done) { poolQueryPromise(this.pool, 100) .then(() => done()) .catch((err) => { @@ -71,7 +71,7 @@ describe('pool', function() { }) }) - it('closes exhausted cursor, saturated pool', function(done) { + it('closes exhausted cursor, saturated pool', function (done) { const promises = [] for (let i = 0; i < 10; i++) { promises.push(poolQueryPromise(this.pool, 100)) @@ -84,16 +84,16 @@ describe('pool', function() { }) }) - it('can close multiple times on a pool', async function() { + it('can close multiple times on a pool', async function () { const pool = new pg.Pool({ max: 1 }) const run = async () => { const cursor = new Cursor(text) const client = await pool.connect() client.query(cursor) await new Promise((resolve) => { - cursor.read(25, function(err) { + cursor.read(25, function (err) { assert.ifError(err) - cursor.close(function(err) { + cursor.close(function (err) { assert.ifError(err) client.release() resolve() diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index fe104a3df..27875c1f8 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -1,7 +1,7 @@ 'use strict' const EventEmitter = require('events').EventEmitter -const NOOP = function() {} +const NOOP = function () {} const removeWhere = (list, predicate) => { const i = list.findIndex(predicate) @@ -33,10 +33,10 @@ function promisify(Promise, callback) { } let rej let res - const cb = function(err, client) { + const cb = function (err, client) { err ? rej(err) : res(client) } - const result = new Promise(function(resolve, reject) { + const result = new Promise(function (resolve, reject) { res = resolve rej = reject }) @@ -76,7 +76,7 @@ class Pool extends EventEmitter { this.options.max = this.options.max || this.options.poolSize || 10 this.options.maxUses = this.options.maxUses || Infinity - this.log = this.options.log || function() {} + this.log = this.options.log || function () {} this.Client = this.options.Client || Client || require('pg').Client this.Promise = this.options.Promise || global.Promise @@ -321,7 +321,7 @@ class Pool extends EventEmitter { // guard clause against passing a function as the first parameter if (typeof text === 'function') { const response = promisify(this.Promise, text) - setImmediate(function() { + setImmediate(function () { return response.callback(new Error('Passing a function as the first parameter to pool.query is not supported')) }) return response.result diff --git a/packages/pg-pool/test/bring-your-own-promise.js b/packages/pg-pool/test/bring-your-own-promise.js index b9a74d433..e905ccc0b 100644 --- a/packages/pg-pool/test/bring-your-own-promise.js +++ b/packages/pg-pool/test/bring-your-own-promise.js @@ -13,10 +13,10 @@ const checkType = (promise) => { return promise.catch((e) => undefined) } -describe('Bring your own promise', function() { +describe('Bring your own promise', function () { it( 'uses supplied promise for operations', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool({ Promise: BluebirdPromise }) const client1 = yield checkType(pool.connect()) client1.release() @@ -30,7 +30,7 @@ describe('Bring your own promise', function() { it( 'uses promises in errors', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool({ Promise: BluebirdPromise, port: 48484 }) yield checkType(pool.connect()) yield checkType(pool.end()) diff --git a/packages/pg-pool/test/connection-strings.js b/packages/pg-pool/test/connection-strings.js index 6d9794143..de45830dc 100644 --- a/packages/pg-pool/test/connection-strings.js +++ b/packages/pg-pool/test/connection-strings.js @@ -3,25 +3,25 @@ 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) { +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) { + Client: function (args) { expect(args.connectionString).to.equal(connectionString) return { - connect: function(cb) { + connect: function (cb) { cb(new Error('testing')) }, - on: function() {}, + on: function () {}, } }, connectionString: connectionString, }) - pool.connect(function(err, client) { + pool.connect(function (err, client) { expect(err).to.not.be(undefined) done() }) diff --git a/packages/pg-pool/test/connection-timeout.js b/packages/pg-pool/test/connection-timeout.js index 1624a1ec2..05e8931df 100644 --- a/packages/pg-pool/test/connection-timeout.js +++ b/packages/pg-pool/test/connection-timeout.js @@ -54,7 +54,7 @@ describe('connection timeout', () => { it( 'should handle multiple timeouts', co.wrap( - function*() { + function* () { const errors = [] const pool = new Pool({ connectionTimeoutMillis: 1, port: this.port, host: 'localhost' }) for (var i = 0; i < 15; i++) { @@ -142,7 +142,7 @@ describe('connection timeout', () => { const orgConnect = Client.prototype.connect let called = false - Client.prototype.connect = function(cb) { + Client.prototype.connect = function (cb) { // Simulate a failure on first call if (!called) { called = true @@ -179,7 +179,7 @@ describe('connection timeout', () => { let connection = 0 - Client.prototype.connect = function(cb) { + Client.prototype.connect = function (cb) { // Simulate a failure on first call if (connection === 0) { connection++ diff --git a/packages/pg-pool/test/ending.js b/packages/pg-pool/test/ending.js index 379575bdb..e1839b46c 100644 --- a/packages/pg-pool/test/ending.js +++ b/packages/pg-pool/test/ending.js @@ -19,7 +19,7 @@ describe('pool ending', () => { it( 'ends with clients', - co.wrap(function*() { + 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') @@ -29,7 +29,7 @@ describe('pool ending', () => { it( 'allows client to finish', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool() const query = pool.query('SELECT $1::text as name', ['brianc']) yield pool.end() diff --git a/packages/pg-pool/test/error-handling.js b/packages/pg-pool/test/error-handling.js index 6c92dd729..fea1d1148 100644 --- a/packages/pg-pool/test/error-handling.js +++ b/packages/pg-pool/test/error-handling.js @@ -8,20 +8,20 @@ const it = require('mocha').it const Pool = require('../') -describe('pool error handling', function() { - it('Should complete these queries without dying', function(done) { +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) { + return new Promise(function (resolve, reject) { pool .query("SELECT 'asd'+1 ") - .then(function(res) { + .then(function (res) { reject(res) // this should always error }) - .catch(function(err) { + .catch(function (err) { errors++ resolve(err) }) @@ -31,7 +31,7 @@ describe('pool error handling', function() { for (let i = 0; i < 5; i++) { ps.push(runErrorQuery()) } - Promise.all(ps).then(function() { + Promise.all(ps).then(function () { expect(shouldGet).to.eql(errors) pool.end(done) }) @@ -40,7 +40,7 @@ describe('pool error handling', function() { describe('calling release more than once', () => { it( 'should throw each time', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool() const client = yield pool.connect() client.release() @@ -50,10 +50,10 @@ describe('pool error handling', function() { }) ) - it('should throw each time with callbacks', function(done) { + it('should throw each time with callbacks', function (done) { const pool = new Pool() - pool.connect(function(err, client, clientDone) { + pool.connect(function (err, client, clientDone) { expect(err).not.to.be.an(Error) clientDone() @@ -66,7 +66,7 @@ describe('pool error handling', function() { }) describe('calling connect after end', () => { - it('should return an error', function*() { + 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') @@ -113,7 +113,7 @@ describe('pool error handling', function() { describe('error from idle client', () => { it( 'removes client from pool', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool() const client = yield pool.connect() expect(pool.totalCount).to.equal(1) @@ -148,7 +148,7 @@ describe('pool error handling', function() { describe('error from in-use client', () => { it( 'keeps the client in the pool', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool() const client = yield pool.connect() expect(pool.totalCount).to.equal(1) @@ -195,7 +195,7 @@ describe('pool error handling', function() { describe('pool with lots of errors', () => { it( 'continues to work and provide new clients', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool({ max: 1 }) const errors = [] for (var i = 0; i < 20; i++) { diff --git a/packages/pg-pool/test/events.js b/packages/pg-pool/test/events.js index 1a0a52c1b..61979247d 100644 --- a/packages/pg-pool/test/events.js +++ b/packages/pg-pool/test/events.js @@ -6,15 +6,15 @@ const describe = require('mocha').describe const it = require('mocha').it const Pool = require('../') -describe('events', function() { - it('emits connect before callback', function(done) { +describe('events', function () { + it('emits connect before callback', function (done) { const pool = new Pool() let emittedClient = false - pool.on('connect', function(client) { + pool.on('connect', function (client) { emittedClient = client }) - pool.connect(function(err, client, release) { + pool.connect(function (err, client, release) { if (err) return done(err) release() pool.end() @@ -23,52 +23,52 @@ describe('events', function() { }) }) - it('emits "connect" only with a successful connection', function() { + it('emits "connect" only with a successful connection', function () { const pool = new Pool({ // This client will always fail to connect Client: mockClient({ - connect: function(cb) { + connect: function (cb) { process.nextTick(() => { cb(new Error('bad news')) }) }, }), }) - pool.on('connect', function() { + 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) { + it('emits acquire every time a client is acquired', function (done) { const pool = new Pool() let acquireCount = 0 - pool.on('acquire', function(client) { + pool.on('acquire', function (client) { expect(client).to.be.ok() acquireCount++ }) for (let i = 0; i < 10; i++) { - pool.connect(function(err, client, release) { + pool.connect(function (err, client, release) { if (err) return done(err) release() }) pool.query('SELECT now()') } - setTimeout(function() { + 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) { + 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) { + pool.connect(function (err, client) { expect(err).to.equal(undefined) client.release() - setImmediate(function() { + setImmediate(function () { client.emit('error', new Error('problem')) }) - pool.once('error', function(err, errClient) { + pool.once('error', function (err, errClient) { expect(err.message).to.equal('problem') expect(errClient).to.equal(client) done() @@ -78,7 +78,7 @@ describe('events', function() { }) function mockClient(methods) { - return function() { + return function () { const client = new EventEmitter() Object.assign(client, methods) return client diff --git a/packages/pg-pool/test/idle-timeout.js b/packages/pg-pool/test/idle-timeout.js index bf9bbae23..fd9fba4a4 100644 --- a/packages/pg-pool/test/idle-timeout.js +++ b/packages/pg-pool/test/idle-timeout.js @@ -22,7 +22,7 @@ describe('idle timeout', () => { it( 'times out and removes clients when others are also removed', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool({ idleTimeoutMillis: 10 }) const clientA = yield pool.connect() const clientB = yield pool.connect() @@ -49,7 +49,7 @@ describe('idle timeout', () => { it( 'can remove idle clients and recreate them', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool({ idleTimeoutMillis: 1 }) const results = [] for (var i = 0; i < 20; i++) { @@ -67,7 +67,7 @@ describe('idle timeout', () => { it( 'does not time out clients which are used', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool({ idleTimeoutMillis: 1 }) const results = [] for (var i = 0; i < 20; i++) { diff --git a/packages/pg-pool/test/index.js b/packages/pg-pool/test/index.js index bc8f2a241..57a68e01e 100644 --- a/packages/pg-pool/test/index.js +++ b/packages/pg-pool/test/index.js @@ -7,13 +7,13 @@ const it = require('mocha').it const Pool = require('../') -describe('pool', function() { - describe('with callbacks', function() { - it('works totally unconfigured', function(done) { +describe('pool', function () { + describe('with callbacks', function () { + it('works totally unconfigured', function (done) { const pool = new Pool() - pool.connect(function(err, client, release) { + pool.connect(function (err, client, release) { if (err) return done(err) - client.query('SELECT NOW()', function(err, res) { + client.query('SELECT NOW()', function (err, res) { release() if (err) return done(err) expect(res.rows).to.have.length(1) @@ -22,9 +22,9 @@ describe('pool', function() { }) }) - it('passes props to clients', function(done) { + it('passes props to clients', function (done) { const pool = new Pool({ binary: true }) - pool.connect(function(err, client, release) { + pool.connect(function (err, client, release) { release() if (err) return done(err) expect(client.binary).to.eql(true) @@ -32,42 +32,42 @@ describe('pool', function() { }) }) - it('can run a query with a callback without parameters', function(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) { + pool.query('SELECT 1 as num', function (err, res) { expect(res.rows[0]).to.eql({ num: 1 }) - pool.end(function() { + pool.end(function () { done(err) }) }) }) - it('can run a query with a callback', function(done) { + 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) { + pool.query('SELECT $1::text as name', ['brianc'], function (err, res) { expect(res.rows[0]).to.eql({ name: 'brianc' }) - pool.end(function() { + pool.end(function () { done(err) }) }) }) - it('passes connection errors to callback', function(done) { + 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) { + 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) { + pool.end(function (err) { done(err) }) }) }) - it('does not pass client to error callback', function(done) { + it('does not pass client to error callback', function (done) { const pool = new Pool({ port: 58242 }) - pool.connect(function(err, client, release) { + pool.connect(function (err, client, release) { expect(err).to.be.an(Error) expect(client).to.be(undefined) expect(release).to.be.a(Function) @@ -75,30 +75,30 @@ describe('pool', function() { }) }) - it('removes client if it errors in background', function(done) { + it('removes client if it errors in background', function (done) { const pool = new Pool() - pool.connect(function(err, client, release) { + pool.connect(function (err, client, release) { release() if (err) return done(err) client.testString = 'foo' - setTimeout(function() { + setTimeout(function () { client.emit('error', new Error('on purpose')) }, 10) }) - pool.on('error', function(err) { + 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() { + err.client.connection.stream.on('end', function () { pool.end(done) }) }) }) - it('should not change given options', function(done) { + it('should not change given options', function (done) { const options = { max: 10 } const pool = new Pool(options) - pool.connect(function(err, client, release) { + pool.connect(function (err, client, release) { release() if (err) return done(err) expect(options).to.eql({ max: 10 }) @@ -106,9 +106,9 @@ describe('pool', function() { }) }) - it('does not create promises when connecting', function(done) { + it('does not create promises when connecting', function (done) { const pool = new Pool() - const returnValue = pool.connect(function(err, client, release) { + const returnValue = pool.connect(function (err, client, release) { release() if (err) return done(err) pool.end(done) @@ -116,23 +116,23 @@ describe('pool', function() { expect(returnValue).to.be(undefined) }) - it('does not create promises when querying', function(done) { + 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() { + 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) { + 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) { + it('never calls callback syncronously', function (done) { const pool = new Pool() pool.connect((err, client) => { if (err) throw err @@ -153,11 +153,11 @@ describe('pool', function() { }) }) - describe('with promises', function() { - it('connects, queries, and disconnects', function() { + 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) { + 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() @@ -174,41 +174,41 @@ describe('pool', function() { }) }) - it('properly pools clients', function() { + 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) { + 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) { + 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() { + 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) { + return Promise.all(promises).then(function (queries) { expect(queries).to.have.length(30) return pool.end() }) }) - it('recovers from query errors', function() { + it('recovers from query errors', function () { const pool = new Pool() const errors = [] const promises = _.times(30, () => { - return pool.query('SELECT asldkfjasldkf').catch(function(e) { + return pool.query('SELECT asldkfjasldkf').catch(function (e) { errors.push(e) }) }) @@ -216,7 +216,7 @@ describe('pool', function() { 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) { + return pool.query('SELECT $1::text as name', ['hi']).then(function (res) { expect(res.rows).to.eql([{ name: 'hi' }]) return pool.end() }) diff --git a/packages/pg-pool/test/logging.js b/packages/pg-pool/test/logging.js index 9374e2751..839603b78 100644 --- a/packages/pg-pool/test/logging.js +++ b/packages/pg-pool/test/logging.js @@ -5,14 +5,14 @@ const it = require('mocha').it const Pool = require('../') -describe('logging', function() { - it('logs to supplied log function if given', function() { +describe('logging', function () { + it('logs to supplied log function if given', function () { const messages = [] - const log = function(msg) { + const log = function (msg) { messages.push(msg) } const pool = new Pool({ log: log }) - return pool.query('SELECT NOW()').then(function() { + return pool.query('SELECT NOW()').then(function () { expect(messages.length).to.be.greaterThan(0) return pool.end() }) diff --git a/packages/pg-pool/test/max-uses.js b/packages/pg-pool/test/max-uses.js index 840ac6419..c94ddec6b 100644 --- a/packages/pg-pool/test/max-uses.js +++ b/packages/pg-pool/test/max-uses.js @@ -10,7 +10,7 @@ const Pool = require('../') describe('maxUses', () => { it( 'can create a single client and use it once', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool({ maxUses: 2 }) expect(pool.waitingCount).to.equal(0) const client = yield pool.connect() @@ -23,7 +23,7 @@ describe('maxUses', () => { it( 'getting a connection a second time returns the same connection and releasing it also closes it', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool({ maxUses: 2 }) expect(pool.waitingCount).to.equal(0) const client = yield pool.connect() @@ -39,7 +39,7 @@ describe('maxUses', () => { it( 'getting a connection a third time returns a new connection', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool({ maxUses: 2 }) expect(pool.waitingCount).to.equal(0) const client = yield pool.connect() @@ -56,7 +56,7 @@ describe('maxUses', () => { it( 'getting a connection from a pending request gets a fresh client when the released candidate is expended', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool({ max: 1, maxUses: 2 }) expect(pool.waitingCount).to.equal(0) const client1 = yield pool.connect() @@ -83,9 +83,9 @@ describe('maxUses', () => { it( 'logs when removing an expended client', - co.wrap(function*() { + co.wrap(function* () { const messages = [] - const log = function(msg) { + const log = function (msg) { messages.push(msg) } const pool = new Pool({ maxUses: 1, log }) diff --git a/packages/pg-pool/test/sizing.js b/packages/pg-pool/test/sizing.js index 32154548a..e7863ba07 100644 --- a/packages/pg-pool/test/sizing.js +++ b/packages/pg-pool/test/sizing.js @@ -10,7 +10,7 @@ const Pool = require('../') describe('pool size of 1', () => { it( 'can create a single client and use it once', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool({ max: 1 }) expect(pool.waitingCount).to.equal(0) const client = yield pool.connect() @@ -23,7 +23,7 @@ describe('pool size of 1', () => { it( 'can create a single client and use it multiple times', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool({ max: 1 }) expect(pool.waitingCount).to.equal(0) const client = yield pool.connect() @@ -39,7 +39,7 @@ describe('pool size of 1', () => { it( 'can only send 1 query at a time', - co.wrap(function*() { + co.wrap(function* () { const pool = new Pool({ max: 1 }) // the query text column name changed in PostgreSQL 9.2 diff --git a/packages/pg-protocol/src/inbound-parser.test.ts b/packages/pg-protocol/src/inbound-parser.test.ts index 8ea9f7570..8a8785a5c 100644 --- a/packages/pg-protocol/src/inbound-parser.test.ts +++ b/packages/pg-protocol/src/inbound-parser.test.ts @@ -14,7 +14,7 @@ var parseCompleteBuffer = buffers.parseComplete() var bindCompleteBuffer = buffers.bindComplete() var portalSuspendedBuffer = buffers.portalSuspended() -var addRow = function(bufferList: BufferList, name: string, offset: number) { +var addRow = function (bufferList: BufferList, name: string, offset: number) { return bufferList .addCString(name) // field name .addInt32(offset++) // table id @@ -144,7 +144,7 @@ var expectedTwoRowMessage = { ], } -var testForMessage = function(buffer: Buffer, expectedMessage: any) { +var testForMessage = function (buffer: Buffer, expectedMessage: any) { it('recieves and parses ' + expectedMessage.name, async () => { const messages = await parseBuffers([buffer]) const [lastMessage] = messages @@ -204,7 +204,7 @@ const parseBuffers = async (buffers: Buffer[]): Promise => { return msgs } -describe('PgPacketStream', function() { +describe('PgPacketStream', function () { testForMessage(authOkBuffer, expectedAuthenticationOkayMessage) testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage) testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage) @@ -226,21 +226,21 @@ describe('PgPacketStream', function() { name: 'noData', }) - describe('rowDescription messages', function() { + describe('rowDescription messages', function () { testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage) testForMessage(oneRowDescBuff, expectedOneRowMessage) testForMessage(twoRowBuf, expectedTwoRowMessage) }) - describe('parsing rows', function() { - describe('parsing empty row', function() { + describe('parsing rows', function () { + describe('parsing empty row', function () { testForMessage(emptyRowFieldBuf, { name: 'dataRow', fieldCount: 0, }) }) - describe('parsing data row with fields', function() { + describe('parsing data row with fields', function () { testForMessage(oneFieldBuf, { name: 'dataRow', fieldCount: 1, @@ -249,7 +249,7 @@ describe('PgPacketStream', function() { }) }) - describe('notice message', function() { + describe('notice message', function () { // this uses the same logic as error message var buff = buffers.notice([{ type: 'C', value: 'code' }]) testForMessage(buff, { @@ -262,7 +262,7 @@ describe('PgPacketStream', function() { name: 'error', }) - describe('with all the fields', function() { + describe('with all the fields', function () { var buffer = buffers.error([ { type: 'S', @@ -351,13 +351,13 @@ describe('PgPacketStream', function() { name: 'closeComplete', }) - describe('parses portal suspended message', function() { + describe('parses portal suspended message', function () { testForMessage(portalSuspendedBuffer, { name: 'portalSuspended', }) }) - describe('parses replication start message', function() { + describe('parses replication start message', function () { testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { name: 'replicationStart', length: 4, @@ -408,10 +408,10 @@ describe('PgPacketStream', function() { // since the data message on a stream can randomly divide the incomming // tcp packets anywhere, we need to make sure we can parse every single // split on a tcp message - describe('split buffer, single message parsing', function() { + describe('split buffer, single message parsing', function () { var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']) - it('parses when full buffer comes in', async function() { + it('parses when full buffer comes in', async function () { const messages = await parseBuffers([fullBuffer]) const message = messages[0] as any assert.equal(message.fields.length, 5) @@ -422,7 +422,7 @@ describe('PgPacketStream', function() { assert.equal(message.fields[4], '!') }) - var testMessageRecievedAfterSpiltAt = async function(split: number) { + var testMessageRecievedAfterSpiltAt = async function (split: number) { var firstBuffer = Buffer.alloc(fullBuffer.length - split) var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) fullBuffer.copy(firstBuffer, 0, 0) @@ -437,29 +437,29 @@ describe('PgPacketStream', function() { assert.equal(message.fields[4], '!') } - it('parses when split in the middle', function() { + it('parses when split in the middle', function () { testMessageRecievedAfterSpiltAt(6) }) - it('parses when split at end', function() { + it('parses when split at end', function () { testMessageRecievedAfterSpiltAt(2) }) - it('parses when split at beginning', function() { + it('parses when split at beginning', function () { testMessageRecievedAfterSpiltAt(fullBuffer.length - 2) testMessageRecievedAfterSpiltAt(fullBuffer.length - 1) testMessageRecievedAfterSpiltAt(fullBuffer.length - 5) }) }) - describe('split buffer, multiple message parsing', function() { + describe('split buffer, multiple message parsing', function () { var dataRowBuffer = buffers.dataRow(['!']) var readyForQueryBuffer = buffers.readyForQuery() var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length) dataRowBuffer.copy(fullBuffer, 0, 0) readyForQueryBuffer.copy(fullBuffer, dataRowBuffer.length, 0) - var verifyMessages = function(messages: any[]) { + var verifyMessages = function (messages: any[]) { assert.strictEqual(messages.length, 2) assert.deepEqual(messages[0], { name: 'dataRow', @@ -475,12 +475,12 @@ describe('PgPacketStream', function() { }) } // sanity check - it('recieves both messages when packet is not split', async function() { + it('recieves both messages when packet is not split', async function () { const messages = await parseBuffers([fullBuffer]) verifyMessages(messages) }) - var splitAndVerifyTwoMessages = async function(split: number) { + var splitAndVerifyTwoMessages = async function (split: number) { var firstBuffer = Buffer.alloc(fullBuffer.length - split) var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) fullBuffer.copy(firstBuffer, 0, 0) @@ -489,11 +489,11 @@ describe('PgPacketStream', function() { verifyMessages(messages) } - describe('recieves both messages when packet is split', function() { - it('in the middle', function() { + describe('recieves both messages when packet is split', function () { + it('in the middle', function () { return splitAndVerifyTwoMessages(11) }) - it('at the front', function() { + it('at the front', function () { return Promise.all([ splitAndVerifyTwoMessages(fullBuffer.length - 1), splitAndVerifyTwoMessages(fullBuffer.length - 4), @@ -501,7 +501,7 @@ describe('PgPacketStream', function() { ]) }) - it('at the end', function() { + it('at the end', function () { return Promise.all([splitAndVerifyTwoMessages(8), splitAndVerifyTwoMessages(1)]) }) }) diff --git a/packages/pg-protocol/src/outbound-serializer.test.ts b/packages/pg-protocol/src/outbound-serializer.test.ts index 23de94c92..4d2457e19 100644 --- a/packages/pg-protocol/src/outbound-serializer.test.ts +++ b/packages/pg-protocol/src/outbound-serializer.test.ts @@ -3,7 +3,7 @@ import { serialize } from './serializer' import BufferList from './testing/buffer-list' describe('serializer', () => { - it('builds startup message', function() { + it('builds startup message', function () { const actual = serialize.startup({ user: 'brian', database: 'bang', @@ -24,66 +24,51 @@ describe('serializer', () => { ) }) - it('builds password message', function() { + it('builds password message', function () { const actual = serialize.password('!') assert.deepEqual(actual, new BufferList().addCString('!').join(true, 'p')) }) - it('builds request ssl message', function() { + it('builds request ssl message', function () { const actual = serialize.requestSsl() const expected = new BufferList().addInt32(80877103).join(true) assert.deepEqual(actual, expected) }) - it('builds SASLInitialResponseMessage message', function() { + it('builds SASLInitialResponseMessage message', function () { const actual = serialize.sendSASLInitialResponseMessage('mech', 'data') - assert.deepEqual( - actual, - new BufferList() - .addCString('mech') - .addInt32(4) - .addString('data') - .join(true, 'p') - ) + assert.deepEqual(actual, new BufferList().addCString('mech').addInt32(4).addString('data').join(true, 'p')) }) - it('builds SCRAMClientFinalMessage message', function() { + it('builds SCRAMClientFinalMessage message', function () { const actual = serialize.sendSCRAMClientFinalMessage('data') assert.deepEqual(actual, new BufferList().addString('data').join(true, 'p')) }) - it('builds query message', function() { + it('builds query message', function () { var txt = 'select * from boom' const actual = serialize.query(txt) assert.deepEqual(actual, new BufferList().addCString(txt).join(true, 'Q')) }) describe('parse message', () => { - it('builds parse message', function() { + it('builds parse message', function () { const actual = serialize.parse({ text: '!' }) - var expected = new BufferList() - .addCString('') - .addCString('!') - .addInt16(0) - .join(true, 'P') + var expected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P') assert.deepEqual(actual, expected) }) - it('builds parse message with named query', function() { + it('builds parse message with named query', function () { const actual = serialize.parse({ name: 'boom', text: 'select * from boom', types: [], }) - var expected = new BufferList() - .addCString('boom') - .addCString('select * from boom') - .addInt16(0) - .join(true, 'P') + var expected = new BufferList().addCString('boom').addCString('select * from boom').addInt16(0).join(true, 'P') assert.deepEqual(actual, expected) }) - it('with multiple parameters', function() { + it('with multiple parameters', function () { const actual = serialize.parse({ name: 'force', text: 'select * from bang where name = $1', @@ -102,8 +87,8 @@ describe('serializer', () => { }) }) - describe('bind messages', function() { - it('with no values', function() { + describe('bind messages', function () { + it('with no values', function () { const actual = serialize.bind() var expectedBuffer = new BufferList() @@ -116,7 +101,7 @@ describe('serializer', () => { assert.deepEqual(actual, expectedBuffer) }) - it('with named statement, portal, and values', function() { + it('with named statement, portal, and values', function () { const actual = serialize.bind({ portal: 'bang', statement: 'woo', @@ -140,7 +125,7 @@ describe('serializer', () => { }) }) - it('with named statement, portal, and buffer value', function() { + it('with named statement, portal, and buffer value', function () { const actual = serialize.bind({ portal: 'bang', statement: 'woo', @@ -167,88 +152,70 @@ describe('serializer', () => { assert.deepEqual(actual, expectedBuffer) }) - describe('builds execute message', function() { - it('for unamed portal with no row limit', function() { + describe('builds execute message', function () { + it('for unamed portal with no row limit', function () { const actual = serialize.execute() - var expectedBuffer = new BufferList() - .addCString('') - .addInt32(0) - .join(true, 'E') + var expectedBuffer = new BufferList().addCString('').addInt32(0).join(true, 'E') assert.deepEqual(actual, expectedBuffer) }) - it('for named portal with row limit', function() { + it('for named portal with row limit', function () { const actual = serialize.execute({ portal: 'my favorite portal', rows: 100, }) - var expectedBuffer = new BufferList() - .addCString('my favorite portal') - .addInt32(100) - .join(true, 'E') + var expectedBuffer = new BufferList().addCString('my favorite portal').addInt32(100).join(true, 'E') assert.deepEqual(actual, expectedBuffer) }) }) - it('builds flush command', function() { + it('builds flush command', function () { const actual = serialize.flush() var expected = new BufferList().join(true, 'H') assert.deepEqual(actual, expected) }) - it('builds sync command', function() { + it('builds sync command', function () { const actual = serialize.sync() var expected = new BufferList().join(true, 'S') assert.deepEqual(actual, expected) }) - it('builds end command', function() { + it('builds end command', function () { const actual = serialize.end() var expected = Buffer.from([0x58, 0, 0, 0, 4]) assert.deepEqual(actual, expected) }) - describe('builds describe command', function() { - it('describe statement', function() { + describe('builds describe command', function () { + it('describe statement', function () { const actual = serialize.describe({ type: 'S', name: 'bang' }) - var expected = new BufferList() - .addChar('S') - .addCString('bang') - .join(true, 'D') + var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D') assert.deepEqual(actual, expected) }) - it('describe unnamed portal', function() { + it('describe unnamed portal', function () { const actual = serialize.describe({ type: 'P' }) - var expected = new BufferList() - .addChar('P') - .addCString('') - .join(true, 'D') + var expected = new BufferList().addChar('P').addCString('').join(true, 'D') assert.deepEqual(actual, expected) }) }) - describe('builds close command', function() { - it('describe statement', function() { + describe('builds close command', function () { + it('describe statement', function () { const actual = serialize.close({ type: 'S', name: 'bang' }) - var expected = new BufferList() - .addChar('S') - .addCString('bang') - .join(true, 'C') + var expected = new BufferList().addChar('S').addCString('bang').join(true, 'C') assert.deepEqual(actual, expected) }) - it('describe unnamed portal', function() { + it('describe unnamed portal', function () { const actual = serialize.close({ type: 'P' }) - var expected = new BufferList() - .addChar('P') - .addCString('') - .join(true, 'C') + var expected = new BufferList().addChar('P').addCString('').join(true, 'C') assert.deepEqual(actual, expected) }) }) - describe('copy messages', function() { + describe('copy messages', function () { it('builds copyFromChunk', () => { const actual = serialize.copyData(Buffer.from([1, 2, 3])) const expected = new BufferList().add(Buffer.from([1, 2, 3])).join(true, 'd') @@ -270,12 +237,7 @@ describe('serializer', () => { it('builds cancel message', () => { const actual = serialize.cancel(3, 4) - const expected = new BufferList() - .addInt16(1234) - .addInt16(5678) - .addInt32(3) - .addInt32(4) - .join(true) + const expected = new BufferList().addInt16(1234).addInt16(5678).addInt32(3).addInt32(4).join(true) assert.deepEqual(actual, expected) }) }) diff --git a/packages/pg-protocol/src/serializer.ts b/packages/pg-protocol/src/serializer.ts index 37208096e..00e43fffe 100644 --- a/packages/pg-protocol/src/serializer.ts +++ b/packages/pg-protocol/src/serializer.ts @@ -32,10 +32,7 @@ const startup = (opts: Record): Buffer => { var length = bodyBuffer.length + 4 - return new Writer() - .addInt32(length) - .add(bodyBuffer) - .flush() + return new Writer().addInt32(length).add(bodyBuffer).flush() } const requestSsl = (): Buffer => { @@ -49,17 +46,14 @@ const password = (password: string): Buffer => { return writer.addCString(password).flush(code.startup) } -const sendSASLInitialResponseMessage = function(mechanism: string, initialResponse: string): Buffer { +const sendSASLInitialResponseMessage = function (mechanism: string, initialResponse: string): Buffer { // 0x70 = 'p' - writer - .addCString(mechanism) - .addInt32(Buffer.byteLength(initialResponse)) - .addString(initialResponse) + writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse) return writer.flush(code.startup) } -const sendSCRAMClientFinalMessage = function(additionalData: string): Buffer { +const sendSCRAMClientFinalMessage = function (additionalData: string): Buffer { return writer.addString(additionalData).flush(code.startup) } diff --git a/packages/pg-protocol/src/testing/buffer-list.ts b/packages/pg-protocol/src/testing/buffer-list.ts index 35a5420a7..15ac785cc 100644 --- a/packages/pg-protocol/src/testing/buffer-list.ts +++ b/packages/pg-protocol/src/testing/buffer-list.ts @@ -11,7 +11,7 @@ export default class BufferList { } public getByteLength(initial?: number) { - return this.buffers.reduce(function(previous, current) { + return this.buffers.reduce(function (previous, current) { return previous + current.length }, initial || 0) } @@ -58,7 +58,7 @@ export default class BufferList { } var result = Buffer.alloc(length) var index = 0 - this.buffers.forEach(function(buffer) { + this.buffers.forEach(function (buffer) { buffer.copy(result, index, 0) index += buffer.length }) diff --git a/packages/pg-protocol/src/testing/test-buffers.ts b/packages/pg-protocol/src/testing/test-buffers.ts index a378a5d2d..19ba16cce 100644 --- a/packages/pg-protocol/src/testing/test-buffers.ts +++ b/packages/pg-protocol/src/testing/test-buffers.ts @@ -2,70 +2,54 @@ import BufferList from './buffer-list' const buffers = { - readyForQuery: function() { + readyForQuery: function () { return new BufferList().add(Buffer.from('I')).join(true, 'Z') }, - authenticationOk: function() { + authenticationOk: function () { return new BufferList().addInt32(0).join(true, 'R') }, - authenticationCleartextPassword: function() { + authenticationCleartextPassword: function () { return new BufferList().addInt32(3).join(true, 'R') }, - authenticationMD5Password: function() { + authenticationMD5Password: function () { return new BufferList() .addInt32(5) .add(Buffer.from([1, 2, 3, 4])) .join(true, 'R') }, - authenticationSASL: function() { - return new BufferList() - .addInt32(10) - .addCString('SCRAM-SHA-256') - .addCString('') - .join(true, 'R') + authenticationSASL: function () { + return new BufferList().addInt32(10).addCString('SCRAM-SHA-256').addCString('').join(true, 'R') }, - authenticationSASLContinue: function() { - return new BufferList() - .addInt32(11) - .addString('data') - .join(true, 'R') + authenticationSASLContinue: function () { + return new BufferList().addInt32(11).addString('data').join(true, 'R') }, - authenticationSASLFinal: function() { - return new BufferList() - .addInt32(12) - .addString('data') - .join(true, 'R') + authenticationSASLFinal: function () { + return new BufferList().addInt32(12).addString('data').join(true, 'R') }, - parameterStatus: function(name: string, value: string) { - return new BufferList() - .addCString(name) - .addCString(value) - .join(true, 'S') + parameterStatus: function (name: string, value: string) { + return new BufferList().addCString(name).addCString(value).join(true, 'S') }, - backendKeyData: function(processID: number, secretKey: number) { - return new BufferList() - .addInt32(processID) - .addInt32(secretKey) - .join(true, 'K') + backendKeyData: function (processID: number, secretKey: number) { + return new BufferList().addInt32(processID).addInt32(secretKey).join(true, 'K') }, - commandComplete: function(string: string) { + commandComplete: function (string: string) { return new BufferList().addCString(string).join(true, 'C') }, - rowDescription: function(fields: any[]) { + rowDescription: function (fields: any[]) { fields = fields || [] var buf = new BufferList() buf.addInt16(fields.length) - fields.forEach(function(field) { + fields.forEach(function (field) { buf .addCString(field.name) .addInt32(field.tableID || 0) @@ -78,11 +62,11 @@ const buffers = { return buf.join(true, 'T') }, - dataRow: function(columns: any[]) { + dataRow: function (columns: any[]) { columns = columns || [] var buf = new BufferList() buf.addInt16(columns.length) - columns.forEach(function(col) { + columns.forEach(function (col) { if (col == null) { buf.addInt32(-1) } else { @@ -94,53 +78,49 @@ const buffers = { return buf.join(true, 'D') }, - error: function(fields: any) { + error: function (fields: any) { return buffers.errorOrNotice(fields).join(true, 'E') }, - notice: function(fields: any) { + notice: function (fields: any) { return buffers.errorOrNotice(fields).join(true, 'N') }, - errorOrNotice: function(fields: any) { + errorOrNotice: function (fields: any) { fields = fields || [] var buf = new BufferList() - fields.forEach(function(field: any) { + fields.forEach(function (field: any) { buf.addChar(field.type) buf.addCString(field.value) }) return buf.add(Buffer.from([0])) // terminator }, - parseComplete: function() { + parseComplete: function () { return new BufferList().join(true, '1') }, - bindComplete: function() { + bindComplete: function () { return new BufferList().join(true, '2') }, - notification: function(id: number, channel: string, payload: string) { - return new BufferList() - .addInt32(id) - .addCString(channel) - .addCString(payload) - .join(true, 'A') + notification: function (id: number, channel: string, payload: string) { + return new BufferList().addInt32(id).addCString(channel).addCString(payload).join(true, 'A') }, - emptyQuery: function() { + emptyQuery: function () { return new BufferList().join(true, 'I') }, - portalSuspended: function() { + portalSuspended: function () { return new BufferList().join(true, 's') }, - closeComplete: function() { + closeComplete: function () { return new BufferList().join(true, '3') }, - copyIn: function(cols: number) { + copyIn: function (cols: number) { const list = new BufferList() // text mode .addByte(0) @@ -152,7 +132,7 @@ const buffers = { return list.join(true, 'G') }, - copyOut: function(cols: number) { + copyOut: function (cols: number) { const list = new BufferList() // text mode .addByte(0) @@ -164,11 +144,11 @@ const buffers = { return list.join(true, 'H') }, - copyData: function(bytes: Buffer) { + copyData: function (bytes: Buffer) { return new BufferList().add(bytes).join(true, 'd') }, - copyDone: function() { + copyDone: function () { return new BufferList().join(true, 'c') }, } diff --git a/packages/pg-query-stream/test/close.js b/packages/pg-query-stream/test/close.js index 0f97277f7..4a95464a7 100644 --- a/packages/pg-query-stream/test/close.js +++ b/packages/pg-query-stream/test/close.js @@ -7,37 +7,37 @@ var helper = require('./helper') if (process.version.startsWith('v8.')) { console.error('warning! node less than 10lts stream closing semantics may not behave properly') } else { - helper('close', function(client) { - it('emits close', function(done) { + helper('close', function (client) { + it('emits close', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], { batchSize: 2, highWaterMark: 2 }) var query = client.query(stream) - query.pipe(concat(function() {})) + query.pipe(concat(function () {})) query.on('close', done) }) }) - helper('early close', function(client) { - it('can be closed early', function(done) { + helper('early close', function (client) { + it('can be closed early', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [20000], { batchSize: 2, highWaterMark: 2, }) var query = client.query(stream) var readCount = 0 - query.on('readable', function() { + query.on('readable', function () { readCount++ query.read() }) - query.once('readable', function() { + query.once('readable', function () { query.destroy() }) - query.on('close', function() { + query.on('close', function () { assert(readCount < 10, 'should not have read more than 10 rows') done() }) }) - it('can destroy stream while reading', function(done) { + it('can destroy stream while reading', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') client.query(stream) stream.on('data', () => done(new Error('stream should not have returned rows'))) @@ -47,7 +47,7 @@ if (process.version.startsWith('v8.')) { }, 100) }) - it('emits an error when calling destroy with an error', function(done) { + it('emits an error when calling destroy with an error', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') client.query(stream) stream.on('data', () => done(new Error('stream should not have returned rows'))) @@ -62,7 +62,7 @@ if (process.version.startsWith('v8.')) { }, 100) }) - it('can destroy stream while reading an error', function(done) { + it('can destroy stream while reading an error', function (done) { var stream = new QueryStream('SELECT * from pg_sleep(1), basdfasdf;') client.query(stream) stream.on('data', () => done(new Error('stream should not have returned rows'))) @@ -73,7 +73,7 @@ if (process.version.startsWith('v8.')) { }) }) - it('does not crash when destroying the stream immediately after calling read', function(done) { + it('does not crash when destroying the stream immediately after calling read', function (done) { var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') client.query(stream) stream.on('data', () => done(new Error('stream should not have returned rows'))) @@ -81,7 +81,7 @@ if (process.version.startsWith('v8.')) { stream.on('close', done) }) - it('does not crash when destroying the stream before its submitted', function(done) { + it('does not crash when destroying the stream before its submitted', function (done) { var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') stream.on('data', () => done(new Error('stream should not have returned rows'))) stream.destroy() diff --git a/packages/pg-query-stream/test/concat.js b/packages/pg-query-stream/test/concat.js index 417a4486e..6ce17a28e 100644 --- a/packages/pg-query-stream/test/concat.js +++ b/packages/pg-query-stream/test/concat.js @@ -5,19 +5,19 @@ var helper = require('./helper') var QueryStream = require('../') -helper('concat', function(client) { - it('concats correctly', function(done) { +helper('concat', function (client) { + it('concats correctly', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) query .pipe( - through(function(row) { + through(function (row) { this.push(row.num) }) ) .pipe( - concat(function(result) { - var total = result.reduce(function(prev, cur) { + concat(function (result) { + var total = result.reduce(function (prev, cur) { return prev + cur }) assert.equal(total, 20100) diff --git a/packages/pg-query-stream/test/empty-query.js b/packages/pg-query-stream/test/empty-query.js index c4bfa95b2..25f7d6956 100644 --- a/packages/pg-query-stream/test/empty-query.js +++ b/packages/pg-query-stream/test/empty-query.js @@ -2,21 +2,21 @@ const assert = require('assert') const helper = require('./helper') const QueryStream = require('../') -helper('empty-query', function(client) { - it('handles empty query', function(done) { +helper('empty-query', function (client) { + it('handles empty query', function (done) { const stream = new QueryStream('-- this is a comment', []) const query = client.query(stream) query - .on('end', function() { + .on('end', function () { // nothing should happen for empty query done() }) - .on('data', function() { + .on('data', function () { // noop to kick off reading }) }) - it('continues to function after stream', function(done) { + it('continues to function after stream', function (done) { client.query('SELECT NOW()', done) }) }) diff --git a/packages/pg-query-stream/test/error.js b/packages/pg-query-stream/test/error.js index 29b5edc40..0b732923d 100644 --- a/packages/pg-query-stream/test/error.js +++ b/packages/pg-query-stream/test/error.js @@ -3,22 +3,22 @@ var helper = require('./helper') var QueryStream = require('../') -helper('error', function(client) { - it('receives error on stream', function(done) { +helper('error', function (client) { + it('receives error on stream', function (done) { var stream = new QueryStream('SELECT * FROM asdf num', []) var query = client.query(stream) query - .on('error', function(err) { + .on('error', function (err) { assert(err) assert.equal(err.code, '42P01') done() }) - .on('data', function() { + .on('data', function () { // noop to kick of reading }) }) - it('continues to function after stream', function(done) { + it('continues to function after stream', function (done) { client.query('SELECT NOW()', done) }) }) diff --git a/packages/pg-query-stream/test/fast-reader.js b/packages/pg-query-stream/test/fast-reader.js index 77e023a0e..4c6f31f95 100644 --- a/packages/pg-query-stream/test/fast-reader.js +++ b/packages/pg-query-stream/test/fast-reader.js @@ -2,12 +2,12 @@ var assert = require('assert') var helper = require('./helper') var QueryStream = require('../') -helper('fast reader', function(client) { - it('works', function(done) { +helper('fast reader', function (client) { + it('works', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) var result = [] - stream.on('readable', function() { + stream.on('readable', function () { var res = stream.read() while (res) { if (result.length !== 201) { @@ -23,8 +23,8 @@ helper('fast reader', function(client) { res = stream.read() } }) - stream.on('end', function() { - var total = result.reduce(function(prev, cur) { + stream.on('end', function () { + var total = result.reduce(function (prev, cur) { return prev + cur }) assert.equal(total, 20100) diff --git a/packages/pg-query-stream/test/helper.js b/packages/pg-query-stream/test/helper.js index f4e427203..ad21d6ea2 100644 --- a/packages/pg-query-stream/test/helper.js +++ b/packages/pg-query-stream/test/helper.js @@ -1,15 +1,15 @@ var pg = require('pg') -module.exports = function(name, cb) { - describe(name, function() { +module.exports = function (name, cb) { + describe(name, function () { var client = new pg.Client() - before(function(done) { + before(function (done) { client.connect(done) }) cb(client) - after(function(done) { + after(function (done) { client.end() client.on('end', done) }) diff --git a/packages/pg-query-stream/test/instant.js b/packages/pg-query-stream/test/instant.js index ae1b3c0a1..0939753bb 100644 --- a/packages/pg-query-stream/test/instant.js +++ b/packages/pg-query-stream/test/instant.js @@ -3,12 +3,12 @@ var concat = require('concat-stream') var QueryStream = require('../') -require('./helper')('instant', function(client) { - it('instant', function(done) { +require('./helper')('instant', function (client) { + it('instant', function (done) { var query = new QueryStream('SELECT pg_sleep(1)', []) var stream = client.query(query) stream.pipe( - concat(function(res) { + concat(function (res) { assert.equal(res.length, 1) done() }) diff --git a/packages/pg-query-stream/test/issue-3.js b/packages/pg-query-stream/test/issue-3.js index ba03c5e60..7b467a3b3 100644 --- a/packages/pg-query-stream/test/issue-3.js +++ b/packages/pg-query-stream/test/issue-3.js @@ -1,7 +1,7 @@ var pg = require('pg') var QueryStream = require('../') -describe('end semantics race condition', function() { - before(function(done) { +describe('end semantics race condition', function () { + before(function (done) { var client = new pg.Client() client.connect() client.on('drain', client.end.bind(client)) @@ -9,7 +9,7 @@ describe('end semantics race condition', function() { client.query('create table IF NOT EXISTS p(id serial primary key)') client.query('create table IF NOT EXISTS c(id int primary key references p)') }) - it('works', function(done) { + it('works', function (done) { var client1 = new pg.Client() client1.connect() var client2 = new pg.Client() @@ -18,11 +18,11 @@ describe('end semantics race condition', function() { var qr = new QueryStream('INSERT INTO p DEFAULT VALUES RETURNING id') client1.query(qr) var id = null - qr.on('data', function(row) { + qr.on('data', function (row) { id = row.id }) - qr.on('end', function() { - client2.query('INSERT INTO c(id) VALUES ($1)', [id], function(err, rows) { + qr.on('end', function () { + client2.query('INSERT INTO c(id) VALUES ($1)', [id], function (err, rows) { client1.end() client2.end() done(err) diff --git a/packages/pg-query-stream/test/passing-options.js b/packages/pg-query-stream/test/passing-options.js index 011e2e0d3..858767de2 100644 --- a/packages/pg-query-stream/test/passing-options.js +++ b/packages/pg-query-stream/test/passing-options.js @@ -2,8 +2,8 @@ var assert = require('assert') var helper = require('./helper') var QueryStream = require('../') -helper('passing options', function(client) { - it('passes row mode array', function(done) { +helper('passing options', function (client) { + it('passes row mode array', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { rowMode: 'array' }) var query = client.query(stream) var result = [] @@ -17,7 +17,7 @@ helper('passing options', function(client) { }) }) - it('passes custom types', function(done) { + it('passes custom types', function (done) { const types = { getTypeParser: () => (string) => string, } diff --git a/packages/pg-query-stream/test/pauses.js b/packages/pg-query-stream/test/pauses.js index f5d538552..3da9a0b07 100644 --- a/packages/pg-query-stream/test/pauses.js +++ b/packages/pg-query-stream/test/pauses.js @@ -4,8 +4,8 @@ var JSONStream = require('JSONStream') var QueryStream = require('../') -require('./helper')('pauses', function(client) { - it('pauses', function(done) { +require('./helper')('pauses', function (client) { + it('pauses', function (done) { this.timeout(5000) var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], { batchSize: 2, highWaterMark: 2 }) var query = client.query(stream) @@ -14,7 +14,7 @@ require('./helper')('pauses', function(client) { .pipe(JSONStream.stringify()) .pipe(pauser) .pipe( - concat(function(json) { + concat(function (json) { JSON.parse(json) done() }) diff --git a/packages/pg-query-stream/test/slow-reader.js b/packages/pg-query-stream/test/slow-reader.js index b96c93ab5..3978f3004 100644 --- a/packages/pg-query-stream/test/slow-reader.js +++ b/packages/pg-query-stream/test/slow-reader.js @@ -6,24 +6,24 @@ var Transform = require('stream').Transform var mapper = new Transform({ objectMode: true }) -mapper._transform = function(obj, enc, cb) { +mapper._transform = function (obj, enc, cb) { this.push(obj) setTimeout(cb, 5) } -helper('slow reader', function(client) { - it('works', function(done) { +helper('slow reader', function (client) { + it('works', function (done) { this.timeout(50000) var stream = new QueryStream('SELECT * FROM generate_series(0, 201) num', [], { highWaterMark: 100, batchSize: 50, }) - stream.on('end', function() { + stream.on('end', function () { // console.log('stream end') }) client.query(stream) stream.pipe(mapper).pipe( - concat(function(res) { + concat(function (res) { done() }) ) diff --git a/packages/pg-query-stream/test/stream-tester-timestamp.js b/packages/pg-query-stream/test/stream-tester-timestamp.js index 4f10b2894..ce989cc3f 100644 --- a/packages/pg-query-stream/test/stream-tester-timestamp.js +++ b/packages/pg-query-stream/test/stream-tester-timestamp.js @@ -2,20 +2,17 @@ var QueryStream = require('../') var spec = require('stream-spec') var assert = require('assert') -require('./helper')('stream tester timestamp', function(client) { - it('should not warn about max listeners', function(done) { +require('./helper')('stream tester timestamp', function (client) { + it('should not warn about max listeners', function (done) { var sql = "SELECT * FROM generate_series('1983-12-30 00:00'::timestamp, '2013-12-30 00:00', '1 years')" var stream = new QueryStream(sql, []) var ended = false var query = client.query(stream) - query.on('end', function() { + query.on('end', function () { ended = true }) - spec(query) - .readable() - .pausable({ strict: true }) - .validateOnExit() - var checkListeners = function() { + spec(query).readable().pausable({ strict: true }).validateOnExit() + var checkListeners = function () { assert(stream.listeners('end').length < 10) if (!ended) { setImmediate(checkListeners) diff --git a/packages/pg-query-stream/test/stream-tester.js b/packages/pg-query-stream/test/stream-tester.js index a0d53779b..f5ab2e372 100644 --- a/packages/pg-query-stream/test/stream-tester.js +++ b/packages/pg-query-stream/test/stream-tester.js @@ -2,14 +2,11 @@ var spec = require('stream-spec') var QueryStream = require('../') -require('./helper')('stream tester', function(client) { - it('passes stream spec', function(done) { +require('./helper')('stream tester', function (client) { + it('passes stream spec', function (done) { var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) var query = client.query(stream) - spec(query) - .readable() - .pausable({ strict: true }) - .validateOnExit() + spec(query).readable().pausable({ strict: true }).validateOnExit() stream.on('end', done) }) }) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 81f82fdac..04124f8a0 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -22,7 +22,7 @@ if (process.env.PG_FAST_CONNECTION) { Connection = require('./connection-fast') } -var Client = function(config) { +var Client = function (config) { EventEmitter.call(this) this.connectionParameters = new ConnectionParameters(config) @@ -71,7 +71,7 @@ var Client = function(config) { util.inherits(Client, EventEmitter) -Client.prototype._errorAllQueries = function(err) { +Client.prototype._errorAllQueries = function (err) { const enqueueError = (query) => { process.nextTick(() => { query.handleError(err, this.connection) @@ -87,7 +87,7 @@ Client.prototype._errorAllQueries = function(err) { this.queryQueue.length = 0 } -Client.prototype._connect = function(callback) { +Client.prototype._connect = function (callback) { var self = this var con = this.connection if (this._connecting || this._connected) { @@ -114,7 +114,7 @@ Client.prototype._connect = function(callback) { } // once connection is established send startup message - con.on('connect', function() { + con.on('connect', function () { if (self.ssl) { con.requestSsl() } else { @@ -122,12 +122,12 @@ Client.prototype._connect = function(callback) { } }) - con.on('sslconnect', function() { + con.on('sslconnect', function () { con.startup(self.getStartupConf()) }) function checkPgPass(cb) { - return function(msg) { + return function (msg) { if (typeof self.password === 'function') { self._Promise .resolve() @@ -150,7 +150,7 @@ Client.prototype._connect = function(callback) { } else if (self.password !== null) { cb(msg) } else { - pgPass(self.connectionParameters, function(pass) { + pgPass(self.connectionParameters, function (pass) { if (undefined !== pass) { self.connectionParameters.password = self.password = pass } @@ -163,7 +163,7 @@ Client.prototype._connect = function(callback) { // password request handling con.on( 'authenticationCleartextPassword', - checkPgPass(function() { + checkPgPass(function () { con.password(self.password) }) ) @@ -171,7 +171,7 @@ Client.prototype._connect = function(callback) { // password request handling con.on( 'authenticationMD5Password', - checkPgPass(function(msg) { + checkPgPass(function (msg) { con.password(utils.postgresMd5PasswordHash(self.user, self.password, msg.salt)) }) ) @@ -180,7 +180,7 @@ Client.prototype._connect = function(callback) { var saslSession con.on( 'authenticationSASL', - checkPgPass(function(msg) { + checkPgPass(function (msg) { saslSession = sasl.startSession(msg.mechanisms) con.sendSASLInitialResponseMessage(saslSession.mechanism, saslSession.response) @@ -188,20 +188,20 @@ Client.prototype._connect = function(callback) { ) // password request handling (SASL) - con.on('authenticationSASLContinue', function(msg) { + con.on('authenticationSASLContinue', function (msg) { sasl.continueSession(saslSession, self.password, msg.data) con.sendSCRAMClientFinalMessage(saslSession.response) }) // password request handling (SASL) - con.on('authenticationSASLFinal', function(msg) { + con.on('authenticationSASLFinal', function (msg) { sasl.finalizeSession(saslSession, msg.data) saslSession = null }) - con.once('backendKeyData', function(msg) { + con.once('backendKeyData', function (msg) { self.processID = msg.processID self.secretKey = msg.secretKey }) @@ -241,7 +241,7 @@ Client.prototype._connect = function(callback) { // hook up query handling events to connection // after the connection initially becomes ready for queries - con.once('readyForQuery', function() { + con.once('readyForQuery', function () { self._connecting = false self._connected = true self._attachListeners(con) @@ -261,7 +261,7 @@ Client.prototype._connect = function(callback) { self.emit('connect') }) - con.on('readyForQuery', function() { + con.on('readyForQuery', function () { var activeQuery = self.activeQuery self.activeQuery = null self.readyForQuery = true @@ -298,12 +298,12 @@ Client.prototype._connect = function(callback) { }) }) - con.on('notice', function(msg) { + con.on('notice', function (msg) { self.emit('notice', msg) }) } -Client.prototype.connect = function(callback) { +Client.prototype.connect = function (callback) { if (callback) { this._connect(callback) return @@ -320,32 +320,32 @@ Client.prototype.connect = function(callback) { }) } -Client.prototype._attachListeners = function(con) { +Client.prototype._attachListeners = function (con) { const self = this // delegate rowDescription to active query - con.on('rowDescription', function(msg) { + con.on('rowDescription', function (msg) { self.activeQuery.handleRowDescription(msg) }) // delegate dataRow to active query - con.on('dataRow', function(msg) { + con.on('dataRow', function (msg) { self.activeQuery.handleDataRow(msg) }) // delegate portalSuspended to active query // eslint-disable-next-line no-unused-vars - con.on('portalSuspended', function(msg) { + con.on('portalSuspended', function (msg) { self.activeQuery.handlePortalSuspended(con) }) // delegate emptyQuery to active query // eslint-disable-next-line no-unused-vars - con.on('emptyQuery', function(msg) { + con.on('emptyQuery', function (msg) { self.activeQuery.handleEmptyQuery(con) }) // delegate commandComplete to active query - con.on('commandComplete', function(msg) { + con.on('commandComplete', function (msg) { self.activeQuery.handleCommandComplete(msg, con) }) @@ -353,27 +353,27 @@ Client.prototype._attachListeners = function(con) { // we track that its already been executed so we don't parse // it again on the same client // eslint-disable-next-line no-unused-vars - con.on('parseComplete', function(msg) { + con.on('parseComplete', function (msg) { if (self.activeQuery.name) { con.parsedStatements[self.activeQuery.name] = self.activeQuery.text } }) // eslint-disable-next-line no-unused-vars - con.on('copyInResponse', function(msg) { + con.on('copyInResponse', function (msg) { self.activeQuery.handleCopyInResponse(self.connection) }) - con.on('copyData', function(msg) { + con.on('copyData', function (msg) { self.activeQuery.handleCopyData(msg, self.connection) }) - con.on('notification', function(msg) { + con.on('notification', function (msg) { self.emit('notification', msg) }) } -Client.prototype.getStartupConf = function() { +Client.prototype.getStartupConf = function () { var params = this.connectionParameters var data = { @@ -398,7 +398,7 @@ Client.prototype.getStartupConf = function() { return data } -Client.prototype.cancel = function(client, query) { +Client.prototype.cancel = function (client, query) { if (client.activeQuery === query) { var con = this.connection @@ -409,7 +409,7 @@ Client.prototype.cancel = function(client, query) { } // once connection is established send cancel message - con.on('connect', function() { + con.on('connect', function () { con.cancel(client.processID, client.secretKey) }) } else if (client.queryQueue.indexOf(query) !== -1) { @@ -417,21 +417,21 @@ Client.prototype.cancel = function(client, query) { } } -Client.prototype.setTypeParser = function(oid, format, parseFn) { +Client.prototype.setTypeParser = function (oid, format, parseFn) { return this._types.setTypeParser(oid, format, parseFn) } -Client.prototype.getTypeParser = function(oid, format) { +Client.prototype.getTypeParser = function (oid, format) { return this._types.getTypeParser(oid, format) } // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c -Client.prototype.escapeIdentifier = function(str) { +Client.prototype.escapeIdentifier = function (str) { return '"' + str.replace(/"/g, '""') + '"' } // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c -Client.prototype.escapeLiteral = function(str) { +Client.prototype.escapeLiteral = function (str) { var hasBackslash = false var escaped = "'" @@ -456,7 +456,7 @@ Client.prototype.escapeLiteral = function(str) { return escaped } -Client.prototype._pulseQueryQueue = function() { +Client.prototype._pulseQueryQueue = function () { if (this.readyForQuery === true) { this.activeQuery = this.queryQueue.shift() if (this.activeQuery) { @@ -478,7 +478,7 @@ Client.prototype._pulseQueryQueue = function() { } } -Client.prototype.query = function(config, values, callback) { +Client.prototype.query = function (config, values, callback) { // can take in strings, config object or query object var query var result @@ -562,7 +562,7 @@ Client.prototype.query = function(config, values, callback) { return result } -Client.prototype.end = function(cb) { +Client.prototype.end = function (cb) { this._ending = true // if we have never connected, then end is a noop, callback immediately diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index 58764abf3..acc5c0e8c 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -17,7 +17,7 @@ const { parse, serialize } = require('../../pg-protocol/dist') // TODO(bmc) support binary mode here // var BINARY_MODE = 1 console.log('***using faster connection***') -var Connection = function(config) { +var Connection = function (config) { EventEmitter.call(this) config = config || {} this.stream = config.stream || new net.Socket() @@ -30,7 +30,7 @@ var Connection = function(config) { this._ending = false this._emitMessage = false var self = this - this.on('newListener', function(eventName) { + this.on('newListener', function (eventName) { if (eventName === 'message') { self._emitMessage = true } @@ -39,7 +39,7 @@ var Connection = function(config) { util.inherits(Connection, EventEmitter) -Connection.prototype.connect = function(port, host) { +Connection.prototype.connect = function (port, host) { var self = this if (this.stream.readyState === 'closed') { @@ -48,14 +48,14 @@ Connection.prototype.connect = function(port, host) { this.emit('connect') } - this.stream.on('connect', function() { + this.stream.on('connect', function () { if (self._keepAlive) { self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis) } self.emit('connect') }) - const reportStreamError = function(error) { + const reportStreamError = function (error) { // errors about disconnections should be ignored during disconnect if (self._ending && (error.code === 'ECONNRESET' || error.code === 'EPIPE')) { return @@ -64,7 +64,7 @@ Connection.prototype.connect = function(port, host) { } this.stream.on('error', reportStreamError) - this.stream.on('close', function() { + this.stream.on('close', function () { self.emit('end') }) @@ -72,7 +72,7 @@ Connection.prototype.connect = function(port, host) { return this.attachListeners(this.stream) } - this.stream.once('data', function(buffer) { + this.stream.once('data', function (buffer) { var responseCode = buffer.toString('utf8') switch (responseCode) { case 'S': // Server supports SSL connections, continue with a secure connection @@ -103,7 +103,7 @@ Connection.prototype.connect = function(port, host) { }) } -Connection.prototype.attachListeners = function(stream) { +Connection.prototype.attachListeners = function (stream) { stream.on('end', () => { this.emit('end') }) @@ -116,67 +116,67 @@ Connection.prototype.attachListeners = function(stream) { }) } -Connection.prototype.requestSsl = function() { +Connection.prototype.requestSsl = function () { this.stream.write(serialize.requestSsl()) } -Connection.prototype.startup = function(config) { +Connection.prototype.startup = function (config) { this.stream.write(serialize.startup(config)) } -Connection.prototype.cancel = function(processID, secretKey) { +Connection.prototype.cancel = function (processID, secretKey) { this._send(serialize.cancel(processID, secretKey)) } -Connection.prototype.password = function(password) { +Connection.prototype.password = function (password) { this._send(serialize.password(password)) } -Connection.prototype.sendSASLInitialResponseMessage = function(mechanism, initialResponse) { +Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) { this._send(serialize.sendSASLInitialResponseMessage(mechanism, initialResponse)) } -Connection.prototype.sendSCRAMClientFinalMessage = function(additionalData) { +Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) { this._send(serialize.sendSCRAMClientFinalMessage(additionalData)) } -Connection.prototype._send = function(buffer) { +Connection.prototype._send = function (buffer) { if (!this.stream.writable) { return false } return this.stream.write(buffer) } -Connection.prototype.query = function(text) { +Connection.prototype.query = function (text) { this._send(serialize.query(text)) } // send parse message -Connection.prototype.parse = function(query) { +Connection.prototype.parse = function (query) { this._send(serialize.parse(query)) } // send bind message // "more" === true to buffer the message until flush() is called -Connection.prototype.bind = function(config) { +Connection.prototype.bind = function (config) { this._send(serialize.bind(config)) } // send execute message // "more" === true to buffer the message until flush() is called -Connection.prototype.execute = function(config) { +Connection.prototype.execute = function (config) { this._send(serialize.execute(config)) } const flushBuffer = serialize.flush() -Connection.prototype.flush = function() { +Connection.prototype.flush = function () { if (this.stream.writable) { this.stream.write(flushBuffer) } } const syncBuffer = serialize.sync() -Connection.prototype.sync = function() { +Connection.prototype.sync = function () { this._ending = true this._send(syncBuffer) this._send(flushBuffer) @@ -184,7 +184,7 @@ Connection.prototype.sync = function() { const endBuffer = serialize.end() -Connection.prototype.end = function() { +Connection.prototype.end = function () { // 0x58 = 'X' this._ending = true if (!this.stream.writable) { @@ -196,23 +196,23 @@ Connection.prototype.end = function() { }) } -Connection.prototype.close = function(msg) { +Connection.prototype.close = function (msg) { this._send(serialize.close(msg)) } -Connection.prototype.describe = function(msg) { +Connection.prototype.describe = function (msg) { this._send(serialize.describe(msg)) } -Connection.prototype.sendCopyFromChunk = function(chunk) { +Connection.prototype.sendCopyFromChunk = function (chunk) { this._send(serialize.copyData(chunk)) } -Connection.prototype.endCopyFrom = function() { +Connection.prototype.endCopyFrom = function () { this._send(serialize.copyDone()) } -Connection.prototype.sendCopyFail = function(msg) { +Connection.prototype.sendCopyFail = function (msg) { this._send(serialize.copyFail(msg)) } diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index 4b0799574..b34e0df5f 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -13,7 +13,7 @@ var defaults = require('./defaults') var parse = require('pg-connection-string').parse // parses a connection string -var val = function(key, config, envVar) { +var val = function (key, config, envVar) { if (envVar === undefined) { envVar = process.env['PG' + key.toUpperCase()] } else if (envVar === false) { @@ -25,7 +25,7 @@ var val = function(key, config, envVar) { return config[key] || envVar || defaults[key] } -var useSsl = function() { +var useSsl = function () { switch (process.env.PGSSLMODE) { case 'disable': return false @@ -38,7 +38,7 @@ var useSsl = function() { return defaults.ssl } -var ConnectionParameters = function(config) { +var ConnectionParameters = function (config) { // if a string is passed, it is a raw connection string so we parse it into a config config = typeof config === 'string' ? parse(config) : config || {} @@ -98,18 +98,18 @@ var ConnectionParameters = function(config) { } // Convert arg to a string, surround in single quotes, and escape single quotes and backslashes -var quoteParamValue = function(value) { +var quoteParamValue = function (value) { return "'" + ('' + value).replace(/\\/g, '\\\\').replace(/'/g, "\\'") + "'" } -var add = function(params, config, paramName) { +var add = function (params, config, paramName) { var value = config[paramName] if (value !== undefined && value !== null) { params.push(paramName + '=' + quoteParamValue(value)) } } -ConnectionParameters.prototype.getLibpqConnectionString = function(cb) { +ConnectionParameters.prototype.getLibpqConnectionString = function (cb) { var params = [] add(params, this, 'user') add(params, this, 'password') @@ -140,7 +140,7 @@ ConnectionParameters.prototype.getLibpqConnectionString = function(cb) { if (this.client_encoding) { params.push('client_encoding=' + quoteParamValue(this.client_encoding)) } - dns.lookup(this.host, function(err, address) { + dns.lookup(this.host, function (err, address) { if (err) return cb(err, null) params.push('hostaddr=' + quoteParamValue(address)) return cb(null, params.join(' ')) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index e5a9aad9a..243872c93 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -16,7 +16,7 @@ var Reader = require('packet-reader') var TEXT_MODE = 0 var BINARY_MODE = 1 -var Connection = function(config) { +var Connection = function (config) { EventEmitter.call(this) config = config || {} this.stream = config.stream || new net.Socket() @@ -38,7 +38,7 @@ var Connection = function(config) { lengthPadding: -4, }) var self = this - this.on('newListener', function(eventName) { + this.on('newListener', function (eventName) { if (eventName === 'message') { self._emitMessage = true } @@ -47,7 +47,7 @@ var Connection = function(config) { util.inherits(Connection, EventEmitter) -Connection.prototype.connect = function(port, host) { +Connection.prototype.connect = function (port, host) { var self = this if (this.stream.readyState === 'closed') { @@ -56,14 +56,14 @@ Connection.prototype.connect = function(port, host) { this.emit('connect') } - this.stream.on('connect', function() { + this.stream.on('connect', function () { if (self._keepAlive) { self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis) } self.emit('connect') }) - const reportStreamError = function(error) { + const reportStreamError = function (error) { // errors about disconnections should be ignored during disconnect if (self._ending && (error.code === 'ECONNRESET' || error.code === 'EPIPE')) { return @@ -72,7 +72,7 @@ Connection.prototype.connect = function(port, host) { } this.stream.on('error', reportStreamError) - this.stream.on('close', function() { + this.stream.on('close', function () { self.emit('end') }) @@ -80,7 +80,7 @@ Connection.prototype.connect = function(port, host) { return this.attachListeners(this.stream) } - this.stream.once('data', function(buffer) { + this.stream.once('data', function (buffer) { var responseCode = buffer.toString('utf8') switch (responseCode) { case 'S': // Server supports SSL connections, continue with a secure connection @@ -110,9 +110,9 @@ Connection.prototype.connect = function(port, host) { }) } -Connection.prototype.attachListeners = function(stream) { +Connection.prototype.attachListeners = function (stream) { var self = this - stream.on('data', function(buff) { + stream.on('data', function (buff) { self._reader.addChunk(buff) var packet = self._reader.read() while (packet) { @@ -125,30 +125,24 @@ Connection.prototype.attachListeners = function(stream) { packet = self._reader.read() } }) - stream.on('end', function() { + stream.on('end', function () { self.emit('end') }) } -Connection.prototype.requestSsl = function() { - var bodyBuffer = this.writer - .addInt16(0x04d2) - .addInt16(0x162f) - .flush() +Connection.prototype.requestSsl = function () { + var bodyBuffer = this.writer.addInt16(0x04d2).addInt16(0x162f).flush() var length = bodyBuffer.length + 4 - var buffer = new Writer() - .addInt32(length) - .add(bodyBuffer) - .join() + var buffer = new Writer().addInt32(length).add(bodyBuffer).join() this.stream.write(buffer) } -Connection.prototype.startup = function(config) { +Connection.prototype.startup = function (config) { var writer = this.writer.addInt16(3).addInt16(0) - Object.keys(config).forEach(function(key) { + Object.keys(config).forEach(function (key) { var val = config[key] writer.addCString(key).addCString(val) }) @@ -160,53 +154,39 @@ Connection.prototype.startup = function(config) { var length = bodyBuffer.length + 4 - var buffer = new Writer() - .addInt32(length) - .add(bodyBuffer) - .join() + var buffer = new Writer().addInt32(length).add(bodyBuffer).join() this.stream.write(buffer) } -Connection.prototype.cancel = function(processID, secretKey) { - var bodyBuffer = this.writer - .addInt16(1234) - .addInt16(5678) - .addInt32(processID) - .addInt32(secretKey) - .flush() +Connection.prototype.cancel = function (processID, secretKey) { + var bodyBuffer = this.writer.addInt16(1234).addInt16(5678).addInt32(processID).addInt32(secretKey).flush() var length = bodyBuffer.length + 4 - var buffer = new Writer() - .addInt32(length) - .add(bodyBuffer) - .join() + var buffer = new Writer().addInt32(length).add(bodyBuffer).join() this.stream.write(buffer) } -Connection.prototype.password = function(password) { +Connection.prototype.password = function (password) { // 0x70 = 'p' this._send(0x70, this.writer.addCString(password)) } -Connection.prototype.sendSASLInitialResponseMessage = function(mechanism, initialResponse) { +Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) { // 0x70 = 'p' - this.writer - .addCString(mechanism) - .addInt32(Buffer.byteLength(initialResponse)) - .addString(initialResponse) + this.writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse) this._send(0x70) } -Connection.prototype.sendSCRAMClientFinalMessage = function(additionalData) { +Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) { // 0x70 = 'p' this.writer.addString(additionalData) this._send(0x70) } -Connection.prototype._send = function(code, more) { +Connection.prototype._send = function (code, more) { if (!this.stream.writable) { return false } @@ -217,14 +197,14 @@ Connection.prototype._send = function(code, more) { } } -Connection.prototype.query = function(text) { +Connection.prototype.query = function (text) { // 0x51 = Q this.stream.write(this.writer.addCString(text).flush(0x51)) } // send parse message // "more" === true to buffer the message until flush() is called -Connection.prototype.parse = function(query, more) { +Connection.prototype.parse = function (query, more) { // expect something like this: // { name: 'queryName', // text: 'select * from blah', @@ -256,7 +236,7 @@ Connection.prototype.parse = function(query, more) { // send bind message // "more" === true to buffer the message until flush() is called -Connection.prototype.bind = function(config, more) { +Connection.prototype.bind = function (config, more) { // normalize config config = config || {} config.portal = config.portal || '' @@ -303,7 +283,7 @@ Connection.prototype.bind = function(config, more) { // send execute message // "more" === true to buffer the message until flush() is called -Connection.prototype.execute = function(config, more) { +Connection.prototype.execute = function (config, more) { config = config || {} config.portal = config.portal || '' config.rows = config.rows || '' @@ -315,13 +295,13 @@ Connection.prototype.execute = function(config, more) { var emptyBuffer = Buffer.alloc(0) -Connection.prototype.flush = function() { +Connection.prototype.flush = function () { // 0x48 = 'H' this.writer.add(emptyBuffer) this._send(0x48) } -Connection.prototype.sync = function() { +Connection.prototype.sync = function () { // clear out any pending data in the writer this.writer.flush(0) @@ -332,7 +312,7 @@ Connection.prototype.sync = function() { const END_BUFFER = Buffer.from([0x58, 0x00, 0x00, 0x00, 0x04]) -Connection.prototype.end = function() { +Connection.prototype.end = function () { // 0x58 = 'X' this.writer.add(emptyBuffer) this._ending = true @@ -345,36 +325,36 @@ Connection.prototype.end = function() { }) } -Connection.prototype.close = function(msg, more) { +Connection.prototype.close = function (msg, more) { this.writer.addCString(msg.type + (msg.name || '')) this._send(0x43, more) } -Connection.prototype.describe = function(msg, more) { +Connection.prototype.describe = function (msg, more) { this.writer.addCString(msg.type + (msg.name || '')) this._send(0x44, more) } -Connection.prototype.sendCopyFromChunk = function(chunk) { +Connection.prototype.sendCopyFromChunk = function (chunk) { this.stream.write(this.writer.add(chunk).flush(0x64)) } -Connection.prototype.endCopyFrom = function() { +Connection.prototype.endCopyFrom = function () { this.stream.write(this.writer.add(emptyBuffer).flush(0x63)) } -Connection.prototype.sendCopyFail = function(msg) { +Connection.prototype.sendCopyFail = function (msg) { // this.stream.write(this.writer.add(emptyBuffer).flush(0x66)); this.writer.addCString(msg) this._send(0x66) } -var Message = function(name, length) { +var Message = function (name, length) { this.name = name this.length = length } -Connection.prototype.parseMessage = function(buffer) { +Connection.prototype.parseMessage = function (buffer) { this.offset = 0 var length = buffer.length + 4 switch (this._reader.header) { @@ -443,7 +423,7 @@ Connection.prototype.parseMessage = function(buffer) { } } -Connection.prototype.parseR = function(buffer, length) { +Connection.prototype.parseR = function (buffer, length) { var code = this.parseInt32(buffer) var msg = new Message('authenticationOk', length) @@ -494,27 +474,27 @@ Connection.prototype.parseR = function(buffer, length) { throw new Error('Unknown authenticationOk message type' + util.inspect(msg)) } -Connection.prototype.parseS = function(buffer, length) { +Connection.prototype.parseS = function (buffer, length) { var msg = new Message('parameterStatus', length) msg.parameterName = this.parseCString(buffer) msg.parameterValue = this.parseCString(buffer) return msg } -Connection.prototype.parseK = function(buffer, length) { +Connection.prototype.parseK = function (buffer, length) { var msg = new Message('backendKeyData', length) msg.processID = this.parseInt32(buffer) msg.secretKey = this.parseInt32(buffer) return msg } -Connection.prototype.parseC = function(buffer, length) { +Connection.prototype.parseC = function (buffer, length) { var msg = new Message('commandComplete', length) msg.text = this.parseCString(buffer) return msg } -Connection.prototype.parseZ = function(buffer, length) { +Connection.prototype.parseZ = function (buffer, length) { var msg = new Message('readyForQuery', length) msg.name = 'readyForQuery' msg.status = this.readString(buffer, 1) @@ -522,7 +502,7 @@ Connection.prototype.parseZ = function(buffer, length) { } var ROW_DESCRIPTION = 'rowDescription' -Connection.prototype.parseT = function(buffer, length) { +Connection.prototype.parseT = function (buffer, length) { var msg = new Message(ROW_DESCRIPTION, length) msg.fieldCount = this.parseInt16(buffer) var fields = [] @@ -533,7 +513,7 @@ Connection.prototype.parseT = function(buffer, length) { return msg } -var Field = function() { +var Field = function () { this.name = null this.tableID = null this.columnID = null @@ -545,7 +525,7 @@ var Field = function() { var FORMAT_TEXT = 'text' var FORMAT_BINARY = 'binary' -Connection.prototype.parseField = function(buffer) { +Connection.prototype.parseField = function (buffer) { var field = new Field() field.name = this.parseCString(buffer) field.tableID = this.parseInt32(buffer) @@ -564,7 +544,7 @@ Connection.prototype.parseField = function(buffer) { } var DATA_ROW = 'dataRow' -var DataRowMessage = function(length, fieldCount) { +var DataRowMessage = function (length, fieldCount) { this.name = DATA_ROW this.length = length this.fieldCount = fieldCount @@ -572,7 +552,7 @@ var DataRowMessage = function(length, fieldCount) { } // extremely hot-path code -Connection.prototype.parseD = function(buffer, length) { +Connection.prototype.parseD = function (buffer, length) { var fieldCount = this.parseInt16(buffer) var msg = new DataRowMessage(length, fieldCount) for (var i = 0; i < fieldCount; i++) { @@ -582,7 +562,7 @@ Connection.prototype.parseD = function(buffer, length) { } // extremely hot-path code -Connection.prototype._readValue = function(buffer) { +Connection.prototype._readValue = function (buffer) { var length = this.parseInt32(buffer) if (length === -1) return null if (this._mode === TEXT_MODE) { @@ -592,7 +572,7 @@ Connection.prototype._readValue = function(buffer) { } // parses error -Connection.prototype.parseE = function(buffer, length, isNotice) { +Connection.prototype.parseE = function (buffer, length, isNotice) { var fields = {} var fieldType = this.readString(buffer, 1) while (fieldType !== '\0') { @@ -627,13 +607,13 @@ Connection.prototype.parseE = function(buffer, length, isNotice) { } // same thing, different name -Connection.prototype.parseN = function(buffer, length) { +Connection.prototype.parseN = function (buffer, length) { var msg = this.parseE(buffer, length, true) msg.name = 'notice' return msg } -Connection.prototype.parseA = function(buffer, length) { +Connection.prototype.parseA = function (buffer, length) { var msg = new Message('notification', length) msg.processId = this.parseInt32(buffer) msg.channel = this.parseCString(buffer) @@ -641,17 +621,17 @@ Connection.prototype.parseA = function(buffer, length) { return msg } -Connection.prototype.parseG = function(buffer, length) { +Connection.prototype.parseG = function (buffer, length) { var msg = new Message('copyInResponse', length) return this.parseGH(buffer, msg) } -Connection.prototype.parseH = function(buffer, length) { +Connection.prototype.parseH = function (buffer, length) { var msg = new Message('copyOutResponse', length) return this.parseGH(buffer, msg) } -Connection.prototype.parseGH = function(buffer, msg) { +Connection.prototype.parseGH = function (buffer, msg) { var isBinary = buffer[this.offset] !== 0 this.offset++ msg.binary = isBinary @@ -663,33 +643,33 @@ Connection.prototype.parseGH = function(buffer, msg) { return msg } -Connection.prototype.parsed = function(buffer, length) { +Connection.prototype.parsed = function (buffer, length) { var msg = new Message('copyData', length) msg.chunk = this.readBytes(buffer, msg.length - 4) return msg } -Connection.prototype.parseInt32 = function(buffer) { +Connection.prototype.parseInt32 = function (buffer) { var value = buffer.readInt32BE(this.offset) this.offset += 4 return value } -Connection.prototype.parseInt16 = function(buffer) { +Connection.prototype.parseInt16 = function (buffer) { var value = buffer.readInt16BE(this.offset) this.offset += 2 return value } -Connection.prototype.readString = function(buffer, length) { +Connection.prototype.readString = function (buffer, length) { return buffer.toString(this.encoding, this.offset, (this.offset += length)) } -Connection.prototype.readBytes = function(buffer, length) { +Connection.prototype.readBytes = function (buffer, length) { return buffer.slice(this.offset, (this.offset += length)) } -Connection.prototype.parseCString = function(buffer) { +Connection.prototype.parseCString = function (buffer) { var start = this.offset var end = buffer.indexOf(0, start) this.offset = end + 1 diff --git a/packages/pg/lib/defaults.js b/packages/pg/lib/defaults.js index 47e510337..394216680 100644 --- a/packages/pg/lib/defaults.js +++ b/packages/pg/lib/defaults.js @@ -79,7 +79,7 @@ var parseBigInteger = pgTypes.getTypeParser(20, 'text') var parseBigIntegerArray = pgTypes.getTypeParser(1016, 'text') // parse int8 so you can get your count values as actual numbers -module.exports.__defineSetter__('parseInt8', function(val) { +module.exports.__defineSetter__('parseInt8', function (val) { pgTypes.setTypeParser(20, 'text', val ? pgTypes.getTypeParser(23, 'text') : parseBigInteger) pgTypes.setTypeParser(1016, 'text', val ? pgTypes.getTypeParser(1007, 'text') : parseBigIntegerArray) }) diff --git a/packages/pg/lib/index.js b/packages/pg/lib/index.js index de171620e..975175cd4 100644 --- a/packages/pg/lib/index.js +++ b/packages/pg/lib/index.js @@ -20,7 +20,7 @@ const poolFactory = (Client) => { } } -var PG = function(clientConstructor) { +var PG = function (clientConstructor) { this.defaults = defaults this.Client = clientConstructor this.Query = this.Client.Query diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index 883aca005..f45546151 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -22,7 +22,7 @@ assert(semver.gte(Native.version, pkg.minNativeVersion), msg) var NativeQuery = require('./query') -var Client = (module.exports = function(config) { +var Client = (module.exports = function (config) { EventEmitter.call(this) config = config || {} @@ -64,7 +64,7 @@ Client.Query = NativeQuery util.inherits(Client, EventEmitter) -Client.prototype._errorAllQueries = function(err) { +Client.prototype._errorAllQueries = function (err) { const enqueueError = (query) => { process.nextTick(() => { query.native = this.native @@ -84,7 +84,7 @@ Client.prototype._errorAllQueries = function(err) { // connect to the backend // pass an optional callback to be called once connected // or with an error if there was a connection error -Client.prototype._connect = function(cb) { +Client.prototype._connect = function (cb) { var self = this if (this._connecting) { @@ -94,9 +94,9 @@ Client.prototype._connect = function(cb) { this._connecting = true - this.connectionParameters.getLibpqConnectionString(function(err, conString) { + this.connectionParameters.getLibpqConnectionString(function (err, conString) { if (err) return cb(err) - self.native.connect(conString, function(err) { + self.native.connect(conString, function (err) { if (err) { self.native.end() return cb(err) @@ -106,13 +106,13 @@ Client.prototype._connect = function(cb) { self._connected = true // handle connection errors from the native layer - self.native.on('error', function(err) { + self.native.on('error', function (err) { self._queryable = false self._errorAllQueries(err) self.emit('error', err) }) - self.native.on('notification', function(msg) { + self.native.on('notification', function (msg) { self.emit('notification', { channel: msg.relname, payload: msg.extra, @@ -128,7 +128,7 @@ Client.prototype._connect = function(cb) { }) } -Client.prototype.connect = function(callback) { +Client.prototype.connect = function (callback) { if (callback) { this._connect(callback) return @@ -155,7 +155,7 @@ Client.prototype.connect = function(callback) { // optional string name to name & cache the query plan // optional string rowMode = 'array' for an array of results // } -Client.prototype.query = function(config, values, callback) { +Client.prototype.query = function (config, values, callback) { var query var result var readTimeout @@ -237,7 +237,7 @@ Client.prototype.query = function(config, values, callback) { } // disconnect from the backend server -Client.prototype.end = function(cb) { +Client.prototype.end = function (cb) { var self = this this._ending = true @@ -247,11 +247,11 @@ Client.prototype.end = function(cb) { } var result if (!cb) { - result = new this._Promise(function(resolve, reject) { + result = new this._Promise(function (resolve, reject) { cb = (err) => (err ? reject(err) : resolve()) }) } - this.native.end(function() { + this.native.end(function () { self._errorAllQueries(new Error('Connection terminated')) process.nextTick(() => { @@ -262,11 +262,11 @@ Client.prototype.end = function(cb) { return result } -Client.prototype._hasActiveQuery = function() { +Client.prototype._hasActiveQuery = function () { return this._activeQuery && this._activeQuery.state !== 'error' && this._activeQuery.state !== 'end' } -Client.prototype._pulseQueryQueue = function(initialConnection) { +Client.prototype._pulseQueryQueue = function (initialConnection) { if (!this._connected) { return } @@ -283,24 +283,24 @@ Client.prototype._pulseQueryQueue = function(initialConnection) { this._activeQuery = query query.submit(this) var self = this - query.once('_done', function() { + query.once('_done', function () { self._pulseQueryQueue() }) } // attempt to cancel an in-progress query -Client.prototype.cancel = function(query) { +Client.prototype.cancel = function (query) { if (this._activeQuery === query) { - this.native.cancel(function() {}) + this.native.cancel(function () {}) } else if (this._queryQueue.indexOf(query) !== -1) { this._queryQueue.splice(this._queryQueue.indexOf(query), 1) } } -Client.prototype.setTypeParser = function(oid, format, parseFn) { +Client.prototype.setTypeParser = function (oid, format, parseFn) { return this._types.setTypeParser(oid, format, parseFn) } -Client.prototype.getTypeParser = function(oid, format) { +Client.prototype.getTypeParser = function (oid, format) { return this._types.getTypeParser(oid, format) } diff --git a/packages/pg/lib/native/query.js b/packages/pg/lib/native/query.js index c2e3ed446..de443489a 100644 --- a/packages/pg/lib/native/query.js +++ b/packages/pg/lib/native/query.js @@ -11,7 +11,7 @@ var EventEmitter = require('events').EventEmitter var util = require('util') var utils = require('../utils') -var NativeQuery = (module.exports = function(config, values, callback) { +var NativeQuery = (module.exports = function (config, values, callback) { EventEmitter.call(this) config = utils.normalizeQueryConfig(config, values, callback) this.text = config.text @@ -29,7 +29,7 @@ var NativeQuery = (module.exports = function(config, values, callback) { this._emitRowEvents = false this.on( 'newListener', - function(event) { + function (event) { if (event === 'row') this._emitRowEvents = true }.bind(this) ) @@ -53,7 +53,7 @@ var errorFieldMap = { sourceFunction: 'routine', } -NativeQuery.prototype.handleError = function(err) { +NativeQuery.prototype.handleError = function (err) { // copy pq error fields into the error object var fields = this.native.pq.resultErrorFields() if (fields) { @@ -70,18 +70,18 @@ NativeQuery.prototype.handleError = function(err) { this.state = 'error' } -NativeQuery.prototype.then = function(onSuccess, onFailure) { +NativeQuery.prototype.then = function (onSuccess, onFailure) { return this._getPromise().then(onSuccess, onFailure) } -NativeQuery.prototype.catch = function(callback) { +NativeQuery.prototype.catch = function (callback) { return this._getPromise().catch(callback) } -NativeQuery.prototype._getPromise = function() { +NativeQuery.prototype._getPromise = function () { if (this._promise) return this._promise this._promise = new Promise( - function(resolve, reject) { + function (resolve, reject) { this._once('end', resolve) this._once('error', reject) }.bind(this) @@ -89,15 +89,15 @@ NativeQuery.prototype._getPromise = function() { return this._promise } -NativeQuery.prototype.submit = function(client) { +NativeQuery.prototype.submit = function (client) { this.state = 'running' var self = this this.native = client.native client.native.arrayMode = this._arrayMode - var after = function(err, rows, results) { + var after = function (err, rows, results) { client.native.arrayMode = false - setImmediate(function() { + setImmediate(function () { self.emit('_done') }) @@ -115,7 +115,7 @@ NativeQuery.prototype.submit = function(client) { }) }) } else { - rows.forEach(function(row) { + rows.forEach(function (row) { self.emit('row', row, results) }) } @@ -154,7 +154,7 @@ NativeQuery.prototype.submit = function(client) { return client.native.execute(this.name, values, after) } // plan the named query the first time, then execute it - return client.native.prepare(this.name, this.text, values.length, function(err) { + return client.native.prepare(this.name, this.text, values.length, function (err) { if (err) return after(err) client.namedQueries[self.name] = self.text return self.native.execute(self.name, values, after) diff --git a/packages/pg/lib/result.js b/packages/pg/lib/result.js index 615a06d0c..233455b06 100644 --- a/packages/pg/lib/result.js +++ b/packages/pg/lib/result.js @@ -12,7 +12,7 @@ var types = require('pg-types') // result object returned from query // in the 'end' event and also // passed as second argument to provided callback -var Result = function(rowMode, types) { +var Result = function (rowMode, types) { this.command = null this.rowCount = null this.oid = null @@ -30,7 +30,7 @@ var Result = function(rowMode, types) { var matchRegexp = /^([A-Za-z]+)(?: (\d+))?(?: (\d+))?/ // adds a command complete message -Result.prototype.addCommandComplete = function(msg) { +Result.prototype.addCommandComplete = function (msg) { var match if (msg.text) { // pure javascript @@ -52,7 +52,7 @@ Result.prototype.addCommandComplete = function(msg) { } } -Result.prototype._parseRowAsArray = function(rowData) { +Result.prototype._parseRowAsArray = function (rowData) { var row = new Array(rowData.length) for (var i = 0, len = rowData.length; i < len; i++) { var rawValue = rowData[i] @@ -65,7 +65,7 @@ Result.prototype._parseRowAsArray = function(rowData) { return row } -Result.prototype.parseRow = function(rowData) { +Result.prototype.parseRow = function (rowData) { var row = {} for (var i = 0, len = rowData.length; i < len; i++) { var rawValue = rowData[i] @@ -79,11 +79,11 @@ Result.prototype.parseRow = function(rowData) { return row } -Result.prototype.addRow = function(row) { +Result.prototype.addRow = function (row) { this.rows.push(row) } -Result.prototype.addFields = function(fieldDescriptions) { +Result.prototype.addFields = function (fieldDescriptions) { // clears field definitions // multiple query statements in 1 action can result in multiple sets // of rowDescriptions...eg: 'select NOW(); select 1::int;' diff --git a/packages/pg/lib/sasl.js b/packages/pg/lib/sasl.js index 8308a489d..22abf5c4a 100644 --- a/packages/pg/lib/sasl.js +++ b/packages/pg/lib/sasl.js @@ -32,10 +32,7 @@ function continueSession(session, password, serverData) { var saltedPassword = Hi(password, saltBytes, sv.iteration) var clientKey = createHMAC(saltedPassword, 'Client Key') - var storedKey = crypto - .createHash('sha256') - .update(clientKey) - .digest() + var storedKey = crypto.createHash('sha256').update(clientKey).digest() var clientFirstMessageBare = 'n=*,r=' + session.clientNonce var serverFirstMessage = 'r=' + sv.nonce + ',s=' + sv.salt + ',i=' + sv.iteration @@ -65,7 +62,7 @@ function finalizeSession(session, serverData) { String(serverData) .split(',') - .forEach(function(part) { + .forEach(function (part) { switch (part[0]) { case 'v': serverSignature = part.substr(2) @@ -83,7 +80,7 @@ function extractVariablesFromFirstServerMessage(data) { String(data) .split(',') - .forEach(function(part) { + .forEach(function (part) { switch (part[0]) { case 'r': nonce = part.substr(2) @@ -133,10 +130,7 @@ function xorBuffers(a, b) { } function createHMAC(key, msg) { - return crypto - .createHmac('sha256', key) - .update(msg) - .digest() + return crypto.createHmac('sha256', key).update(msg).digest() } function Hi(password, saltBytes, iterations) { diff --git a/packages/pg/lib/type-overrides.js b/packages/pg/lib/type-overrides.js index 88b5b93c2..63bfc83e1 100644 --- a/packages/pg/lib/type-overrides.js +++ b/packages/pg/lib/type-overrides.js @@ -15,7 +15,7 @@ function TypeOverrides(userTypes) { this.binary = {} } -TypeOverrides.prototype.getOverrides = function(format) { +TypeOverrides.prototype.getOverrides = function (format) { switch (format) { case 'text': return this.text @@ -26,7 +26,7 @@ TypeOverrides.prototype.getOverrides = function(format) { } } -TypeOverrides.prototype.setTypeParser = function(oid, format, parseFn) { +TypeOverrides.prototype.setTypeParser = function (oid, format, parseFn) { if (typeof format === 'function') { parseFn = format format = 'text' @@ -34,7 +34,7 @@ TypeOverrides.prototype.setTypeParser = function(oid, format, parseFn) { this.getOverrides(format)[oid] = parseFn } -TypeOverrides.prototype.getTypeParser = function(oid, format) { +TypeOverrides.prototype.getTypeParser = function (oid, format) { format = format || 'text' return this.getOverrides(format)[oid] || this._types.getTypeParser(oid, format) } diff --git a/packages/pg/lib/utils.js b/packages/pg/lib/utils.js index f4e29f8ef..f6da81f47 100644 --- a/packages/pg/lib/utils.js +++ b/packages/pg/lib/utils.js @@ -44,7 +44,7 @@ function arrayString(val) { // to their 'raw' counterparts for use as a postgres parameter // note: you can override this function to provide your own conversion mechanism // for complex types, etc... -var prepareValue = function(val, seen) { +var prepareValue = function (val, seen) { if (val instanceof Buffer) { return val } @@ -170,15 +170,12 @@ function normalizeQueryConfig(config, values, callback) { return config } -const md5 = function(string) { - return crypto - .createHash('md5') - .update(string, 'utf-8') - .digest('hex') +const md5 = function (string) { + return crypto.createHash('md5').update(string, 'utf-8').digest('hex') } // See AuthenticationMD5Password at https://www.postgresql.org/docs/current/static/protocol-flow.html -const postgresMd5PasswordHash = function(user, password, salt) { +const postgresMd5PasswordHash = function (user, password, salt) { var inner = md5(password + user) var outer = md5(Buffer.concat([Buffer.from(inner), salt])) return 'md5' + outer diff --git a/packages/pg/script/dump-db-types.js b/packages/pg/script/dump-db-types.js index d1e7f7328..08fe4dc98 100644 --- a/packages/pg/script/dump-db-types.js +++ b/packages/pg/script/dump-db-types.js @@ -4,14 +4,14 @@ var args = require(__dirname + '/../test/cli') var queries = ['select CURRENT_TIMESTAMP', "select interval '1 day' + interval '1 hour'", "select TIMESTAMP 'today'"] -queries.forEach(function(query) { +queries.forEach(function (query) { var client = new pg.Client({ user: args.user, database: args.database, password: args.password, }) client.connect() - client.query(query).on('row', function(row) { + client.query(query).on('row', function (row) { console.log(row) client.end() }) diff --git a/packages/pg/script/list-db-types.js b/packages/pg/script/list-db-types.js index dfe527251..c3e75c1ae 100644 --- a/packages/pg/script/list-db-types.js +++ b/packages/pg/script/list-db-types.js @@ -3,7 +3,7 @@ var helper = require(__dirname + '/../test/integration/test-helper') var pg = helper.pg pg.connect( helper.config, - assert.success(function(client) { + assert.success(function (client) { var query = client.query("select oid, typname from pg_type where typtype = 'b' order by oid") query.on('row', console.log) }) diff --git a/packages/pg/test/buffer-list.js b/packages/pg/test/buffer-list.js index ca54e8ed6..aea529c10 100644 --- a/packages/pg/test/buffer-list.js +++ b/packages/pg/test/buffer-list.js @@ -1,32 +1,32 @@ 'use strict' -global.BufferList = function() { +global.BufferList = function () { this.buffers = [] } var p = BufferList.prototype -p.add = function(buffer, front) { +p.add = function (buffer, front) { this.buffers[front ? 'unshift' : 'push'](buffer) return this } -p.addInt16 = function(val, front) { +p.addInt16 = function (val, front) { return this.add(Buffer.from([val >>> 8, val >>> 0]), front) } -p.getByteLength = function(initial) { - return this.buffers.reduce(function(previous, current) { +p.getByteLength = function (initial) { + return this.buffers.reduce(function (previous, current) { return previous + current.length }, initial || 0) } -p.addInt32 = function(val, first) { +p.addInt32 = function (val, first) { return this.add( Buffer.from([(val >>> 24) & 0xff, (val >>> 16) & 0xff, (val >>> 8) & 0xff, (val >>> 0) & 0xff]), first ) } -p.addCString = function(val, front) { +p.addCString = function (val, front) { var len = Buffer.byteLength(val) var buffer = Buffer.alloc(len + 1) buffer.write(val) @@ -34,18 +34,18 @@ p.addCString = function(val, front) { return this.add(buffer, front) } -p.addString = function(val, front) { +p.addString = function (val, front) { var len = Buffer.byteLength(val) var buffer = Buffer.alloc(len) buffer.write(val) return this.add(buffer, front) } -p.addChar = function(char, first) { +p.addChar = function (char, first) { return this.add(Buffer.from(char, 'utf8'), first) } -p.join = function(appendLength, char) { +p.join = function (appendLength, char) { var length = this.getByteLength() if (appendLength) { this.addInt32(length + 4, true) @@ -57,14 +57,14 @@ p.join = function(appendLength, char) { } var result = Buffer.alloc(length) var index = 0 - this.buffers.forEach(function(buffer) { + this.buffers.forEach(function (buffer) { buffer.copy(result, index, 0) index += buffer.length }) return result } -BufferList.concat = function() { +BufferList.concat = function () { var total = new BufferList() for (var i = 0; i < arguments.length; i++) { total.add(arguments[i]) diff --git a/packages/pg/test/integration/client/api-tests.js b/packages/pg/test/integration/client/api-tests.js index 2abf7d6b8..a957c32ae 100644 --- a/packages/pg/test/integration/client/api-tests.js +++ b/packages/pg/test/integration/client/api-tests.js @@ -4,10 +4,10 @@ var pg = helper.pg var suite = new helper.Suite() -suite.test('null and undefined are both inserted as NULL', function(done) { +suite.test('null and undefined are both inserted as NULL', function (done) { const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { + assert.calls(function (err, client, release) { assert(!err) client.query('CREATE TEMP TABLE my_nulls(a varchar(1), b varchar(1), c integer, d integer, e date, f date)') client.query('INSERT INTO my_nulls(a,b,c,d,e,f) VALUES ($1,$2,$3,$4,$5,$6)', [ @@ -20,7 +20,7 @@ suite.test('null and undefined are both inserted as NULL', function(done) { ]) client.query( 'SELECT * FROM my_nulls', - assert.calls(function(err, result) { + assert.calls(function (err, result) { console.log(err) assert.ifError(err) assert.equal(result.rows.length, 1) @@ -41,7 +41,7 @@ suite.test('null and undefined are both inserted as NULL', function(done) { suite.test('pool callback behavior', (done) => { // test weird callback behavior with node-pool const pool = new pg.Pool() - pool.connect(function(err) { + pool.connect(function (err) { assert(!err) arguments[1].emit('drain') arguments[2]() @@ -54,7 +54,7 @@ suite.test('query timeout', (cb) => { pool.connect().then((client) => { client.query( 'SELECT pg_sleep(2)', - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(err) assert(err.message === 'Query read timeout') client.release() @@ -69,14 +69,14 @@ suite.test('query recover from timeout', (cb) => { pool.connect().then((client) => { client.query( 'SELECT pg_sleep(20)', - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(err) assert(err.message === 'Query read timeout') client.release(err) pool.connect().then((client) => { client.query( 'SELECT 1', - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) client.release(err) pool.end(cb) @@ -93,7 +93,7 @@ suite.test('query no timeout', (cb) => { pool.connect().then((client) => { client.query( 'SELECT pg_sleep(1)', - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) client.release() pool.end(cb) @@ -135,21 +135,21 @@ suite.test('callback API', (done) => { }) }) -suite.test('executing nested queries', function(done) { +suite.test('executing nested queries', function (done) { const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { + assert.calls(function (err, client, release) { assert(!err) client.query( 'select now as now from NOW()', - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert.equal(new Date().getYear(), result.rows[0].now.getYear()) client.query( 'select now as now_again FROM NOW()', - assert.calls(function() { + assert.calls(function () { client.query( 'select * FROM NOW()', - assert.calls(function() { + assert.calls(function () { assert.ok('all queries hit') release() pool.end(done) @@ -163,25 +163,25 @@ suite.test('executing nested queries', function(done) { ) }) -suite.test('raises error if cannot connect', function() { +suite.test('raises error if cannot connect', function () { var connectionString = 'pg://sfalsdkf:asdf@localhost/ieieie' const pool = new pg.Pool({ connectionString: connectionString }) pool.connect( - assert.calls(function(err, client, done) { + assert.calls(function (err, client, done) { assert.ok(err, 'should have raised an error') done() }) ) }) -suite.test('query errors are handled and do not bubble if callback is provided', function(done) { +suite.test('query errors are handled and do not bubble if callback is provided', function (done) { const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { + assert.calls(function (err, client, release) { assert(!err) client.query( 'SELECT OISDJF FROM LEIWLISEJLSE', - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert.ok(err) release() pool.end(done) @@ -191,10 +191,10 @@ suite.test('query errors are handled and do not bubble if callback is provided', ) }) -suite.test('callback is fired once and only once', function(done) { +suite.test('callback is fired once and only once', function (done) { const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { + assert.calls(function (err, client, release) { assert(!err) client.query('CREATE TEMP TABLE boom(name varchar(10))') var callCount = 0 @@ -204,7 +204,7 @@ suite.test('callback is fired once and only once', function(done) { "INSERT INTO boom(name) VALUES('boom')", "INSERT INTO boom(name) VALUES('zoom')", ].join(';'), - function(err, callback) { + function (err, callback) { assert.equal(callCount++, 0, 'Call count should be 0. More means this callback fired more than once.') release() pool.end(done) @@ -214,17 +214,17 @@ suite.test('callback is fired once and only once', function(done) { ) }) -suite.test('can provide callback and config object', function(done) { +suite.test('can provide callback and config object', function (done) { const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { + assert.calls(function (err, client, release) { assert(!err) client.query( { name: 'boom', text: 'select NOW()', }, - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) assert.equal(result.rows[0].now.getYear(), new Date().getYear()) release() @@ -235,10 +235,10 @@ suite.test('can provide callback and config object', function(done) { ) }) -suite.test('can provide callback and config and parameters', function(done) { +suite.test('can provide callback and config and parameters', function (done) { const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { + assert.calls(function (err, client, release) { assert(!err) var config = { text: 'select $1::text as val', @@ -246,7 +246,7 @@ suite.test('can provide callback and config and parameters', function(done) { client.query( config, ['hi'], - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) assert.equal(result.rows.length, 1) assert.equal(result.rows[0].val, 'hi') diff --git a/packages/pg/test/integration/client/appname-tests.js b/packages/pg/test/integration/client/appname-tests.js index fc773af41..dd8de6b39 100644 --- a/packages/pg/test/integration/client/appname-tests.js +++ b/packages/pg/test/integration/client/appname-tests.js @@ -13,10 +13,10 @@ function getConInfo(override) { function getAppName(conf, cb) { var client = new Client(conf) client.connect( - assert.success(function() { + assert.success(function () { client.query( 'SHOW application_name', - assert.success(function(res) { + assert.success(function (res) { var appName = res.rows[0].application_name cb(appName) client.end() @@ -26,50 +26,50 @@ function getAppName(conf, cb) { ) } -suite.test('No default appliation_name ', function(done) { +suite.test('No default appliation_name ', function (done) { var conf = getConInfo() - getAppName({}, function(res) { + getAppName({}, function (res) { assert.strictEqual(res, '') done() }) }) -suite.test('fallback_application_name is used', function(done) { +suite.test('fallback_application_name is used', function (done) { var fbAppName = 'this is my app' var conf = getConInfo({ fallback_application_name: fbAppName, }) - getAppName(conf, function(res) { + getAppName(conf, function (res) { assert.strictEqual(res, fbAppName) done() }) }) -suite.test('application_name is used', function(done) { +suite.test('application_name is used', function (done) { var appName = 'some wired !@#$% application_name' var conf = getConInfo({ application_name: appName, }) - getAppName(conf, function(res) { + getAppName(conf, function (res) { assert.strictEqual(res, appName) done() }) }) -suite.test('application_name has precedence over fallback_application_name', function(done) { +suite.test('application_name has precedence over fallback_application_name', function (done) { var appName = 'some wired !@#$% application_name' var fbAppName = 'some other strange $$test$$ appname' var conf = getConInfo({ application_name: appName, fallback_application_name: fbAppName, }) - getAppName(conf, function(res) { + getAppName(conf, function (res) { assert.strictEqual(res, appName) done() }) }) -suite.test('application_name from connection string', function(done) { +suite.test('application_name from connection string', function (done) { var appName = 'my app' var conParams = require(__dirname + '/../../../lib/connection-parameters') var conf @@ -78,7 +78,7 @@ suite.test('application_name from connection string', function(done) { } else { conf = 'postgres://?application_name=' + appName } - getAppName(conf, function(res) { + getAppName(conf, function (res) { assert.strictEqual(res, appName) done() }) @@ -86,9 +86,9 @@ suite.test('application_name from connection string', function(done) { // TODO: make the test work for native client too if (!helper.args.native) { - suite.test('application_name is read from the env', function(done) { + suite.test('application_name is read from the env', function (done) { var appName = (process.env.PGAPPNAME = 'testest') - getAppName({}, function(res) { + getAppName({}, function (res) { delete process.env.PGAPPNAME assert.strictEqual(res, appName) done() diff --git a/packages/pg/test/integration/client/array-tests.js b/packages/pg/test/integration/client/array-tests.js index dfeec66c3..f5e62b032 100644 --- a/packages/pg/test/integration/client/array-tests.js +++ b/packages/pg/test/integration/client/array-tests.js @@ -7,14 +7,14 @@ var suite = new helper.Suite() const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { + assert.calls(function (err, client, release) { assert(!err) - suite.test('nulls', function(done) { + suite.test('nulls', function (done) { client.query( 'SELECT $1::text[] as array', [[null]], - assert.success(function(result) { + assert.success(function (result) { var array = result.rows[0].array assert.lengthIs(array, 1) assert.isNull(array[0]) @@ -23,7 +23,7 @@ pool.connect( ) }) - suite.test('elements containing JSON-escaped characters', function(done) { + suite.test('elements containing JSON-escaped characters', function (done) { var param = '\\"\\"' for (var i = 1; i <= 0x1f; i++) { @@ -33,7 +33,7 @@ pool.connect( client.query( 'SELECT $1::text[] as array', [[param]], - assert.success(function(result) { + assert.success(function (result) { var array = result.rows[0].array assert.lengthIs(array, 1) assert.equal(array[0], param) @@ -45,17 +45,17 @@ pool.connect( suite.test('cleanup', () => release()) pool.connect( - assert.calls(function(err, client, release) { + assert.calls(function (err, client, release) { assert(!err) client.query('CREATE TEMP TABLE why(names text[], numbors integer[])') client .query(new pg.Query('INSERT INTO why(names, numbors) VALUES(\'{"aaron", "brian","a b c" }\', \'{1, 2, 3}\')')) .on('error', console.log) - suite.test('numbers', function(done) { + suite.test('numbers', function (done) { // client.connection.on('message', console.log) client.query( 'SELECT numbors FROM why', - assert.success(function(result) { + assert.success(function (result) { assert.lengthIs(result.rows[0].numbors, 3) assert.equal(result.rows[0].numbors[0], 1) assert.equal(result.rows[0].numbors[1], 2) @@ -65,10 +65,10 @@ pool.connect( ) }) - suite.test('parses string arrays', function(done) { + suite.test('parses string arrays', function (done) { client.query( 'SELECT names FROM why', - assert.success(function(result) { + assert.success(function (result) { var names = result.rows[0].names assert.lengthIs(names, 3) assert.equal(names[0], 'aaron') @@ -79,10 +79,10 @@ pool.connect( ) }) - suite.test('empty array', function(done) { + suite.test('empty array', function (done) { client.query( "SELECT '{}'::text[] as names", - assert.success(function(result) { + assert.success(function (result) { var names = result.rows[0].names assert.lengthIs(names, 0) done() @@ -90,10 +90,10 @@ pool.connect( ) }) - suite.test('element containing comma', function(done) { + suite.test('element containing comma', function (done) { client.query( 'SELECT \'{"joe,bob",jim}\'::text[] as names', - assert.success(function(result) { + assert.success(function (result) { var names = result.rows[0].names assert.lengthIs(names, 2) assert.equal(names[0], 'joe,bob') @@ -103,10 +103,10 @@ pool.connect( ) }) - suite.test('bracket in quotes', function(done) { + suite.test('bracket in quotes', function (done) { client.query( 'SELECT \'{"{","}"}\'::text[] as names', - assert.success(function(result) { + assert.success(function (result) { var names = result.rows[0].names assert.lengthIs(names, 2) assert.equal(names[0], '{') @@ -116,10 +116,10 @@ pool.connect( ) }) - suite.test('null value', function(done) { + suite.test('null value', function (done) { client.query( 'SELECT \'{joe,null,bob,"NULL"}\'::text[] as names', - assert.success(function(result) { + assert.success(function (result) { var names = result.rows[0].names assert.lengthIs(names, 4) assert.equal(names[0], 'joe') @@ -131,10 +131,10 @@ pool.connect( ) }) - suite.test('element containing quote char', function(done) { + suite.test('element containing quote char', function (done) { client.query( "SELECT ARRAY['joe''', 'jim', 'bob\"'] AS names", - assert.success(function(result) { + assert.success(function (result) { var names = result.rows[0].names assert.lengthIs(names, 3) assert.equal(names[0], "joe'") @@ -145,10 +145,10 @@ pool.connect( ) }) - suite.test('nested array', function(done) { + suite.test('nested array', function (done) { client.query( "SELECT '{{1,joe},{2,bob}}'::text[] as names", - assert.success(function(result) { + assert.success(function (result) { var names = result.rows[0].names assert.lengthIs(names, 2) @@ -164,10 +164,10 @@ pool.connect( ) }) - suite.test('integer array', function(done) { + suite.test('integer array', function (done) { client.query( "SELECT '{1,2,3}'::integer[] as names", - assert.success(function(result) { + assert.success(function (result) { var names = result.rows[0].names assert.lengthIs(names, 3) assert.equal(names[0], 1) @@ -178,10 +178,10 @@ pool.connect( ) }) - suite.test('integer nested array', function(done) { + suite.test('integer nested array', function (done) { client.query( "SELECT '{{1,100},{2,100},{3,100}}'::integer[] as names", - assert.success(function(result) { + assert.success(function (result) { var names = result.rows[0].names assert.lengthIs(names, 3) assert.equal(names[0][0], 1) @@ -197,7 +197,7 @@ pool.connect( ) }) - suite.test('JS array parameter', function(done) { + suite.test('JS array parameter', function (done) { client.query( 'SELECT $1::integer[] as names', [ @@ -207,7 +207,7 @@ pool.connect( [3, 100], ], ], - assert.success(function(result) { + assert.success(function (result) { var names = result.rows[0].names assert.lengthIs(names, 3) assert.equal(names[0][0], 1) diff --git a/packages/pg/test/integration/client/big-simple-query-tests.js b/packages/pg/test/integration/client/big-simple-query-tests.js index e51cde546..b0dc252f6 100644 --- a/packages/pg/test/integration/client/big-simple-query-tests.js +++ b/packages/pg/test/integration/client/big-simple-query-tests.js @@ -17,7 +17,7 @@ var big_query_rows_2 = [] var big_query_rows_3 = [] // Works -suite.test('big simple query 1', function(done) { +suite.test('big simple query 1', function (done) { var client = helper.client() client .query( @@ -25,10 +25,10 @@ suite.test('big simple query 1', function(done) { "select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = '' or 1 = 1" ) ) - .on('row', function(row) { + .on('row', function (row) { big_query_rows_1.push(row) }) - .on('error', function(error) { + .on('error', function (error) { console.log('big simple query 1 error') console.log(error) }) @@ -39,7 +39,7 @@ suite.test('big simple query 1', function(done) { }) // Works -suite.test('big simple query 2', function(done) { +suite.test('big simple query 2', function (done) { var client = helper.client() client .query( @@ -48,10 +48,10 @@ suite.test('big simple query 2', function(done) { [''] ) ) - .on('row', function(row) { + .on('row', function (row) { big_query_rows_2.push(row) }) - .on('error', function(error) { + .on('error', function (error) { console.log('big simple query 2 error') console.log(error) }) @@ -63,7 +63,7 @@ suite.test('big simple query 2', function(done) { // Fails most of the time with 'invalid byte sequence for encoding "UTF8": 0xb9' or 'insufficient data left in message' // If test 1 and 2 are commented out it works -suite.test('big simple query 3', function(done) { +suite.test('big simple query 3', function (done) { var client = helper.client() client .query( @@ -72,10 +72,10 @@ suite.test('big simple query 3', function(done) { [''] ) ) - .on('row', function(row) { + .on('row', function (row) { big_query_rows_3.push(row) }) - .on('error', function(error) { + .on('error', function (error) { console.log('big simple query 3 error') console.log(error) }) @@ -85,18 +85,18 @@ suite.test('big simple query 3', function(done) { }) }) -process.on('exit', function() { +process.on('exit', function () { assert.equal(big_query_rows_1.length, 26, 'big simple query 1 should return 26 rows') assert.equal(big_query_rows_2.length, 26, 'big simple query 2 should return 26 rows') assert.equal(big_query_rows_3.length, 26, 'big simple query 3 should return 26 rows') }) -var runBigQuery = function(client) { +var runBigQuery = function (client) { var rows = [] var q = client.query( "select 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' as bla from person where name = $1 or 1 = 1", [''], - function(err, result) { + function (err, result) { if (err != null) { console.log(err) throw Err @@ -106,14 +106,14 @@ var runBigQuery = function(client) { ) } -suite.test('many times', function(done) { +suite.test('many times', function (done) { var client = helper.client() for (var i = 0; i < 20; i++) { runBigQuery(client) } - client.on('drain', function() { + client.on('drain', function () { client.end() - setTimeout(function() { + setTimeout(function () { done() // let client disconnect fully }, 100) diff --git a/packages/pg/test/integration/client/configuration-tests.js b/packages/pg/test/integration/client/configuration-tests.js index 1366a3687..0737a79c3 100644 --- a/packages/pg/test/integration/client/configuration-tests.js +++ b/packages/pg/test/integration/client/configuration-tests.js @@ -11,7 +11,7 @@ for (var key in process.env) { if (!key.indexOf('PG')) delete process.env[key] } -suite.test('default values are used in new clients', function() { +suite.test('default values are used in new clients', function () { assert.same(pg.defaults, { user: process.env.USER, database: undefined, @@ -37,7 +37,7 @@ suite.test('default values are used in new clients', function() { }) }) -suite.test('modified values are passed to created clients', function() { +suite.test('modified values are passed to created clients', function () { pg.defaults.user = 'boom' pg.defaults.password = 'zap' pg.defaults.database = 'pow' diff --git a/packages/pg/test/integration/client/custom-types-tests.js b/packages/pg/test/integration/client/custom-types-tests.js index d22e9312d..d1dd2eec0 100644 --- a/packages/pg/test/integration/client/custom-types-tests.js +++ b/packages/pg/test/integration/client/custom-types-tests.js @@ -13,7 +13,7 @@ suite.test('custom type parser in client config', (done) => { client.connect().then(() => { client.query( 'SELECT NOW() as val', - assert.success(function(res) { + assert.success(function (res) { assert.equal(res.rows[0].val, 'okay!') client.end().then(done) }) @@ -32,7 +32,7 @@ if (!helper.args.native) { text: 'SELECT NOW() as val', types: customTypes, }, - assert.success(function(res) { + assert.success(function (res) { assert.equal(res.rows[0].val, 'okay!') client.end().then(done) }) diff --git a/packages/pg/test/integration/client/empty-query-tests.js b/packages/pg/test/integration/client/empty-query-tests.js index f22e5b399..d887885c7 100644 --- a/packages/pg/test/integration/client/empty-query-tests.js +++ b/packages/pg/test/integration/client/empty-query-tests.js @@ -2,17 +2,17 @@ var helper = require('./test-helper') const suite = new helper.Suite() -suite.test('empty query message handling', function(done) { +suite.test('empty query message handling', function (done) { const client = helper.client() - assert.emits(client, 'drain', function() { + assert.emits(client, 'drain', function () { client.end(done) }) client.query({ text: '' }) }) -suite.test('callback supported', function(done) { +suite.test('callback supported', function (done) { const client = helper.client() - client.query('', function(err, result) { + client.query('', function (err, result) { assert(!err) assert.empty(result.rows) client.end(done) diff --git a/packages/pg/test/integration/client/error-handling-tests.js b/packages/pg/test/integration/client/error-handling-tests.js index d5f44a94d..93959e02b 100644 --- a/packages/pg/test/integration/client/error-handling-tests.js +++ b/packages/pg/test/integration/client/error-handling-tests.js @@ -6,9 +6,9 @@ var util = require('util') var pg = helper.pg const Client = pg.Client -var createErorrClient = function() { +var createErorrClient = function () { var client = helper.client() - client.once('error', function(err) { + client.once('error', function (err) { assert.fail('Client shoud not throw error during query execution') }) client.on('drain', client.end.bind(client)) @@ -67,10 +67,10 @@ suite.test('using a client after closing it results in error', (done) => { }) }) -suite.test('query receives error on client shutdown', function(done) { +suite.test('query receives error on client shutdown', function (done) { var client = new Client() client.connect( - assert.success(function() { + assert.success(function () { const config = { text: 'select pg_sleep(5)', name: 'foobar', @@ -78,7 +78,7 @@ suite.test('query receives error on client shutdown', function(done) { let queryError client.query( new pg.Query(config), - assert.calls(function(err, res) { + assert.calls(function (err, res) { assert(err instanceof Error) queryError = err }) @@ -92,9 +92,9 @@ suite.test('query receives error on client shutdown', function(done) { ) }) -var ensureFuture = function(testClient, done) { +var ensureFuture = function (testClient, done) { var goodQuery = testClient.query(new pg.Query('select age from boom')) - assert.emits(goodQuery, 'row', function(row) { + assert.emits(goodQuery, 'row', function (row) { assert.equal(row.age, 28) done() }) @@ -113,12 +113,12 @@ suite.test('when query is parsing', (done) => { }) ) - assert.emits(query, 'error', function(err) { + assert.emits(query, 'error', function (err) { ensureFuture(client, done) }) }) -suite.test('when a query is binding', function(done) { +suite.test('when a query is binding', function (done) { var client = createErorrClient() var q = client.query({ text: 'CREATE TEMP TABLE boom(age integer); INSERT INTO boom (age) VALUES (28);' }) @@ -130,25 +130,25 @@ suite.test('when a query is binding', function(done) { }) ) - assert.emits(query, 'error', function(err) { + assert.emits(query, 'error', function (err) { assert.equal(err.severity, 'ERROR') ensureFuture(client, done) }) }) -suite.test('non-query error with callback', function(done) { +suite.test('non-query error with callback', function (done) { var client = new Client({ user: 'asldkfjsadlfkj', }) client.connect( - assert.calls(function(error, client) { + assert.calls(function (error, client) { assert(error instanceof Error) done() }) ) }) -suite.test('non-error calls supplied callback', function(done) { +suite.test('non-error calls supplied callback', function (done) { var client = new Client({ user: helper.args.user, password: helper.args.password, @@ -158,27 +158,27 @@ suite.test('non-error calls supplied callback', function(done) { }) client.connect( - assert.calls(function(err) { + assert.calls(function (err) { assert.ifError(err) client.end(done) }) ) }) -suite.test('when connecting to an invalid host with callback', function(done) { +suite.test('when connecting to an invalid host with callback', function (done) { var client = new Client({ user: 'very invalid username', }) client.on('error', () => { assert.fail('unexpected error event when connecting') }) - client.connect(function(error, client) { + client.connect(function (error, client) { assert(error instanceof Error) done() }) }) -suite.test('when connecting to invalid host with promise', function(done) { +suite.test('when connecting to invalid host with promise', function (done) { var client = new Client({ user: 'very invalid username', }) @@ -188,7 +188,7 @@ suite.test('when connecting to invalid host with promise', function(done) { client.connect().catch((e) => done()) }) -suite.test('non-query error', function(done) { +suite.test('non-query error', function (done) { var client = new Client({ user: 'asldkfjsadlfkj', }) @@ -203,7 +203,7 @@ suite.test('within a simple query', (done) => { var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")) - assert.emits(query, 'error', function(error) { + assert.emits(query, 'error', function (error) { assert.equal(error.severity, 'ERROR') done() }) diff --git a/packages/pg/test/integration/client/field-name-escape-tests.js b/packages/pg/test/integration/client/field-name-escape-tests.js index bb6a9def9..146ad1b68 100644 --- a/packages/pg/test/integration/client/field-name-escape-tests.js +++ b/packages/pg/test/integration/client/field-name-escape-tests.js @@ -4,7 +4,7 @@ var sql = 'SELECT 1 AS "\\\'/*", 2 AS "\\\'*/\n + process.exit(-1)] = null;\n//" var client = new pg.Client() client.connect() -client.query(sql, function(err, res) { +client.query(sql, function (err, res) { if (err) throw err client.end() }) diff --git a/packages/pg/test/integration/client/huge-numeric-tests.js b/packages/pg/test/integration/client/huge-numeric-tests.js index ccd433f0a..bdbfac261 100644 --- a/packages/pg/test/integration/client/huge-numeric-tests.js +++ b/packages/pg/test/integration/client/huge-numeric-tests.js @@ -3,13 +3,13 @@ var helper = require('./test-helper') const pool = new helper.pg.Pool() pool.connect( - assert.success(function(client, done) { + assert.success(function (client, done) { var types = require('pg-types') // 1231 = numericOID - types.setTypeParser(1700, function() { + types.setTypeParser(1700, function () { return 'yes' }) - types.setTypeParser(1700, 'binary', function() { + types.setTypeParser(1700, 'binary', function () { return 'yes' }) var bignum = '294733346389144765940638005275322203805' @@ -17,7 +17,7 @@ pool.connect( client.query('INSERT INTO bignumz(id) VALUES ($1)', [bignum]) client.query( 'SELECT * FROM bignumz', - assert.success(function(result) { + assert.success(function (result) { assert.equal(result.rows[0].id, 'yes') done() pool.end() diff --git a/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js b/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js index a8db2fcb3..f970faaf2 100644 --- a/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js +++ b/packages/pg/test/integration/client/idle_in_transaction_session_timeout-tests.js @@ -13,13 +13,13 @@ function getConInfo(override) { function testClientVersion(cb) { var client = new Client({}) client.connect( - assert.success(function() { + assert.success(function () { helper.versionGTE( client, 100000, - assert.success(function(isGreater) { + assert.success(function (isGreater) { return client.end( - assert.success(function() { + assert.success(function () { if (!isGreater) { console.log( 'skip idle_in_transaction_session_timeout at client-level is only available in v10 and above' @@ -38,10 +38,10 @@ function testClientVersion(cb) { function getIdleTransactionSessionTimeout(conf, cb) { var client = new Client(conf) client.connect( - assert.success(function() { + assert.success(function () { client.query( 'SHOW idle_in_transaction_session_timeout', - assert.success(function(res) { + assert.success(function (res) { var timeout = res.rows[0].idle_in_transaction_session_timeout cb(timeout) client.end() @@ -53,40 +53,40 @@ function getIdleTransactionSessionTimeout(conf, cb) { if (!helper.args.native) { // idle_in_transaction_session_timeout is not supported with the native client - testClientVersion(function() { - suite.test('No default idle_in_transaction_session_timeout ', function(done) { + testClientVersion(function () { + suite.test('No default idle_in_transaction_session_timeout ', function (done) { getConInfo() - getIdleTransactionSessionTimeout({}, function(res) { + getIdleTransactionSessionTimeout({}, function (res) { assert.strictEqual(res, '0') // 0 = no timeout done() }) }) - suite.test('idle_in_transaction_session_timeout integer is used', function(done) { + suite.test('idle_in_transaction_session_timeout integer is used', function (done) { var conf = getConInfo({ idle_in_transaction_session_timeout: 3000, }) - getIdleTransactionSessionTimeout(conf, function(res) { + getIdleTransactionSessionTimeout(conf, function (res) { assert.strictEqual(res, '3s') done() }) }) - suite.test('idle_in_transaction_session_timeout float is used', function(done) { + suite.test('idle_in_transaction_session_timeout float is used', function (done) { var conf = getConInfo({ idle_in_transaction_session_timeout: 3000.7, }) - getIdleTransactionSessionTimeout(conf, function(res) { + getIdleTransactionSessionTimeout(conf, function (res) { assert.strictEqual(res, '3s') done() }) }) - suite.test('idle_in_transaction_session_timeout string is used', function(done) { + suite.test('idle_in_transaction_session_timeout string is used', function (done) { var conf = getConInfo({ idle_in_transaction_session_timeout: '3000', }) - getIdleTransactionSessionTimeout(conf, function(res) { + getIdleTransactionSessionTimeout(conf, function (res) { assert.strictEqual(res, '3s') done() }) diff --git a/packages/pg/test/integration/client/json-type-parsing-tests.js b/packages/pg/test/integration/client/json-type-parsing-tests.js index f4d431d3f..ba7696020 100644 --- a/packages/pg/test/integration/client/json-type-parsing-tests.js +++ b/packages/pg/test/integration/client/json-type-parsing-tests.js @@ -4,11 +4,11 @@ var assert = require('assert') const pool = new helper.pg.Pool() pool.connect( - assert.success(function(client, done) { + assert.success(function (client, done) { helper.versionGTE( client, 90200, - assert.success(function(jsonSupported) { + assert.success(function (jsonSupported) { if (!jsonSupported) { console.log('skip json test on older versions of postgres') done() @@ -19,7 +19,7 @@ pool.connect( client.query('INSERT INTO stuff (data) VALUES ($1)', [value]) client.query( 'SELECT * FROM stuff', - assert.success(function(result) { + assert.success(function (result) { assert.equal(result.rows.length, 1) assert.equal(typeof result.rows[0].data, 'object') var row = result.rows[0].data diff --git a/packages/pg/test/integration/client/multiple-results-tests.js b/packages/pg/test/integration/client/multiple-results-tests.js index 8a084d040..addca9b68 100644 --- a/packages/pg/test/integration/client/multiple-results-tests.js +++ b/packages/pg/test/integration/client/multiple-results-tests.js @@ -8,7 +8,7 @@ const suite = new helper.Suite('multiple result sets') suite.test( 'two select results work', - co.wrap(function*() { + co.wrap(function* () { const client = new helper.Client() yield client.connect() @@ -27,7 +27,7 @@ suite.test( suite.test( 'multiple selects work', - co.wrap(function*() { + co.wrap(function* () { const client = new helper.Client() yield client.connect() @@ -57,7 +57,7 @@ suite.test( suite.test( 'mixed queries and statements', - co.wrap(function*() { + co.wrap(function* () { const client = new helper.Client() yield client.connect() diff --git a/packages/pg/test/integration/client/network-partition-tests.js b/packages/pg/test/integration/client/network-partition-tests.js index b0fa8bb71..993396401 100644 --- a/packages/pg/test/integration/client/network-partition-tests.js +++ b/packages/pg/test/integration/client/network-partition-tests.js @@ -5,24 +5,24 @@ var suite = new helper.Suite() var net = require('net') -var Server = function(response) { +var Server = function (response) { this.server = undefined this.socket = undefined this.response = response } -Server.prototype.start = function(cb) { +Server.prototype.start = function (cb) { // this is our fake postgres server // it responds with our specified response immediatley after receiving every buffer // this is sufficient into convincing the client its connectet to a valid backend // if we respond with a readyForQuery message this.server = net.createServer( - function(socket) { + function (socket) { this.socket = socket if (this.response) { this.socket.on( 'data', - function(data) { + function (data) { // deny request for SSL if (data.length == 8) { this.socket.write(Buffer.from('N', 'utf8')) @@ -45,22 +45,22 @@ Server.prototype.start = function(cb) { host: 'localhost', port: port, } - this.server.listen(options.port, options.host, function() { + this.server.listen(options.port, options.host, function () { cb(options) }) } -Server.prototype.drop = function() { +Server.prototype.drop = function () { this.socket.destroy() } -Server.prototype.close = function(cb) { +Server.prototype.close = function (cb) { this.server.close(cb) } -var testServer = function(server, cb) { +var testServer = function (server, cb) { // wait for our server to start - server.start(function(options) { + server.start(function (options) { // connect a client to it var client = new helper.Client(options) client.connect().catch((err) => { @@ -71,13 +71,13 @@ var testServer = function(server, cb) { server.server.on('connection', () => { // after 50 milliseconds, drop the client - setTimeout(function() { + setTimeout(function () { server.drop() }, 50) }) // blow up if we don't receive an error - var timeoutId = setTimeout(function() { + var timeoutId = setTimeout(function () { throw new Error('Client should have emitted an error but it did not.') }, 5000) }) diff --git a/packages/pg/test/integration/client/no-data-tests.js b/packages/pg/test/integration/client/no-data-tests.js index c4051d11e..ad0f22be3 100644 --- a/packages/pg/test/integration/client/no-data-tests.js +++ b/packages/pg/test/integration/client/no-data-tests.js @@ -2,7 +2,7 @@ var helper = require('./test-helper') const suite = new helper.Suite() -suite.test('noData message handling', function() { +suite.test('noData message handling', function () { var client = helper.client() var q = client.query({ @@ -16,7 +16,7 @@ suite.test('noData message handling', function() { text: 'insert into boom(size) values($1)', values: [100], }, - function(err, result) { + function (err, result) { if (err) { console.log(err) throw err diff --git a/packages/pg/test/integration/client/no-row-result-tests.js b/packages/pg/test/integration/client/no-row-result-tests.js index a4acf31ef..6e8f52cf0 100644 --- a/packages/pg/test/integration/client/no-row-result-tests.js +++ b/packages/pg/test/integration/client/no-row-result-tests.js @@ -4,8 +4,8 @@ var pg = helper.pg const suite = new helper.Suite() const pool = new pg.Pool() -suite.test('can access results when no rows are returned', function(done) { - var checkResult = function(result) { +suite.test('can access results when no rows are returned', function (done) { + var checkResult = function (result) { assert(result.fields, 'should have fields definition') assert.equal(result.fields.length, 1) assert.equal(result.fields[0].name, 'val') @@ -13,11 +13,11 @@ suite.test('can access results when no rows are returned', function(done) { } pool.connect( - assert.success(function(client, release) { + assert.success(function (client, release) { const q = new pg.Query('select $1::text as val limit 0', ['hi']) var query = client.query( q, - assert.success(function(result) { + assert.success(function (result) { checkResult(result) release() pool.end(done) diff --git a/packages/pg/test/integration/client/notice-tests.js b/packages/pg/test/integration/client/notice-tests.js index 1c232711b..b5d4f3d5e 100644 --- a/packages/pg/test/integration/client/notice-tests.js +++ b/packages/pg/test/integration/client/notice-tests.js @@ -3,19 +3,19 @@ const helper = require('./test-helper') const assert = require('assert') const suite = new helper.Suite() -suite.test('emits notify message', function(done) { +suite.test('emits notify message', function (done) { const client = helper.client() client.query( 'LISTEN boom', - assert.calls(function() { + assert.calls(function () { const otherClient = helper.client() let bothEmitted = -1 otherClient.query( 'LISTEN boom', - assert.calls(function() { - assert.emits(client, 'notification', function(msg) { + assert.calls(function () { + assert.emits(client, 'notification', function (msg) { // make sure PQfreemem doesn't invalidate string pointers - setTimeout(function() { + setTimeout(function () { assert.equal(msg.channel, 'boom') assert.ok( msg.payload == 'omg!' /* 9.x */ || msg.payload == '' /* 8.x */, @@ -24,12 +24,12 @@ suite.test('emits notify message', function(done) { client.end(++bothEmitted ? done : undefined) }, 100) }) - assert.emits(otherClient, 'notification', function(msg) { + assert.emits(otherClient, 'notification', function (msg) { assert.equal(msg.channel, 'boom') otherClient.end(++bothEmitted ? done : undefined) }) - client.query("NOTIFY boom, 'omg!'", function(err, q) { + client.query("NOTIFY boom, 'omg!'", function (err, q) { if (err) { // notify not supported with payload on 8.x client.query('NOTIFY boom') @@ -42,7 +42,7 @@ suite.test('emits notify message', function(done) { }) // this test fails on travis due to their config -suite.test('emits notice message', function(done) { +suite.test('emits notice message', function (done) { if (helper.args.native) { console.error('notice messages do not work curreintly with node-libpq') return done() @@ -62,7 +62,7 @@ $$; client.end() }) }) - assert.emits(client, 'notice', function(notice) { + assert.emits(client, 'notice', function (notice) { assert.ok(notice != null) // notice messages should not be error instances assert(notice instanceof Error === false) diff --git a/packages/pg/test/integration/client/parse-int-8-tests.js b/packages/pg/test/integration/client/parse-int-8-tests.js index 88ac8cf7c..9f251de69 100644 --- a/packages/pg/test/integration/client/parse-int-8-tests.js +++ b/packages/pg/test/integration/client/parse-int-8-tests.js @@ -5,15 +5,15 @@ var pg = helper.pg const suite = new helper.Suite() const pool = new pg.Pool(helper.config) -suite.test('ability to turn on and off parser', function() { +suite.test('ability to turn on and off parser', function () { if (helper.args.binary) return false pool.connect( - assert.success(function(client, done) { + assert.success(function (client, done) { pg.defaults.parseInt8 = true client.query('CREATE TEMP TABLE asdf(id SERIAL PRIMARY KEY)') client.query( 'SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', - assert.success(function(res) { + assert.success(function (res) { assert.strictEqual(0, res.rows[0].count) assert.strictEqual(1, res.rows[0].array[0]) assert.strictEqual(2, res.rows[0].array[1]) @@ -21,7 +21,7 @@ suite.test('ability to turn on and off parser', function() { pg.defaults.parseInt8 = false client.query( 'SELECT COUNT(*) as "count", \'{1,2,3}\'::bigint[] as array FROM asdf', - assert.success(function(res) { + assert.success(function (res) { done() assert.strictEqual('0', res.rows[0].count) assert.strictEqual('1', res.rows[0].array[0]) diff --git a/packages/pg/test/integration/client/prepared-statement-tests.js b/packages/pg/test/integration/client/prepared-statement-tests.js index 57286bd5e..48d12f899 100644 --- a/packages/pg/test/integration/client/prepared-statement-tests.js +++ b/packages/pg/test/integration/client/prepared-statement-tests.js @@ -4,14 +4,14 @@ var Query = helper.pg.Query var suite = new helper.Suite() -;(function() { +;(function () { var client = helper.client() client.on('drain', client.end.bind(client)) var queryName = 'user by age and like name' var parseCount = 0 - suite.test('first named prepared statement', function(done) { + suite.test('first named prepared statement', function (done) { var query = client.query( new Query({ text: 'select name from person where age <= $1 and name LIKE $2', @@ -20,14 +20,14 @@ var suite = new helper.Suite() }) ) - assert.emits(query, 'row', function(row) { + assert.emits(query, 'row', function (row) { assert.equal(row.name, 'Brian') }) query.on('end', () => done()) }) - suite.test('second named prepared statement with same name & text', function(done) { + suite.test('second named prepared statement with same name & text', function (done) { var cachedQuery = client.query( new Query({ text: 'select name from person where age <= $1 and name LIKE $2', @@ -36,14 +36,14 @@ var suite = new helper.Suite() }) ) - assert.emits(cachedQuery, 'row', function(row) { + assert.emits(cachedQuery, 'row', function (row) { assert.equal(row.name, 'Aaron') }) cachedQuery.on('end', () => done()) }) - suite.test('with same name, but without query text', function(done) { + suite.test('with same name, but without query text', function (done) { var q = client.query( new Query({ name: queryName, @@ -51,11 +51,11 @@ var suite = new helper.Suite() }) ) - assert.emits(q, 'row', function(row) { + assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Aaron') // test second row is emitted as well - assert.emits(q, 'row', function(row) { + assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Brian') }) }) @@ -63,7 +63,7 @@ var suite = new helper.Suite() q.on('end', () => done()) }) - suite.test('with same name, but with different text', function(done) { + suite.test('with same name, but with different text', function (done) { client.query( new Query({ text: 'select name from person where age >= $1 and name LIKE $2', @@ -80,7 +80,7 @@ var suite = new helper.Suite() ) }) })() -;(function() { +;(function () { var statementName = 'differ' var statement1 = 'select count(*)::int4 as count from person' var statement2 = 'select count(*)::int4 as count from person where age < $1' @@ -88,7 +88,7 @@ var suite = new helper.Suite() var client1 = helper.client() var client2 = helper.client() - suite.test('client 1 execution', function(done) { + suite.test('client 1 execution', function (done) { var query = client1.query( { name: statementName, @@ -102,7 +102,7 @@ var suite = new helper.Suite() ) }) - suite.test('client 2 execution', function(done) { + suite.test('client 2 execution', function (done) { var query = client2.query( new Query({ name: statementName, @@ -111,11 +111,11 @@ var suite = new helper.Suite() }) ) - assert.emits(query, 'row', function(row) { + assert.emits(query, 'row', function (row) { assert.equal(row.count, 1) }) - assert.emits(query, 'end', function() { + assert.emits(query, 'end', function () { done() }) }) @@ -124,28 +124,28 @@ var suite = new helper.Suite() return client1.end().then(() => client2.end()) }) })() -;(function() { +;(function () { var client = helper.client() client.query('CREATE TEMP TABLE zoom(name varchar(100));') client.query("INSERT INTO zoom (name) VALUES ('zed')") client.query("INSERT INTO zoom (name) VALUES ('postgres')") client.query("INSERT INTO zoom (name) VALUES ('node postgres')") - var checkForResults = function(q) { - assert.emits(q, 'row', function(row) { + var checkForResults = function (q) { + assert.emits(q, 'row', function (row) { assert.equal(row.name, 'node postgres') - assert.emits(q, 'row', function(row) { + assert.emits(q, 'row', function (row) { assert.equal(row.name, 'postgres') - assert.emits(q, 'row', function(row) { + assert.emits(q, 'row', function (row) { assert.equal(row.name, 'zed') }) }) }) } - suite.test('with small row count', function(done) { + suite.test('with small row count', function (done) { var query = client.query( new Query( { @@ -160,7 +160,7 @@ var suite = new helper.Suite() checkForResults(query) }) - suite.test('with large row count', function(done) { + suite.test('with large row count', function (done) { var query = client.query( new Query( { diff --git a/packages/pg/test/integration/client/query-as-promise-tests.js b/packages/pg/test/integration/client/query-as-promise-tests.js index 6be886c74..46365c6c0 100644 --- a/packages/pg/test/integration/client/query-as-promise-tests.js +++ b/packages/pg/test/integration/client/query-as-promise-tests.js @@ -3,7 +3,7 @@ var bluebird = require('bluebird') var helper = require(__dirname + '/../test-helper') var pg = helper.pg -process.on('unhandledRejection', function(e) { +process.on('unhandledRejection', function (e) { console.error(e, e.stack) process.exit(1) }) @@ -15,14 +15,14 @@ suite.test('promise API', (cb) => { pool.connect().then((client) => { client .query('SELECT $1::text as name', ['foo']) - .then(function(result) { + .then(function (result) { assert.equal(result.rows[0].name, 'foo') return client }) - .then(function(client) { - client.query('ALKJSDF').catch(function(e) { + .then(function (client) { + client.query('ALKJSDF').catch(function (e) { assert(e instanceof Error) - client.query('SELECT 1 as num').then(function(result) { + client.query('SELECT 1 as num').then(function (result) { assert.equal(result.rows[0].num, 1) client.release() pool.end(cb) diff --git a/packages/pg/test/integration/client/query-column-names-tests.js b/packages/pg/test/integration/client/query-column-names-tests.js index 61469ec96..6b32881e5 100644 --- a/packages/pg/test/integration/client/query-column-names-tests.js +++ b/packages/pg/test/integration/client/query-column-names-tests.js @@ -2,14 +2,14 @@ var helper = require(__dirname + '/../test-helper') var pg = helper.pg -new helper.Suite().test('support for complex column names', function() { +new helper.Suite().test('support for complex column names', function () { const pool = new pg.Pool() pool.connect( - assert.success(function(client, done) { + assert.success(function (client, done) { client.query('CREATE TEMP TABLE t ( "complex\'\'column" TEXT )') client.query( 'SELECT * FROM t', - assert.success(function(res) { + assert.success(function (res) { done() assert.strictEqual(res.fields[0].name, "complex''column") pool.end() diff --git a/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js b/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js index 2930761dd..adef58d16 100644 --- a/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js +++ b/packages/pg/test/integration/client/query-error-handling-prepared-statement-tests.js @@ -5,10 +5,10 @@ var util = require('util') var suite = new helper.Suite() -suite.test('client end during query execution of prepared statement', function(done) { +suite.test('client end during query execution of prepared statement', function (done) { var client = new Client() client.connect( - assert.success(function() { + assert.success(function () { var sleepQuery = 'select pg_sleep($1)' var queryConfig = { @@ -19,7 +19,7 @@ suite.test('client end during query execution of prepared statement', function(d var queryInstance = new Query( queryConfig, - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert.equal(err.message, 'Connection terminated') done() }) @@ -27,15 +27,15 @@ suite.test('client end during query execution of prepared statement', function(d var query1 = client.query(queryInstance) - query1.on('error', function(err) { + query1.on('error', function (err) { assert.fail('Prepared statement should not emit error') }) - query1.on('row', function(row) { + query1.on('row', function (row) { assert.fail('Prepared statement should not emit row') }) - query1.on('end', function(err) { + query1.on('end', function (err) { assert.fail('Prepared statement when executed should not return before being killed') }) @@ -49,11 +49,11 @@ function killIdleQuery(targetQuery, cb) { var pidColName = 'procpid' var queryColName = 'current_query' client2.connect( - assert.success(function() { + assert.success(function () { helper.versionGTE( client2, 90200, - assert.success(function(isGreater) { + assert.success(function (isGreater) { if (isGreater) { pidColName = 'pid' queryColName = 'query' @@ -69,7 +69,7 @@ function killIdleQuery(targetQuery, cb) { client2.query( killIdleQuery, [targetQuery], - assert.calls(function(err, res) { + assert.calls(function (err, res) { assert.ifError(err) assert.equal(res.rows.length, 1) client2.end(cb) @@ -82,13 +82,13 @@ function killIdleQuery(targetQuery, cb) { ) } -suite.test('query killed during query execution of prepared statement', function(done) { +suite.test('query killed during query execution of prepared statement', function (done) { if (helper.args.native) { return done() } var client = new Client(helper.args) client.connect( - assert.success(function() { + assert.success(function () { var sleepQuery = 'select pg_sleep($1)' const queryConfig = { @@ -102,20 +102,20 @@ suite.test('query killed during query execution of prepared statement', function var query1 = client.query( new Query(queryConfig), - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert.equal(err.message, 'terminating connection due to administrator command') }) ) - query1.on('error', function(err) { + query1.on('error', function (err) { assert.fail('Prepared statement should not emit error') }) - query1.on('row', function(row) { + query1.on('row', function (row) { assert.fail('Prepared statement should not emit row') }) - query1.on('end', function(err) { + query1.on('end', function (err) { assert.fail('Prepared statement when executed should not return before being killed') }) diff --git a/packages/pg/test/integration/client/query-error-handling-tests.js b/packages/pg/test/integration/client/query-error-handling-tests.js index 94891bf32..34eab8f65 100644 --- a/packages/pg/test/integration/client/query-error-handling-tests.js +++ b/packages/pg/test/integration/client/query-error-handling-tests.js @@ -3,10 +3,10 @@ var helper = require('./test-helper') var util = require('util') var Query = helper.pg.Query -test('error during query execution', function() { +test('error during query execution', function () { var client = new Client(helper.args) client.connect( - assert.success(function() { + assert.success(function () { var queryText = 'select pg_sleep(10)' var sleepQuery = new Query(queryText) var pidColName = 'procpid' @@ -14,14 +14,14 @@ test('error during query execution', function() { helper.versionGTE( client, 90200, - assert.success(function(isGreater) { + assert.success(function (isGreater) { if (isGreater) { pidColName = 'pid' queryColName = 'query' } var query1 = client.query( sleepQuery, - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(err) client.end() }) @@ -29,18 +29,18 @@ test('error during query execution', function() { //ensure query1 does not emit an 'end' event //because it was killed and received an error //https://github.com/brianc/node-postgres/issues/547 - query1.on('end', function() { + query1.on('end', function () { assert.fail('Query with an error should not emit "end" event') }) - setTimeout(function() { + setTimeout(function () { var client2 = new Client(helper.args) client2.connect( - assert.success(function() { + assert.success(function () { var killIdleQuery = `SELECT ${pidColName}, (SELECT pg_cancel_backend(${pidColName})) AS killed FROM pg_stat_activity WHERE ${queryColName} LIKE $1` client2.query( killIdleQuery, [queryText], - assert.calls(function(err, res) { + assert.calls(function (err, res) { assert.ifError(err) assert(res.rows.length > 0) client2.end() @@ -60,20 +60,20 @@ if (helper.config.native) { return } -test('9.3 column error fields', function() { +test('9.3 column error fields', function () { var client = new Client(helper.args) client.connect( - assert.success(function() { + assert.success(function () { helper.versionGTE( client, 90300, - assert.success(function(isGreater) { + assert.success(function (isGreater) { if (!isGreater) { return client.end() } client.query('CREATE TEMP TABLE column_err_test(a int NOT NULL)') - client.query('INSERT INTO column_err_test(a) VALUES (NULL)', function(err) { + client.query('INSERT INTO column_err_test(a) VALUES (NULL)', function (err) { assert.equal(err.severity, 'ERROR') assert.equal(err.code, '23502') assert.equal(err.table, 'column_err_test') @@ -86,14 +86,14 @@ test('9.3 column error fields', function() { ) }) -test('9.3 constraint error fields', function() { +test('9.3 constraint error fields', function () { var client = new Client(helper.args) client.connect( - assert.success(function() { + assert.success(function () { helper.versionGTE( client, 90300, - assert.success(function(isGreater) { + assert.success(function (isGreater) { if (!isGreater) { console.log('skip 9.3 error field on older versions of postgres') return client.end() @@ -101,7 +101,7 @@ test('9.3 constraint error fields', function() { client.query('CREATE TEMP TABLE constraint_err_test(a int PRIMARY KEY)') client.query('INSERT INTO constraint_err_test(a) VALUES (1)') - client.query('INSERT INTO constraint_err_test(a) VALUES (1)', function(err) { + client.query('INSERT INTO constraint_err_test(a) VALUES (1)', function (err) { assert.equal(err.severity, 'ERROR') assert.equal(err.code, '23505') assert.equal(err.table, 'constraint_err_test') diff --git a/packages/pg/test/integration/client/result-metadata-tests.js b/packages/pg/test/integration/client/result-metadata-tests.js index 352cce194..66d9ac4ae 100644 --- a/packages/pg/test/integration/client/result-metadata-tests.js +++ b/packages/pg/test/integration/client/result-metadata-tests.js @@ -3,32 +3,32 @@ var helper = require('./test-helper') var pg = helper.pg const pool = new pg.Pool() -new helper.Suite().test('should return insert metadata', function() { +new helper.Suite().test('should return insert metadata', function () { pool.connect( - assert.calls(function(err, client, done) { + assert.calls(function (err, client, done) { assert(!err) helper.versionGTE( client, 90000, - assert.success(function(hasRowCount) { + assert.success(function (hasRowCount) { client.query( 'CREATE TEMP TABLE zugzug(name varchar(10))', - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) assert.equal(result.oid, null) assert.equal(result.command, 'CREATE') var q = client.query( "INSERT INTO zugzug(name) VALUES('more work?')", - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) assert.equal(result.command, 'INSERT') assert.equal(result.rowCount, 1) client.query( 'SELECT * FROM zugzug', - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) if (hasRowCount) assert.equal(result.rowCount, 1) assert.equal(result.command, 'SELECT') diff --git a/packages/pg/test/integration/client/results-as-array-tests.js b/packages/pg/test/integration/client/results-as-array-tests.js index 6b77ed5e6..5ebb2a9d5 100644 --- a/packages/pg/test/integration/client/results-as-array-tests.js +++ b/packages/pg/test/integration/client/results-as-array-tests.js @@ -6,9 +6,9 @@ var Client = helper.Client var conInfo = helper.config -test('returns results as array', function() { +test('returns results as array', function () { var client = new Client(conInfo) - var checkRow = function(row) { + var checkRow = function (row) { assert(util.isArray(row), 'row should be an array') assert.equal(row.length, 4) assert.equal(row[0].getFullYear(), new Date().getFullYear()) @@ -17,7 +17,7 @@ test('returns results as array', function() { assert.strictEqual(row[3], null) } client.connect( - assert.success(function() { + assert.success(function () { var config = { text: 'SELECT NOW(), 1::int, $1::text, null', values: ['hai'], @@ -25,7 +25,7 @@ test('returns results as array', function() { } var query = client.query( config, - assert.success(function(result) { + assert.success(function (result) { assert.equal(result.rows.length, 1) checkRow(result.rows[0]) client.end() diff --git a/packages/pg/test/integration/client/row-description-on-results-tests.js b/packages/pg/test/integration/client/row-description-on-results-tests.js index 52966148d..688b96e6c 100644 --- a/packages/pg/test/integration/client/row-description-on-results-tests.js +++ b/packages/pg/test/integration/client/row-description-on-results-tests.js @@ -5,7 +5,7 @@ var Client = helper.Client var conInfo = helper.config -var checkResult = function(result) { +var checkResult = function (result) { assert(result.fields) assert.equal(result.fields.length, 3) var fields = result.fields @@ -17,14 +17,14 @@ var checkResult = function(result) { assert.equal(fields[2].dataTypeID, 25) } -test('row descriptions on result object', function() { +test('row descriptions on result object', function () { var client = new Client(conInfo) client.connect( - assert.success(function() { + assert.success(function () { client.query( 'SELECT NOW() as now, 1::int as num, $1::text as texty', ['hello'], - assert.success(function(result) { + assert.success(function (result) { checkResult(result) client.end() }) @@ -33,14 +33,14 @@ test('row descriptions on result object', function() { ) }) -test('row description on no rows', function() { +test('row description on no rows', function () { var client = new Client(conInfo) client.connect( - assert.success(function() { + assert.success(function () { client.query( 'SELECT NOW() as now, 1::int as num, $1::text as texty LIMIT 0', ['hello'], - assert.success(function(result) { + assert.success(function (result) { checkResult(result) client.end() }) diff --git a/packages/pg/test/integration/client/simple-query-tests.js b/packages/pg/test/integration/client/simple-query-tests.js index e3071b837..d22d74742 100644 --- a/packages/pg/test/integration/client/simple-query-tests.js +++ b/packages/pg/test/integration/client/simple-query-tests.js @@ -3,7 +3,7 @@ var helper = require('./test-helper') var Query = helper.pg.Query // before running this test make sure you run the script create-test-tables -test('simple query interface', function() { +test('simple query interface', function () { var client = helper.client() var query = client.query(new Query('select name from person order by name collate "C"')) @@ -11,12 +11,12 @@ test('simple query interface', function() { client.on('drain', client.end.bind(client)) var rows = [] - query.on('row', function(row, result) { + query.on('row', function (row, result) { assert.ok(result) rows.push(row['name']) }) - query.once('row', function(row) { - test('Can iterate through columns', function() { + query.once('row', function (row) { + test('Can iterate through columns', function () { var columnCount = 0 for (var column in row) { columnCount++ @@ -31,18 +31,18 @@ test('simple query interface', function() { }) }) - assert.emits(query, 'end', function() { - test('returned right number of rows', function() { + assert.emits(query, 'end', function () { + test('returned right number of rows', function () { assert.lengthIs(rows, 26) }) - test('row ordering', function() { + test('row ordering', function () { assert.equal(rows[0], 'Aaron') assert.equal(rows[25], 'Zanzabar') }) }) }) -test('prepared statements do not mutate params', function() { +test('prepared statements do not mutate params', function () { var client = helper.client() var params = [1] @@ -54,12 +54,12 @@ test('prepared statements do not mutate params', function() { client.on('drain', client.end.bind(client)) const rows = [] - query.on('row', function(row, result) { + query.on('row', function (row, result) { assert.ok(result) rows.push(row) }) - query.on('end', function(result) { + query.on('end', function (result) { assert.lengthIs(rows, 26, 'result returned wrong number of rows') assert.lengthIs(rows, result.rowCount) assert.equal(rows[0].name, 'Aaron') @@ -67,30 +67,30 @@ test('prepared statements do not mutate params', function() { }) }) -test('multiple simple queries', function() { +test('multiple simple queries', function () { var client = helper.client() client.query({ text: "create temp table bang(id serial, name varchar(5));insert into bang(name) VALUES('boom');" }) client.query("insert into bang(name) VALUES ('yes');") var query = client.query(new Query('select name from bang')) - assert.emits(query, 'row', function(row) { + assert.emits(query, 'row', function (row) { assert.equal(row['name'], 'boom') - assert.emits(query, 'row', function(row) { + assert.emits(query, 'row', function (row) { assert.equal(row['name'], 'yes') }) }) client.on('drain', client.end.bind(client)) }) -test('multiple select statements', function() { +test('multiple select statements', function () { var client = helper.client() client.query( 'create temp table boom(age integer); insert into boom(age) values(1); insert into boom(age) values(2); insert into boom(age) values(3)' ) client.query({ text: "create temp table bang(name varchar(5)); insert into bang(name) values('zoom');" }) var result = client.query(new Query({ text: 'select age from boom where age < 2; select name from bang' })) - assert.emits(result, 'row', function(row) { + assert.emits(result, 'row', function (row) { assert.strictEqual(row['age'], 1) - assert.emits(result, 'row', function(row) { + assert.emits(result, 'row', function (row) { assert.strictEqual(row['name'], 'zoom') }) }) diff --git a/packages/pg/test/integration/client/ssl-tests.js b/packages/pg/test/integration/client/ssl-tests.js index 1e544bf56..1d3c5015b 100644 --- a/packages/pg/test/integration/client/ssl-tests.js +++ b/packages/pg/test/integration/client/ssl-tests.js @@ -1,18 +1,18 @@ 'use strict' var pg = require(__dirname + '/../../../lib') var config = require(__dirname + '/test-helper').config -test('can connect with ssl', function() { +test('can connect with ssl', function () { return false config.ssl = { rejectUnauthorized: false, } pg.connect( config, - assert.success(function(client) { + assert.success(function (client) { return false client.query( 'SELECT NOW()', - assert.success(function() { + assert.success(function () { pg.end() }) ) diff --git a/packages/pg/test/integration/client/statement_timeout-tests.js b/packages/pg/test/integration/client/statement_timeout-tests.js index b59cb51c0..e0898ccee 100644 --- a/packages/pg/test/integration/client/statement_timeout-tests.js +++ b/packages/pg/test/integration/client/statement_timeout-tests.js @@ -13,10 +13,10 @@ function getConInfo(override) { function getStatementTimeout(conf, cb) { var client = new Client(conf) client.connect( - assert.success(function() { + assert.success(function () { client.query( 'SHOW statement_timeout', - assert.success(function(res) { + assert.success(function (res) { var statementTimeout = res.rows[0].statement_timeout cb(statementTimeout) client.end() @@ -28,52 +28,52 @@ function getStatementTimeout(conf, cb) { if (!helper.args.native) { // statement_timeout is not supported with the native client - suite.test('No default statement_timeout ', function(done) { + suite.test('No default statement_timeout ', function (done) { getConInfo() - getStatementTimeout({}, function(res) { + getStatementTimeout({}, function (res) { assert.strictEqual(res, '0') // 0 = no timeout done() }) }) - suite.test('statement_timeout integer is used', function(done) { + suite.test('statement_timeout integer is used', function (done) { var conf = getConInfo({ statement_timeout: 3000, }) - getStatementTimeout(conf, function(res) { + getStatementTimeout(conf, function (res) { assert.strictEqual(res, '3s') done() }) }) - suite.test('statement_timeout float is used', function(done) { + suite.test('statement_timeout float is used', function (done) { var conf = getConInfo({ statement_timeout: 3000.7, }) - getStatementTimeout(conf, function(res) { + getStatementTimeout(conf, function (res) { assert.strictEqual(res, '3s') done() }) }) - suite.test('statement_timeout string is used', function(done) { + suite.test('statement_timeout string is used', function (done) { var conf = getConInfo({ statement_timeout: '3000', }) - getStatementTimeout(conf, function(res) { + getStatementTimeout(conf, function (res) { assert.strictEqual(res, '3s') done() }) }) - suite.test('statement_timeout actually cancels long running queries', function(done) { + suite.test('statement_timeout actually cancels long running queries', function (done) { var conf = getConInfo({ statement_timeout: '10', // 10ms to keep tests running fast }) var client = new Client(conf) client.connect( - assert.success(function() { - client.query('SELECT pg_sleep( 1 )', function(error) { + assert.success(function () { + client.query('SELECT pg_sleep( 1 )', function (error) { client.end() assert.strictEqual(error.code, '57014') // query_cancelled done() diff --git a/packages/pg/test/integration/client/timezone-tests.js b/packages/pg/test/integration/client/timezone-tests.js index aa3f3442f..c9f6a8c83 100644 --- a/packages/pg/test/integration/client/timezone-tests.js +++ b/packages/pg/test/integration/client/timezone-tests.js @@ -10,19 +10,19 @@ var date = new Date() const pool = new helper.pg.Pool() const suite = new helper.Suite() -pool.connect(function(err, client, done) { +pool.connect(function (err, client, done) { assert(!err) - suite.test('timestamp without time zone', function(cb) { - client.query('SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS "val"', [date], function(err, result) { + suite.test('timestamp without time zone', function (cb) { + client.query('SELECT CAST($1 AS TIMESTAMP WITHOUT TIME ZONE) AS "val"', [date], function (err, result) { assert(!err) assert.equal(result.rows[0].val.getTime(), date.getTime()) cb() }) }) - suite.test('timestamp with time zone', function(cb) { - client.query('SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS "val"', [date], function(err, result) { + suite.test('timestamp with time zone', function (cb) { + client.query('SELECT CAST($1 AS TIMESTAMP WITH TIME ZONE) AS "val"', [date], function (err, result) { assert(!err) assert.equal(result.rows[0].val.getTime(), date.getTime()) diff --git a/packages/pg/test/integration/client/transaction-tests.js b/packages/pg/test/integration/client/transaction-tests.js index f227da720..18f8ff095 100644 --- a/packages/pg/test/integration/client/transaction-tests.js +++ b/packages/pg/test/integration/client/transaction-tests.js @@ -5,7 +5,7 @@ const pg = helper.pg const client = new pg.Client() client.connect( - assert.success(function() { + assert.success(function () { client.query('begin') var getZed = { @@ -13,10 +13,10 @@ client.connect( values: ['Zed'], } - suite.test('name should not exist in the database', function(done) { + suite.test('name should not exist in the database', function (done) { client.query( getZed, - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) assert.empty(result.rows) done() @@ -28,17 +28,17 @@ client.connect( client.query( 'INSERT INTO person(name, age) VALUES($1, $2)', ['Zed', 270], - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) done() }) ) }) - suite.test('name should exist in the database', function(done) { + suite.test('name should exist in the database', function (done) { client.query( getZed, - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) assert.equal(result.rows[0].name, 'Zed') done() @@ -50,10 +50,10 @@ client.connect( client.query('rollback', done) }) - suite.test('name should not exist in the database', function(done) { + suite.test('name should not exist in the database', function (done) { client.query( getZed, - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) assert.empty(result.rows) client.end(done) @@ -63,10 +63,10 @@ client.connect( }) ) -suite.test('gh#36', function(cb) { +suite.test('gh#36', function (cb) { const pool = new pg.Pool() pool.connect( - assert.success(function(client, done) { + assert.success(function (client, done) { client.query('BEGIN') client.query( { @@ -74,7 +74,7 @@ suite.test('gh#36', function(cb) { text: 'SELECT $1::INTEGER', values: [0], }, - assert.calls(function(err, result) { + assert.calls(function (err, result) { if (err) throw err assert.equal(result.rows.length, 1) }) @@ -85,12 +85,12 @@ suite.test('gh#36', function(cb) { text: 'SELECT $1::INTEGER', values: [0], }, - assert.calls(function(err, result) { + assert.calls(function (err, result) { if (err) throw err assert.equal(result.rows.length, 1) }) ) - client.query('COMMIT', function() { + client.query('COMMIT', function () { done() pool.end(cb) }) diff --git a/packages/pg/test/integration/client/type-coercion-tests.js b/packages/pg/test/integration/client/type-coercion-tests.js index d2be87b87..96f57b08c 100644 --- a/packages/pg/test/integration/client/type-coercion-tests.js +++ b/packages/pg/test/integration/client/type-coercion-tests.js @@ -4,21 +4,21 @@ var pg = helper.pg var sink const suite = new helper.Suite() -var testForTypeCoercion = function(type) { +var testForTypeCoercion = function (type) { const pool = new pg.Pool() suite.test(`test type coercion ${type.name}`, (cb) => { - pool.connect(function(err, client, done) { + pool.connect(function (err, client, done) { assert(!err) client.query( 'create temp table test_type(col ' + type.name + ')', - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) - type.values.forEach(function(val) { + type.values.forEach(function (val) { var insertQuery = client.query( 'insert into test_type(col) VALUES($1)', [val], - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) }) ) @@ -30,7 +30,7 @@ var testForTypeCoercion = function(type) { }) ) - query.on('error', function(err) { + query.on('error', function (err) { console.log(err) throw err }) @@ -38,7 +38,7 @@ var testForTypeCoercion = function(type) { assert.emits( query, 'row', - function(row) { + function (row) { var expected = val + ' (' + typeof val + ')' var returned = row.col + ' (' + typeof row.col + ')' assert.strictEqual(row.col, val, 'expected ' + type.name + ' of ' + expected + ' but got ' + returned) @@ -49,7 +49,7 @@ var testForTypeCoercion = function(type) { client.query('delete from test_type') }) - client.query('drop table test_type', function() { + client.query('drop table test_type', function () { done() pool.end(cb) }) @@ -131,18 +131,18 @@ var types = [ // ignore some tests in binary mode if (helper.config.binary) { - types = types.filter(function(type) { + types = types.filter(function (type) { return !(type.name in { real: 1, timetz: 1, time: 1, numeric: 1, bigint: 1 }) }) } var valueCount = 0 -types.forEach(function(type) { +types.forEach(function (type) { testForTypeCoercion(type) }) -suite.test('timestampz round trip', function(cb) { +suite.test('timestampz round trip', function (cb) { var now = new Date() var client = helper.client() client.query('create temp table date_tests(name varchar(10), tstz timestamptz(3))') @@ -159,7 +159,7 @@ suite.test('timestampz round trip', function(cb) { }) ) - assert.emits(result, 'row', function(row) { + assert.emits(result, 'row', function (row) { var date = row.tstz assert.equal(date.getYear(), now.getYear()) assert.equal(date.getMonth(), now.getMonth()) @@ -178,16 +178,16 @@ suite.test('timestampz round trip', function(cb) { suite.test('selecting nulls', (cb) => { const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, done) { + assert.calls(function (err, client, done) { assert.ifError(err) client.query( 'select null as res;', - assert.calls(function(err, res) { + assert.calls(function (err, res) { assert(!err) assert.strictEqual(res.rows[0].res, null) }) ) - client.query('select 7 <> $1 as res;', [null], function(err, res) { + client.query('select 7 <> $1 as res;', [null], function (err, res) { assert(!err) assert.strictEqual(res.rows[0].res, null) done() @@ -197,7 +197,7 @@ suite.test('selecting nulls', (cb) => { ) }) -suite.test('date range extremes', function(done) { +suite.test('date range extremes', function (done) { var client = helper.client() // Set the server timeszone to the same as used for the test, @@ -206,7 +206,7 @@ suite.test('date range extremes', function(done) { // in the case of "275760-09-13 00:00:00 GMT" the timevalue overflows. client.query( 'SET TIMEZONE TO GMT', - assert.success(function(res) { + assert.success(function (res) { // PostgreSQL supports date range of 4713 BCE to 294276 CE // http://www.postgresql.org/docs/9.2/static/datatype-datetime.html // ECMAScript supports date range of Apr 20 271821 BCE to Sep 13 275760 CE @@ -214,7 +214,7 @@ suite.test('date range extremes', function(done) { client.query( 'SELECT $1::TIMESTAMPTZ as when', ['275760-09-13 00:00:00 GMT'], - assert.success(function(res) { + assert.success(function (res) { assert.equal(res.rows[0].when.getFullYear(), 275760) }) ) @@ -222,7 +222,7 @@ suite.test('date range extremes', function(done) { client.query( 'SELECT $1::TIMESTAMPTZ as when', ['4713-12-31 12:31:59 BC GMT'], - assert.success(function(res) { + assert.success(function (res) { assert.equal(res.rows[0].when.getFullYear(), -4712) }) ) @@ -230,7 +230,7 @@ suite.test('date range extremes', function(done) { client.query( 'SELECT $1::TIMESTAMPTZ as when', ['275760-09-13 00:00:00 -15:00'], - assert.success(function(res) { + assert.success(function (res) { assert(isNaN(res.rows[0].when.getTime())) }) ) diff --git a/packages/pg/test/integration/client/type-parser-override-tests.js b/packages/pg/test/integration/client/type-parser-override-tests.js index c55aba3a3..42c3dafba 100644 --- a/packages/pg/test/integration/client/type-parser-override-tests.js +++ b/packages/pg/test/integration/client/type-parser-override-tests.js @@ -7,7 +7,7 @@ function testTypeParser(client, expectedResult, done) { client.query('INSERT INTO parserOverrideTest(id) VALUES ($1)', [boolValue]) client.query( 'SELECT * FROM parserOverrideTest', - assert.success(function(result) { + assert.success(function (result) { assert.equal(result.rows[0].id, expectedResult) done() }) @@ -16,21 +16,21 @@ function testTypeParser(client, expectedResult, done) { const pool = new helper.pg.Pool(helper.config) pool.connect( - assert.success(function(client1, done1) { + assert.success(function (client1, done1) { pool.connect( - assert.success(function(client2, done2) { + assert.success(function (client2, done2) { var boolTypeOID = 16 - client1.setTypeParser(boolTypeOID, function() { + client1.setTypeParser(boolTypeOID, function () { return 'first client' }) - client2.setTypeParser(boolTypeOID, function() { + client2.setTypeParser(boolTypeOID, function () { return 'second client' }) - client1.setTypeParser(boolTypeOID, 'binary', function() { + client1.setTypeParser(boolTypeOID, 'binary', function () { return 'first client binary' }) - client2.setTypeParser(boolTypeOID, 'binary', function() { + client2.setTypeParser(boolTypeOID, 'binary', function () { return 'second client binary' }) diff --git a/packages/pg/test/integration/connection-pool/error-tests.js b/packages/pg/test/integration/connection-pool/error-tests.js index 143e694d6..f3f9cdcaa 100644 --- a/packages/pg/test/integration/connection-pool/error-tests.js +++ b/packages/pg/test/integration/connection-pool/error-tests.js @@ -14,15 +14,15 @@ suite.test('errors emitted on checked-out clients', (cb) => { const pool = new pg.Pool({ max: 2 }) // get first client pool.connect( - assert.success(function(client, done) { - client.query('SELECT NOW()', function() { + assert.success(function (client, done) { + client.query('SELECT NOW()', function () { pool.connect( - assert.success(function(client2, done2) { + assert.success(function (client2, done2) { var pidColName = 'procpid' helper.versionGTE( client2, 90200, - assert.success(function(isGreater) { + assert.success(function (isGreater) { var killIdleQuery = 'SELECT pid, (SELECT pg_terminate_backend(pid)) AS killed FROM pg_stat_activity WHERE state = $1' var params = ['idle'] @@ -42,7 +42,7 @@ suite.test('errors emitted on checked-out clients', (cb) => { client2.query( killIdleQuery, params, - assert.success(function(res) { + assert.success(function (res) { // check to make sure client connection actually was killed // return client2 to the pool done2() diff --git a/packages/pg/test/integration/connection-pool/idle-timeout-tests.js b/packages/pg/test/integration/connection-pool/idle-timeout-tests.js index ca2a24447..f36b6938e 100644 --- a/packages/pg/test/integration/connection-pool/idle-timeout-tests.js +++ b/packages/pg/test/integration/connection-pool/idle-timeout-tests.js @@ -1,11 +1,11 @@ 'use strict' var helper = require('./test-helper') -new helper.Suite().test('idle timeout', function() { +new helper.Suite().test('idle timeout', function () { const config = Object.assign({}, helper.config, { idleTimeoutMillis: 50 }) const pool = new helper.pg.Pool(config) pool.connect( - assert.calls(function(err, client, done) { + assert.calls(function (err, client, done) { assert(!err) client.query('SELECT NOW()') done() diff --git a/packages/pg/test/integration/connection-pool/native-instance-tests.js b/packages/pg/test/integration/connection-pool/native-instance-tests.js index 49084828d..a981503e8 100644 --- a/packages/pg/test/integration/connection-pool/native-instance-tests.js +++ b/packages/pg/test/integration/connection-pool/native-instance-tests.js @@ -6,7 +6,7 @@ var native = helper.args.native var pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, done) { + assert.calls(function (err, client, done) { if (native) { assert(client.native) } else { diff --git a/packages/pg/test/integration/connection-pool/test-helper.js b/packages/pg/test/integration/connection-pool/test-helper.js index 854d74c84..97a177a62 100644 --- a/packages/pg/test/integration/connection-pool/test-helper.js +++ b/packages/pg/test/integration/connection-pool/test-helper.js @@ -3,19 +3,19 @@ var helper = require('./../test-helper') const suite = new helper.Suite() -helper.testPoolSize = function(max) { +helper.testPoolSize = function (max) { suite.test(`test ${max} queries executed on a pool rapidly`, (cb) => { const pool = new helper.pg.Pool({ max: 10 }) - var sink = new helper.Sink(max, function() { + var sink = new helper.Sink(max, function () { pool.end(cb) }) for (var i = 0; i < max; i++) { - pool.connect(function(err, client, done) { + pool.connect(function (err, client, done) { assert(!err) client.query('SELECT * FROM NOW()') - client.query('select generate_series(0, 25)', function(err, result) { + client.query('select generate_series(0, 25)', function (err, result) { assert.equal(result.rows.length, 26) }) var query = client.query('SELECT * FROM NOW()', (err) => { diff --git a/packages/pg/test/integration/connection-pool/yield-support-tests.js b/packages/pg/test/integration/connection-pool/yield-support-tests.js index af7db97a9..00508f5d6 100644 --- a/packages/pg/test/integration/connection-pool/yield-support-tests.js +++ b/packages/pg/test/integration/connection-pool/yield-support-tests.js @@ -5,7 +5,7 @@ var co = require('co') const pool = new helper.pg.Pool() new helper.Suite().test( 'using coroutines works with promises', - co.wrap(function*() { + co.wrap(function* () { var client = yield pool.connect() var res = yield client.query('SELECT $1::text as name', ['foo']) assert.equal(res.rows[0].name, 'foo') diff --git a/packages/pg/test/integration/connection/bound-command-tests.js b/packages/pg/test/integration/connection/bound-command-tests.js index e422fca3d..a707bc4b1 100644 --- a/packages/pg/test/integration/connection/bound-command-tests.js +++ b/packages/pg/test/integration/connection/bound-command-tests.js @@ -2,8 +2,8 @@ var helper = require(__dirname + '/test-helper') // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY -test('flushing once', function() { - helper.connect(function(con) { +test('flushing once', function () { + helper.connect(function (con) { con.parse({ text: 'select * from ids', }) @@ -15,35 +15,35 @@ test('flushing once', function() { assert.emits(con, 'parseComplete') assert.emits(con, 'bindComplete') assert.emits(con, 'dataRow') - assert.emits(con, 'commandComplete', function() { + assert.emits(con, 'commandComplete', function () { con.sync() }) - assert.emits(con, 'readyForQuery', function() { + assert.emits(con, 'readyForQuery', function () { con.end() }) }) }) -test('sending many flushes', function() { - helper.connect(function(con) { - assert.emits(con, 'parseComplete', function() { +test('sending many flushes', function () { + helper.connect(function (con) { + assert.emits(con, 'parseComplete', function () { con.bind() con.flush() }) - assert.emits(con, 'bindComplete', function() { + assert.emits(con, 'bindComplete', function () { con.execute() con.flush() }) - assert.emits(con, 'dataRow', function(msg) { + assert.emits(con, 'dataRow', function (msg) { assert.equal(msg.fields[0], 1) - assert.emits(con, 'dataRow', function(msg) { + assert.emits(con, 'dataRow', function (msg) { assert.equal(msg.fields[0], 2) - assert.emits(con, 'commandComplete', function() { + assert.emits(con, 'commandComplete', function () { con.sync() }) - assert.emits(con, 'readyForQuery', function() { + assert.emits(con, 'readyForQuery', function () { con.end() }) }) diff --git a/packages/pg/test/integration/connection/copy-tests.js b/packages/pg/test/integration/connection/copy-tests.js index 78bcd3c20..1b7d06ed1 100644 --- a/packages/pg/test/integration/connection/copy-tests.js +++ b/packages/pg/test/integration/connection/copy-tests.js @@ -2,16 +2,16 @@ var helper = require(__dirname + '/test-helper') var assert = require('assert') -test('COPY FROM events check', function() { - helper.connect(function(con) { +test('COPY FROM events check', function () { + helper.connect(function (con) { var stdinStream = con.query('COPY person FROM STDIN') - con.on('copyInResponse', function() { + con.on('copyInResponse', function () { con.endCopyFrom() }) assert.emits( con, 'copyInResponse', - function() { + function () { con.endCopyFrom() }, 'backend should emit copyInResponse after COPY FROM query' @@ -19,22 +19,22 @@ test('COPY FROM events check', function() { assert.emits( con, 'commandComplete', - function() { + function () { con.end() }, 'backend should emit commandComplete after COPY FROM stream ends' ) }) }) -test('COPY TO events check', function() { - helper.connect(function(con) { +test('COPY TO events check', function () { + helper.connect(function (con) { var stdoutStream = con.query('COPY person TO STDOUT') - assert.emits(con, 'copyOutResponse', function() {}, 'backend should emit copyOutResponse after COPY TO query') - assert.emits(con, 'copyData', function() {}, 'backend should emit copyData on every data row') + assert.emits(con, 'copyOutResponse', function () {}, 'backend should emit copyOutResponse after COPY TO query') + assert.emits(con, 'copyData', function () {}, 'backend should emit copyData on every data row') assert.emits( con, 'copyDone', - function() { + function () { con.end() }, 'backend should emit copyDone after all data rows' diff --git a/packages/pg/test/integration/connection/notification-tests.js b/packages/pg/test/integration/connection/notification-tests.js index 700fdabae..347b7ee89 100644 --- a/packages/pg/test/integration/connection/notification-tests.js +++ b/packages/pg/test/integration/connection/notification-tests.js @@ -1,12 +1,12 @@ 'use strict' var helper = require(__dirname + '/test-helper') // http://www.postgresql.org/docs/8.3/static/libpq-notify.html -test('recieves notification from same connection with no payload', function() { - helper.connect(function(con) { +test('recieves notification from same connection with no payload', function () { + helper.connect(function (con) { con.query('LISTEN boom') - assert.emits(con, 'readyForQuery', function() { + assert.emits(con, 'readyForQuery', function () { con.query('NOTIFY boom') - assert.emits(con, 'notification', function(msg) { + assert.emits(con, 'notification', function (msg) { assert.equal(msg.payload, '') assert.equal(msg.channel, 'boom') con.end() diff --git a/packages/pg/test/integration/connection/query-tests.js b/packages/pg/test/integration/connection/query-tests.js index 661019558..70c39c322 100644 --- a/packages/pg/test/integration/connection/query-tests.js +++ b/packages/pg/test/integration/connection/query-tests.js @@ -5,20 +5,20 @@ var assert = require('assert') var rows = [] // testing the low level 1-1 mapping api of client to postgres messages // it's cumbersome to use the api this way -test('simple query', function() { - helper.connect(function(con) { +test('simple query', function () { + helper.connect(function (con) { con.query('select * from ids') assert.emits(con, 'dataRow') - con.on('dataRow', function(msg) { + con.on('dataRow', function (msg) { rows.push(msg.fields) }) - assert.emits(con, 'readyForQuery', function() { + assert.emits(con, 'readyForQuery', function () { con.end() }) }) }) -process.on('exit', function() { +process.on('exit', function () { assert.equal(rows.length, 2) assert.equal(rows[0].length, 1) assert.strictEqual(String(rows[0][0]), '1') diff --git a/packages/pg/test/integration/connection/test-helper.js b/packages/pg/test/integration/connection/test-helper.js index ae88bfc4d..ca978af4f 100644 --- a/packages/pg/test/integration/connection/test-helper.js +++ b/packages/pg/test/integration/connection/test-helper.js @@ -3,31 +3,31 @@ var net = require('net') var helper = require(__dirname + '/../test-helper') var Connection = require(__dirname + '/../../../lib/connection') var utils = require(__dirname + '/../../../lib/utils') -var connect = function(callback) { +var connect = function (callback) { var username = helper.args.user var database = helper.args.database var con = new Connection({ stream: new net.Stream() }) - con.on('error', function(error) { + con.on('error', function (error) { console.log(error) throw new Error('Connection error') }) con.connect(helper.args.port || '5432', helper.args.host || 'localhost') - con.once('connect', function() { + con.once('connect', function () { con.startup({ user: username, database: database, }) - con.once('authenticationCleartextPassword', function() { + con.once('authenticationCleartextPassword', function () { con.password(helper.args.password) }) - con.once('authenticationMD5Password', function(msg) { + con.once('authenticationMD5Password', function (msg) { con.password(utils.postgresMd5PasswordHash(helper.args.user, helper.args.password, msg.salt)) }) - con.once('readyForQuery', function() { + con.once('readyForQuery', function () { con.query('create temp table ids(id integer)') - con.once('readyForQuery', function() { + con.once('readyForQuery', function () { con.query('insert into ids(id) values(1); insert into ids(id) values(2);') - con.once('readyForQuery', function() { + con.once('readyForQuery', function () { callback(con) }) }) diff --git a/packages/pg/test/integration/domain-tests.js b/packages/pg/test/integration/domain-tests.js index 6d3f2f71f..ce46eb8a4 100644 --- a/packages/pg/test/integration/domain-tests.js +++ b/packages/pg/test/integration/domain-tests.js @@ -7,11 +7,11 @@ var suite = new helper.Suite() const Pool = helper.pg.Pool -suite.test('no domain', function(cb) { +suite.test('no domain', function (cb) { assert(!process.domain) const pool = new Pool() pool.connect( - assert.success(function(client, done) { + assert.success(function (client, done) { assert(!process.domain) done() pool.end(cb) @@ -19,20 +19,20 @@ suite.test('no domain', function(cb) { ) }) -suite.test('with domain', function(cb) { +suite.test('with domain', function (cb) { assert(!process.domain) const pool = new Pool() var domain = require('domain').create() - domain.run(function() { + domain.run(function () { var startingDomain = process.domain assert(startingDomain) pool.connect( - assert.success(function(client, done) { + assert.success(function (client, done) { assert(process.domain, 'no domain exists in connect callback') assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') var query = client.query( 'SELECT NOW()', - assert.success(function() { + assert.success(function () { assert(process.domain, 'no domain exists in query callback') assert.equal(startingDomain, process.domain, 'domain was lost when checking out a client') done(true) @@ -45,15 +45,15 @@ suite.test('with domain', function(cb) { }) }) -suite.test('error on domain', function(cb) { +suite.test('error on domain', function (cb) { var domain = require('domain').create() const pool = new Pool() - domain.on('error', function() { + domain.on('error', function () { pool.end(cb) }) - domain.run(function() { + domain.run(function () { pool.connect( - assert.success(function(client, done) { + assert.success(function (client, done) { client.query(new Query('SELECT SLDKJFLSKDJF')) client.on('drain', done) }) diff --git a/packages/pg/test/integration/gh-issues/130-tests.js b/packages/pg/test/integration/gh-issues/130-tests.js index 252d75768..8b097b99b 100644 --- a/packages/pg/test/integration/gh-issues/130-tests.js +++ b/packages/pg/test/integration/gh-issues/130-tests.js @@ -5,13 +5,13 @@ var exec = require('child_process').exec helper.pg.defaults.poolIdleTimeout = 1000 const pool = new helper.pg.Pool() -pool.connect(function(err, client, done) { +pool.connect(function (err, client, done) { assert.ifError(err) - client.once('error', function(err) { + client.once('error', function (err) { client.on('error', (err) => {}) done(err) }) - client.query('SELECT pg_backend_pid()', function(err, result) { + client.query('SELECT pg_backend_pid()', function (err, result) { assert.ifError(err) var pid = result.rows[0].pg_backend_pid var psql = 'psql' @@ -20,7 +20,7 @@ pool.connect(function(err, client, done) { if (helper.args.user) psql = psql + ' -U ' + helper.args.user exec( psql + ' -c "select pg_terminate_backend(' + pid + ')" template1', - assert.calls(function(error, stdout, stderr) { + assert.calls(function (error, stdout, stderr) { assert.ifError(error) }) ) diff --git a/packages/pg/test/integration/gh-issues/131-tests.js b/packages/pg/test/integration/gh-issues/131-tests.js index 0ebad8d97..5838067fc 100644 --- a/packages/pg/test/integration/gh-issues/131-tests.js +++ b/packages/pg/test/integration/gh-issues/131-tests.js @@ -4,10 +4,10 @@ var pg = helper.pg var suite = new helper.Suite() -suite.test('parsing array decimal results', function(done) { +suite.test('parsing array decimal results', function (done) { const pool = new pg.Pool() pool.connect( - assert.calls(function(err, client, release) { + assert.calls(function (err, client, release) { assert(!err) client.query('CREATE TEMP TABLE why(names text[], numbors integer[], decimals double precision[])') client @@ -19,7 +19,7 @@ suite.test('parsing array decimal results', function(done) { .on('error', console.log) client.query( 'SELECT decimals FROM why', - assert.success(function(result) { + assert.success(function (result) { assert.lengthIs(result.rows[0].decimals, 3) assert.equal(result.rows[0].decimals[0], 0.1) assert.equal(result.rows[0].decimals[1], 0.05) diff --git a/packages/pg/test/integration/gh-issues/1854-tests.js b/packages/pg/test/integration/gh-issues/1854-tests.js index e63df5c6f..92ac6ec35 100644 --- a/packages/pg/test/integration/gh-issues/1854-tests.js +++ b/packages/pg/test/integration/gh-issues/1854-tests.js @@ -14,7 +14,7 @@ suite.test('Parameter serialization errors should not cause query to hang', (don .connect() .then(() => { const obj = { - toPostgres: function() { + toPostgres: function () { throw expectedErr }, } diff --git a/packages/pg/test/integration/gh-issues/199-tests.js b/packages/pg/test/integration/gh-issues/199-tests.js index dc74963f1..2710020c5 100644 --- a/packages/pg/test/integration/gh-issues/199-tests.js +++ b/packages/pg/test/integration/gh-issues/199-tests.js @@ -12,7 +12,7 @@ ARRAY['xx', 'yy', 'zz'] AS c,\ ARRAY(SELECT n FROM arrtest) AS d,\ ARRAY(SELECT s FROM arrtest) AS e;" -client.query(qText, function(err, result) { +client.query(qText, function (err, result) { if (err) throw err var row = result.rows[0] for (var key in row) { diff --git a/packages/pg/test/integration/gh-issues/507-tests.js b/packages/pg/test/integration/gh-issues/507-tests.js index 958e28241..9c3409199 100644 --- a/packages/pg/test/integration/gh-issues/507-tests.js +++ b/packages/pg/test/integration/gh-issues/507-tests.js @@ -2,13 +2,13 @@ var helper = require(__dirname + '/../test-helper') var pg = helper.pg -new helper.Suite().test('parsing array results', function(cb) { +new helper.Suite().test('parsing array results', function (cb) { const pool = new pg.Pool() pool.connect( - assert.success(function(client, done) { + assert.success(function (client, done) { client.query('CREATE TEMP TABLE test_table(bar integer, "baz\'s" integer)') client.query('INSERT INTO test_table(bar, "baz\'s") VALUES(1, 1), (2, 2)') - client.query('SELECT * FROM test_table', function(err, res) { + client.query('SELECT * FROM test_table', function (err, res) { assert.equal(res.rows[0]["baz's"], 1) assert.equal(res.rows[1]["baz's"], 2) done() diff --git a/packages/pg/test/integration/gh-issues/600-tests.js b/packages/pg/test/integration/gh-issues/600-tests.js index 84a7124bd..af679ee8e 100644 --- a/packages/pg/test/integration/gh-issues/600-tests.js +++ b/packages/pg/test/integration/gh-issues/600-tests.js @@ -45,9 +45,9 @@ function endTransaction(callback) { function doTransaction(callback) { // The transaction runs startTransaction, then all queries, then endTransaction, // no matter if there has been an error in a query in the middle. - startTransaction(function() { - insertDataFoo(function() { - insertDataBar(function() { + startTransaction(function () { + insertDataFoo(function () { + insertDataBar(function () { endTransaction(callback) }) }) @@ -56,17 +56,17 @@ function doTransaction(callback) { var steps = [createTableFoo, createTableBar, doTransaction, insertDataBar] -suite.test('test if query fails', function(done) { +suite.test('test if query fails', function (done) { async.series( steps, - assert.success(function() { + assert.success(function () { db.end() done() }) ) }) -suite.test('test if prepare works but bind fails', function(done) { +suite.test('test if prepare works but bind fails', function (done) { var client = helper.client() var q = { text: 'SELECT $1::int as name', @@ -75,11 +75,11 @@ suite.test('test if prepare works but bind fails', function(done) { } client.query( q, - assert.calls(function(err, res) { + assert.calls(function (err, res) { q.values = [1] client.query( q, - assert.calls(function(err, res) { + assert.calls(function (err, res) { assert.ifError(err) client.end() done() diff --git a/packages/pg/test/integration/gh-issues/675-tests.js b/packages/pg/test/integration/gh-issues/675-tests.js index 31f57589d..2e281ecc6 100644 --- a/packages/pg/test/integration/gh-issues/675-tests.js +++ b/packages/pg/test/integration/gh-issues/675-tests.js @@ -3,22 +3,22 @@ var helper = require('../test-helper') var assert = require('assert') const pool = new helper.pg.Pool() -pool.connect(function(err, client, done) { +pool.connect(function (err, client, done) { if (err) throw err var c = 'CREATE TEMP TABLE posts (body TEXT)' - client.query(c, function(err) { + client.query(c, function (err) { if (err) throw err c = 'INSERT INTO posts (body) VALUES ($1) RETURNING *' var body = Buffer.from('foo') - client.query(c, [body], function(err) { + client.query(c, [body], function (err) { if (err) throw err body = Buffer.from([]) - client.query(c, [body], function(err, res) { + client.query(c, [body], function (err, res) { done() if (err) throw err diff --git a/packages/pg/test/integration/gh-issues/699-tests.js b/packages/pg/test/integration/gh-issues/699-tests.js index 2ce1d0069..c9be63bfa 100644 --- a/packages/pg/test/integration/gh-issues/699-tests.js +++ b/packages/pg/test/integration/gh-issues/699-tests.js @@ -6,16 +6,16 @@ var copyFrom = require('pg-copy-streams').from if (helper.args.native) return const pool = new helper.pg.Pool() -pool.connect(function(err, client, done) { +pool.connect(function (err, client, done) { if (err) throw err var c = 'CREATE TEMP TABLE employee (id integer, fname varchar(400), lname varchar(400))' - client.query(c, function(err) { + client.query(c, function (err) { if (err) throw err var stream = client.query(copyFrom('COPY employee FROM STDIN')) - stream.on('end', function() { + stream.on('end', function () { done() setTimeout(() => { pool.end() diff --git a/packages/pg/test/integration/gh-issues/787-tests.js b/packages/pg/test/integration/gh-issues/787-tests.js index 81fb27705..9a3198f52 100644 --- a/packages/pg/test/integration/gh-issues/787-tests.js +++ b/packages/pg/test/integration/gh-issues/787-tests.js @@ -2,13 +2,13 @@ var helper = require('../test-helper') const pool = new helper.pg.Pool() -pool.connect(function(err, client) { +pool.connect(function (err, client) { var q = { name: 'This is a super long query name just so I can test that an error message is properly spit out to console.error without throwing an exception or anything', text: 'SELECT NOW()', } - client.query(q, function() { + client.query(q, function () { client.end() }) }) diff --git a/packages/pg/test/integration/gh-issues/882-tests.js b/packages/pg/test/integration/gh-issues/882-tests.js index 324de2e6f..4a8ef6474 100644 --- a/packages/pg/test/integration/gh-issues/882-tests.js +++ b/packages/pg/test/integration/gh-issues/882-tests.js @@ -4,6 +4,6 @@ var helper = require('../test-helper') var client = helper.client() client.query({ name: 'foo1', text: null }) client.query({ name: 'foo2', text: ' ' }) -client.query({ name: 'foo3', text: '' }, function(err, res) { +client.query({ name: 'foo3', text: '' }, function (err, res) { client.end() }) diff --git a/packages/pg/test/integration/gh-issues/981-tests.js b/packages/pg/test/integration/gh-issues/981-tests.js index 49ac7916c..998adea3a 100644 --- a/packages/pg/test/integration/gh-issues/981-tests.js +++ b/packages/pg/test/integration/gh-issues/981-tests.js @@ -21,7 +21,7 @@ const nativePool = new native.Pool() const suite = new helper.Suite() suite.test('js pool returns js client', (cb) => { - jsPool.connect(function(err, client, done) { + jsPool.connect(function (err, client, done) { assert(client instanceof JsClient) done() jsPool.end(cb) @@ -29,7 +29,7 @@ suite.test('js pool returns js client', (cb) => { }) suite.test('native pool returns native client', (cb) => { - nativePool.connect(function(err, client, done) { + nativePool.connect(function (err, client, done) { assert(client instanceof NativeClient) done() nativePool.end(cb) diff --git a/packages/pg/test/integration/test-helper.js b/packages/pg/test/integration/test-helper.js index 5a603946d..9b8b58c60 100644 --- a/packages/pg/test/integration/test-helper.js +++ b/packages/pg/test/integration/test-helper.js @@ -8,16 +8,16 @@ if (helper.args.native) { } // creates a client from cli parameters -helper.client = function(cb) { +helper.client = function (cb) { var client = new Client() client.connect(cb) return client } -helper.versionGTE = function(client, testVersion, callback) { +helper.versionGTE = function (client, testVersion, callback) { client.query( 'SHOW server_version_num', - assert.calls(function(err, result) { + assert.calls(function (err, result) { if (err) return callback(err) var version = parseInt(result.rows[0].server_version_num, 10) return callback(null, version >= testVersion) diff --git a/packages/pg/test/native/callback-api-tests.js b/packages/pg/test/native/callback-api-tests.js index d4be9d473..80fdcdf56 100644 --- a/packages/pg/test/native/callback-api-tests.js +++ b/packages/pg/test/native/callback-api-tests.js @@ -4,19 +4,19 @@ var helper = require('./../test-helper') var Client = require('./../../lib/native') const suite = new helper.Suite() -suite.test('fires callback with results', function(done) { +suite.test('fires callback with results', function (done) { var client = new Client(helper.config) client.connect() client.query( 'SELECT 1 as num', - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) assert.equal(result.rows[0].num, 1) assert.strictEqual(result.rowCount, 1) client.query( 'SELECT * FROM person WHERE name = $1', ['Brian'], - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(!err) assert.equal(result.rows[0].name, 'Brian') client.end(done) @@ -26,14 +26,14 @@ suite.test('fires callback with results', function(done) { ) }) -suite.test('preserves domain', function(done) { +suite.test('preserves domain', function (done) { var dom = domain.create() - dom.run(function() { + dom.run(function () { var client = new Client(helper.config) assert.ok(dom === require('domain').active, 'domain is active') client.connect() - client.query('select 1', function() { + client.query('select 1', function () { assert.ok(dom === require('domain').active, 'domain is still active') client.end(done) }) diff --git a/packages/pg/test/native/evented-api-tests.js b/packages/pg/test/native/evented-api-tests.js index 7bed1632a..ba0496eff 100644 --- a/packages/pg/test/native/evented-api-tests.js +++ b/packages/pg/test/native/evented-api-tests.js @@ -3,7 +3,7 @@ var helper = require('../test-helper') var Client = require('../../lib/native') var Query = Client.Query -var setupClient = function() { +var setupClient = function () { var client = new Client(helper.config) client.connect() client.query('CREATE TEMP TABLE boom(name varchar(10), age integer)') @@ -12,22 +12,22 @@ var setupClient = function() { return client } -test('multiple results', function() { - test('queued queries', function() { +test('multiple results', function () { + test('queued queries', function () { var client = setupClient() var q = client.query(new Query('SELECT name FROM BOOM')) - assert.emits(q, 'row', function(row) { + assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Aaron') - assert.emits(q, 'row', function(row) { + assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Brian') }) }) - assert.emits(q, 'end', function() { - test('query with config', function() { + assert.emits(q, 'end', function () { + test('query with config', function () { var q2 = client.query(new Query({ text: 'SELECT 1 as num' })) - assert.emits(q2, 'row', function(row) { + assert.emits(q2, 'row', function (row) { assert.strictEqual(row.num, 1) - assert.emits(q2, 'end', function() { + assert.emits(q2, 'end', function () { client.end() }) }) @@ -36,19 +36,19 @@ test('multiple results', function() { }) }) -test('parameterized queries', function() { - test('with a single string param', function() { +test('parameterized queries', function () { + test('with a single string param', function () { var client = setupClient() var q = client.query(new Query('SELECT * FROM boom WHERE name = $1', ['Aaron'])) - assert.emits(q, 'row', function(row) { + assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Aaron') }) - assert.emits(q, 'end', function() { + assert.emits(q, 'end', function () { client.end() }) }) - test('with object config for query', function() { + test('with object config for query', function () { var client = setupClient() var q = client.query( new Query({ @@ -56,38 +56,38 @@ test('parameterized queries', function() { values: ['Brian'], }) ) - assert.emits(q, 'row', function(row) { + assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Brian') }) - assert.emits(q, 'end', function() { + assert.emits(q, 'end', function () { client.end() }) }) - test('multiple parameters', function() { + test('multiple parameters', function () { var client = setupClient() var q = client.query( new Query('SELECT name FROM boom WHERE name = $1 or name = $2 ORDER BY name COLLATE "C"', ['Aaron', 'Brian']) ) - assert.emits(q, 'row', function(row) { + assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Aaron') - assert.emits(q, 'row', function(row) { + assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Brian') - assert.emits(q, 'end', function() { + assert.emits(q, 'end', function () { client.end() }) }) }) }) - test('integer parameters', function() { + test('integer parameters', function () { var client = setupClient() var q = client.query(new Query('SELECT * FROM boom WHERE age > $1', [27])) - assert.emits(q, 'row', function(row) { + assert.emits(q, 'row', function (row) { assert.equal(row.name, 'Brian') assert.equal(row.age, 28) }) - assert.emits(q, 'end', function() { + assert.emits(q, 'end', function () { client.end() }) }) diff --git a/packages/pg/test/native/stress-tests.js b/packages/pg/test/native/stress-tests.js index c6a8cac88..49904b12a 100644 --- a/packages/pg/test/native/stress-tests.js +++ b/packages/pg/test/native/stress-tests.js @@ -3,48 +3,48 @@ var helper = require(__dirname + '/../test-helper') var Client = require(__dirname + '/../../lib/native') var Query = Client.Query -test('many rows', function() { +test('many rows', function () { var client = new Client(helper.config) client.connect() var q = client.query(new Query('SELECT * FROM person')) var rows = [] - q.on('row', function(row) { + q.on('row', function (row) { rows.push(row) }) - assert.emits(q, 'end', function() { + assert.emits(q, 'end', function () { client.end() assert.lengthIs(rows, 26) }) }) -test('many queries', function() { +test('many queries', function () { var client = new Client(helper.config) client.connect() var count = 0 var expected = 100 for (var i = 0; i < expected; i++) { var q = client.query(new Query('SELECT * FROM person')) - assert.emits(q, 'end', function() { + assert.emits(q, 'end', function () { count++ }) } - assert.emits(client, 'drain', function() { + assert.emits(client, 'drain', function () { client.end() assert.equal(count, expected) }) }) -test('many clients', function() { +test('many clients', function () { var clients = [] for (var i = 0; i < 10; i++) { clients.push(new Client(helper.config)) } - clients.forEach(function(client) { + clients.forEach(function (client) { client.connect() for (var i = 0; i < 20; i++) { client.query('SELECT * FROM person') } - assert.emits(client, 'drain', function() { + assert.emits(client, 'drain', function () { client.end() }) }) diff --git a/packages/pg/test/test-buffers.js b/packages/pg/test/test-buffers.js index 573056bce..9fdd889d4 100644 --- a/packages/pg/test/test-buffers.js +++ b/packages/pg/test/test-buffers.js @@ -3,70 +3,54 @@ require(__dirname + '/test-helper') // http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html var buffers = {} -buffers.readyForQuery = function() { +buffers.readyForQuery = function () { return new BufferList().add(Buffer.from('I')).join(true, 'Z') } -buffers.authenticationOk = function() { +buffers.authenticationOk = function () { return new BufferList().addInt32(0).join(true, 'R') } -buffers.authenticationCleartextPassword = function() { +buffers.authenticationCleartextPassword = function () { return new BufferList().addInt32(3).join(true, 'R') } -buffers.authenticationMD5Password = function() { +buffers.authenticationMD5Password = function () { return new BufferList() .addInt32(5) .add(Buffer.from([1, 2, 3, 4])) .join(true, 'R') } -buffers.authenticationSASL = function() { - return new BufferList() - .addInt32(10) - .addCString('SCRAM-SHA-256') - .addCString('') - .join(true, 'R') +buffers.authenticationSASL = function () { + return new BufferList().addInt32(10).addCString('SCRAM-SHA-256').addCString('').join(true, 'R') } -buffers.authenticationSASLContinue = function() { - return new BufferList() - .addInt32(11) - .addString('data') - .join(true, 'R') +buffers.authenticationSASLContinue = function () { + return new BufferList().addInt32(11).addString('data').join(true, 'R') } -buffers.authenticationSASLFinal = function() { - return new BufferList() - .addInt32(12) - .addString('data') - .join(true, 'R') +buffers.authenticationSASLFinal = function () { + return new BufferList().addInt32(12).addString('data').join(true, 'R') } -buffers.parameterStatus = function(name, value) { - return new BufferList() - .addCString(name) - .addCString(value) - .join(true, 'S') +buffers.parameterStatus = function (name, value) { + return new BufferList().addCString(name).addCString(value).join(true, 'S') } -buffers.backendKeyData = function(processID, secretKey) { - return new BufferList() - .addInt32(processID) - .addInt32(secretKey) - .join(true, 'K') +buffers.backendKeyData = function (processID, secretKey) { + return new BufferList().addInt32(processID).addInt32(secretKey).join(true, 'K') } -buffers.commandComplete = function(string) { +buffers.commandComplete = function (string) { return new BufferList().addCString(string).join(true, 'C') } -buffers.rowDescription = function(fields) { +buffers.rowDescription = function (fields) { fields = fields || [] var buf = new BufferList() buf.addInt16(fields.length) - fields.forEach(function(field) { + fields.forEach(function (field) { buf .addCString(field.name) .addInt32(field.tableID || 0) @@ -79,11 +63,11 @@ buffers.rowDescription = function(fields) { return buf.join(true, 'T') } -buffers.dataRow = function(columns) { +buffers.dataRow = function (columns) { columns = columns || [] var buf = new BufferList() buf.addInt16(columns.length) - columns.forEach(function(col) { + columns.forEach(function (col) { if (col == null) { buf.addInt32(-1) } else { @@ -95,45 +79,41 @@ buffers.dataRow = function(columns) { return buf.join(true, 'D') } -buffers.error = function(fields) { +buffers.error = function (fields) { return errorOrNotice(fields).join(true, 'E') } -buffers.notice = function(fields) { +buffers.notice = function (fields) { return errorOrNotice(fields).join(true, 'N') } -var errorOrNotice = function(fields) { +var errorOrNotice = function (fields) { fields = fields || [] var buf = new BufferList() - fields.forEach(function(field) { + fields.forEach(function (field) { buf.addChar(field.type) buf.addCString(field.value) }) return buf.add(Buffer.from([0])) // terminator } -buffers.parseComplete = function() { +buffers.parseComplete = function () { return new BufferList().join(true, '1') } -buffers.bindComplete = function() { +buffers.bindComplete = function () { return new BufferList().join(true, '2') } -buffers.notification = function(id, channel, payload) { - return new BufferList() - .addInt32(id) - .addCString(channel) - .addCString(payload) - .join(true, 'A') +buffers.notification = function (id, channel, payload) { + return new BufferList().addInt32(id).addCString(channel).addCString(payload).join(true, 'A') } -buffers.emptyQuery = function() { +buffers.emptyQuery = function () { return new BufferList().join(true, 'I') } -buffers.portalSuspended = function() { +buffers.portalSuspended = function () { return new BufferList().join(true, 's') } diff --git a/packages/pg/test/test-helper.js b/packages/pg/test/test-helper.js index 0fd6b222e..8159e387c 100644 --- a/packages/pg/test/test-helper.js +++ b/packages/pg/test/test-helper.js @@ -12,7 +12,7 @@ var Connection = require('./../lib/connection') global.Client = require('./../lib').Client -process.on('uncaughtException', function(d) { +process.on('uncaughtException', function (d) { if ('stack' in d && 'message' in d) { console.log('Message: ' + d.message) console.log(d.stack) @@ -22,21 +22,21 @@ process.on('uncaughtException', function(d) { process.exit(-1) }) -assert.same = function(actual, expected) { +assert.same = function (actual, expected) { for (var key in expected) { assert.equal(actual[key], expected[key]) } } -assert.emits = function(item, eventName, callback, message) { +assert.emits = function (item, eventName, callback, message) { var called = false - var id = setTimeout(function() { - test("Should have called '" + eventName + "' event", function() { + var id = setTimeout(function () { + test("Should have called '" + eventName + "' event", function () { assert.ok(called, message || "Expected '" + eventName + "' to be called.") }) }, 5000) - item.once(eventName, function() { + item.once(eventName, function () { if (eventName === 'error') { // belt and braces test to ensure all error events return an error assert.ok( @@ -53,7 +53,7 @@ assert.emits = function(item, eventName, callback, message) { }) } -assert.UTCDate = function(actual, year, month, day, hours, min, sec, milisecond) { +assert.UTCDate = function (actual, year, month, day, hours, min, sec, milisecond) { var actualYear = actual.getUTCFullYear() assert.equal(actualYear, year, 'expected year ' + year + ' but got ' + actualYear) @@ -76,7 +76,7 @@ assert.UTCDate = function(actual, year, month, day, hours, min, sec, milisecond) assert.equal(actualMili, milisecond, 'expected milisecond ' + milisecond + ' but got ' + actualMili) } -assert.equalBuffers = function(actual, expected) { +assert.equalBuffers = function (actual, expected) { if (actual.length != expected.length) { spit(actual, expected) assert.equal(actual.length, expected.length) @@ -89,13 +89,13 @@ assert.equalBuffers = function(actual, expected) { } } -assert.empty = function(actual) { +assert.empty = function (actual) { assert.lengthIs(actual, 0) } -assert.success = function(callback) { +assert.success = function (callback) { if (callback.length === 1 || callback.length === 0) { - return assert.calls(function(err, arg) { + return assert.calls(function (err, arg) { if (err) { console.log(err) } @@ -103,7 +103,7 @@ assert.success = function(callback) { callback(arg) }) } else if (callback.length === 2) { - return assert.calls(function(err, arg1, arg2) { + return assert.calls(function (err, arg1, arg2) { if (err) { console.log(err) } @@ -115,7 +115,7 @@ assert.success = function(callback) { } } -assert.throws = function(offender) { +assert.throws = function (offender) { try { offender() } catch (e) { @@ -125,14 +125,14 @@ assert.throws = function(offender) { assert.ok(false, 'Expected ' + offender + ' to throw exception') } -assert.lengthIs = function(actual, expectedLength) { +assert.lengthIs = function (actual, expectedLength) { assert.equal(actual.length, expectedLength) } -var expect = function(callback, timeout) { +var expect = function (callback, timeout) { var executed = false timeout = timeout || parseInt(process.env.TEST_TIMEOUT) || 5000 - var id = setTimeout(function() { + var id = setTimeout(function () { assert.ok( executed, 'Expected execution of function to be fired within ' + @@ -145,7 +145,7 @@ var expect = function(callback, timeout) { }, timeout) if (callback.length < 3) { - return function(err, queryResult) { + return function (err, queryResult) { clearTimeout(id) if (err) { assert.ok(err instanceof Error, 'Expected errors to be instances of Error: ' + sys.inspect(err)) @@ -153,7 +153,7 @@ var expect = function(callback, timeout) { callback.apply(this, arguments) } } else if (callback.length == 3) { - return function(err, arg1, arg2) { + return function (err, arg1, arg2) { clearTimeout(id) if (err) { assert.ok(err instanceof Error, 'Expected errors to be instances of Error: ' + sys.inspect(err)) @@ -166,7 +166,7 @@ var expect = function(callback, timeout) { } assert.calls = expect -assert.isNull = function(item, message) { +assert.isNull = function (item, message) { message = message || 'expected ' + item + ' to be null' assert.ok(item === null, message) } @@ -177,7 +177,7 @@ const getMode = () => { return '' } -global.test = function(name, action) { +global.test = function (name, action) { test.testCount++ test[name] = action var result = test[name]() @@ -193,11 +193,11 @@ process.stdout.write(require('path').basename(process.argv[1])) if (args.binary) process.stdout.write(' (binary)') if (args.native) process.stdout.write(' (native)') -process.on('exit', function() { +process.on('exit', function () { console.log('') }) -process.on('uncaughtException', function(err) { +process.on('uncaughtException', function (err) { console.error('\n %s', err.stack || err.toString()) // causes xargs to abort right away process.exit(255) @@ -205,7 +205,7 @@ process.on('uncaughtException', function(err) { var count = 0 -var Sink = function(expected, timeout, callback) { +var Sink = function (expected, timeout, callback) { var defaultTimeout = 5000 if (typeof timeout === 'function') { callback = timeout @@ -213,12 +213,12 @@ var Sink = function(expected, timeout, callback) { } timeout = timeout || defaultTimeout var internalCount = 0 - var kill = function() { + var kill = function () { assert.ok(false, 'Did not reach expected ' + expected + ' with an idle timeout of ' + timeout) } var killTimeout = setTimeout(kill, timeout) return { - add: function(count) { + add: function (count) { count = count || 1 internalCount += count clearTimeout(killTimeout) @@ -234,13 +234,13 @@ var Sink = function(expected, timeout, callback) { var getTimezoneOffset = Date.prototype.getTimezoneOffset -var setTimezoneOffset = function(minutesOffset) { - Date.prototype.getTimezoneOffset = function() { +var setTimezoneOffset = function (minutesOffset) { + Date.prototype.getTimezoneOffset = function () { return minutesOffset } } -var resetTimezoneOffset = function() { +var resetTimezoneOffset = function () { Date.prototype.getTimezoneOffset = getTimezoneOffset } diff --git a/packages/pg/test/unit/client/cleartext-password-tests.js b/packages/pg/test/unit/client/cleartext-password-tests.js index de28136e0..cd8dbb005 100644 --- a/packages/pg/test/unit/client/cleartext-password-tests.js +++ b/packages/pg/test/unit/client/cleartext-password-tests.js @@ -7,12 +7,12 @@ const createClient = require('./test-helper').createClient * code-being-tested works behind the scenes. */ -test('cleartext password authentication', function() { +test('cleartext password authentication', function () { var client = createClient() client.password = '!' client.connection.stream.packets = [] client.connection.emit('authenticationCleartextPassword') - test('responds with password', function() { + test('responds with password', function () { var packets = client.connection.stream.packets assert.lengthIs(packets, 1) var packet = packets[0] diff --git a/packages/pg/test/unit/client/configuration-tests.js b/packages/pg/test/unit/client/configuration-tests.js index f51e9a9e4..e6cbc0dcc 100644 --- a/packages/pg/test/unit/client/configuration-tests.js +++ b/packages/pg/test/unit/client/configuration-tests.js @@ -5,8 +5,8 @@ var pguser = process.env['PGUSER'] || process.env.USER var pgdatabase = process.env['PGDATABASE'] || process.env.USER var pgport = process.env['PGPORT'] || 5432 -test('client settings', function() { - test('defaults', function() { +test('client settings', function () { + test('defaults', function () { var client = new Client() assert.equal(client.user, pguser) assert.equal(client.database, pgdatabase) @@ -14,7 +14,7 @@ test('client settings', function() { assert.equal(client.ssl, false) }) - test('custom', function() { + test('custom', function () { var user = 'brian' var database = 'pgjstest' var password = 'boom' @@ -33,7 +33,7 @@ test('client settings', function() { assert.equal(client.ssl, true) }) - test('custom ssl default on', function() { + test('custom ssl default on', function () { var old = process.env.PGSSLMODE process.env.PGSSLMODE = 'prefer' @@ -43,7 +43,7 @@ test('client settings', function() { assert.equal(client.ssl, true) }) - test('custom ssl force off', function() { + test('custom ssl force off', function () { var old = process.env.PGSSLMODE process.env.PGSSLMODE = 'prefer' @@ -56,8 +56,8 @@ test('client settings', function() { }) }) -test('initializing from a config string', function() { - test('uses connectionString property', function() { +test('initializing from a config string', function () { + test('uses connectionString property', function () { var client = new Client({ connectionString: 'postgres://brian:pass@host1:333/databasename', }) @@ -68,7 +68,7 @@ test('initializing from a config string', function() { assert.equal(client.database, 'databasename') }) - test('uses the correct values from the config string', function() { + test('uses the correct values from the config string', function () { var client = new Client('postgres://brian:pass@host1:333/databasename') assert.equal(client.user, 'brian') assert.equal(client.password, 'pass') @@ -77,7 +77,7 @@ test('initializing from a config string', function() { assert.equal(client.database, 'databasename') }) - test('uses the correct values from the config string with space in password', function() { + test('uses the correct values from the config string with space in password', function () { var client = new Client('postgres://brian:pass word@host1:333/databasename') assert.equal(client.user, 'brian') assert.equal(client.password, 'pass word') @@ -86,7 +86,7 @@ test('initializing from a config string', function() { assert.equal(client.database, 'databasename') }) - test('when not including all values the defaults are used', function() { + test('when not including all values the defaults are used', function () { var client = new Client('postgres://host1') assert.equal(client.user, process.env['PGUSER'] || process.env.USER) assert.equal(client.password, process.env['PGPASSWORD'] || null) @@ -95,7 +95,7 @@ test('initializing from a config string', function() { assert.equal(client.database, process.env['PGDATABASE'] || process.env.USER) }) - test('when not including all values the environment variables are used', function() { + test('when not including all values the environment variables are used', function () { var envUserDefined = process.env['PGUSER'] !== undefined var envPasswordDefined = process.env['PGPASSWORD'] !== undefined var envDBDefined = process.env['PGDATABASE'] !== undefined @@ -153,11 +153,11 @@ test('initializing from a config string', function() { }) }) -test('calls connect correctly on connection', function() { +test('calls connect correctly on connection', function () { var client = new Client('/tmp') var usedPort = '' var usedHost = '' - client.connection.connect = function(port, host) { + client.connection.connect = function (port, host) { usedPort = port usedHost = host } diff --git a/packages/pg/test/unit/client/early-disconnect-tests.js b/packages/pg/test/unit/client/early-disconnect-tests.js index a741a0c68..494482845 100644 --- a/packages/pg/test/unit/client/early-disconnect-tests.js +++ b/packages/pg/test/unit/client/early-disconnect-tests.js @@ -4,15 +4,15 @@ var net = require('net') var pg = require('../../../lib/index.js') /* console.log() messages show up in `make test` output. TODO: fix it. */ -var server = net.createServer(function(c) { +var server = net.createServer(function (c) { c.destroy() server.close() }) -server.listen(7777, function() { +server.listen(7777, function () { var client = new pg.Client('postgres://localhost:7777') client.connect( - assert.calls(function(err) { + assert.calls(function (err) { assert(err) }) ) diff --git a/packages/pg/test/unit/client/escape-tests.js b/packages/pg/test/unit/client/escape-tests.js index dae361ffe..7f96a832d 100644 --- a/packages/pg/test/unit/client/escape-tests.js +++ b/packages/pg/test/unit/client/escape-tests.js @@ -3,21 +3,21 @@ var helper = require(__dirname + '/test-helper') function createClient(callback) { var client = new Client(helper.config) - client.connect(function(err) { + client.connect(function (err) { return callback(client) }) } -var testLit = function(testName, input, expected) { - test(testName, function() { +var testLit = function (testName, input, expected) { + test(testName, function () { var client = new Client(helper.config) var actual = client.escapeLiteral(input) assert.equal(expected, actual) }) } -var testIdent = function(testName, input, expected) { - test(testName, function() { +var testIdent = function (testName, input, expected) { + test(testName, function () { var client = new Client(helper.config) var actual = client.escapeIdentifier(input) assert.equal(expected, actual) diff --git a/packages/pg/test/unit/client/md5-password-tests.js b/packages/pg/test/unit/client/md5-password-tests.js index 5fdd44706..a55e955bc 100644 --- a/packages/pg/test/unit/client/md5-password-tests.js +++ b/packages/pg/test/unit/client/md5-password-tests.js @@ -2,15 +2,15 @@ var helper = require('./test-helper') var utils = require('../../../lib/utils') -test('md5 authentication', function() { +test('md5 authentication', function () { var client = helper.createClient() client.password = '!' var salt = Buffer.from([1, 2, 3, 4]) client.connection.emit('authenticationMD5Password', { salt: salt }) - test('responds', function() { + test('responds', function () { assert.lengthIs(client.connection.stream.packets, 1) - test('should have correct encrypted data', function() { + test('should have correct encrypted data', function () { var password = utils.postgresMd5PasswordHash(client.user, client.password, salt) // how do we want to test this? assert.equalBuffers(client.connection.stream.packets[0], new BufferList().addCString(password).join(true, 'p')) @@ -18,6 +18,6 @@ test('md5 authentication', function() { }) }) -test('md5 of utf-8 strings', function() { +test('md5 of utf-8 strings', function () { assert.equal(utils.md5('😊'), '5deda34cd95f304948d2bc1b4a62c11e') }) diff --git a/packages/pg/test/unit/client/notification-tests.js b/packages/pg/test/unit/client/notification-tests.js index fd33b34a6..5ca9df226 100644 --- a/packages/pg/test/unit/client/notification-tests.js +++ b/packages/pg/test/unit/client/notification-tests.js @@ -1,9 +1,9 @@ 'use strict' var helper = require(__dirname + '/test-helper') -test('passes connection notification', function() { +test('passes connection notification', function () { var client = helper.client() - assert.emits(client, 'notice', function(msg) { + assert.emits(client, 'notice', function (msg) { assert.equal(msg, 'HAY!!') }) client.connection.emit('notice', 'HAY!!') diff --git a/packages/pg/test/unit/client/prepared-statement-tests.js b/packages/pg/test/unit/client/prepared-statement-tests.js index afcf10f7d..2499808f7 100644 --- a/packages/pg/test/unit/client/prepared-statement-tests.js +++ b/packages/pg/test/unit/client/prepared-statement-tests.js @@ -5,49 +5,49 @@ var Query = require('../../../lib/query') var client = helper.client() var con = client.connection var parseArg = null -con.parse = function(arg) { +con.parse = function (arg) { parseArg = arg - process.nextTick(function() { + process.nextTick(function () { con.emit('parseComplete') }) } var bindArg = null -con.bind = function(arg) { +con.bind = function (arg) { bindArg = arg - process.nextTick(function() { + process.nextTick(function () { con.emit('bindComplete') }) } var executeArg = null -con.execute = function(arg) { +con.execute = function (arg) { executeArg = arg - process.nextTick(function() { + process.nextTick(function () { con.emit('rowData', { fields: [] }) con.emit('commandComplete', { text: '' }) }) } var describeArg = null -con.describe = function(arg) { +con.describe = function (arg) { describeArg = arg - process.nextTick(function() { + process.nextTick(function () { con.emit('rowDescription', { fields: [] }) }) } var syncCalled = false -con.flush = function() {} -con.sync = function() { +con.flush = function () {} +con.sync = function () { syncCalled = true - process.nextTick(function() { + process.nextTick(function () { con.emit('readyForQuery') }) } -test('bound command', function() { - test('simple, unnamed bound command', function() { +test('bound command', function () { + test('simple, unnamed bound command', function () { assert.ok(client.connection.emit('readyForQuery')) var query = client.query( @@ -57,31 +57,31 @@ test('bound command', function() { }) ) - assert.emits(query, 'end', function() { - test('parse argument', function() { + assert.emits(query, 'end', function () { + test('parse argument', function () { assert.equal(parseArg.name, null) assert.equal(parseArg.text, 'select * from X where name = $1') assert.equal(parseArg.types, null) }) - test('bind argument', function() { + test('bind argument', function () { assert.equal(bindArg.statement, null) assert.equal(bindArg.portal, '') assert.lengthIs(bindArg.values, 1) assert.equal(bindArg.values[0], 'hi') }) - test('describe argument', function() { + test('describe argument', function () { assert.equal(describeArg.type, 'P') assert.equal(describeArg.name, '') }) - test('execute argument', function() { + test('execute argument', function () { assert.equal(executeArg.portal, '') assert.equal(executeArg.rows, null) }) - test('sync called', function() { + test('sync called', function () { assert.ok(syncCalled) }) }) @@ -91,46 +91,46 @@ test('bound command', function() { var portalClient = helper.client() var portalCon = portalClient.connection var portalParseArg = null -portalCon.parse = function(arg) { +portalCon.parse = function (arg) { portalParseArg = arg - process.nextTick(function() { + process.nextTick(function () { portalCon.emit('parseComplete') }) } var portalBindArg = null -portalCon.bind = function(arg) { +portalCon.bind = function (arg) { portalBindArg = arg - process.nextTick(function() { + process.nextTick(function () { portalCon.emit('bindComplete') }) } var portalExecuteArg = null -portalCon.execute = function(arg) { +portalCon.execute = function (arg) { portalExecuteArg = arg - process.nextTick(function() { + process.nextTick(function () { portalCon.emit('rowData', { fields: [] }) portalCon.emit('commandComplete', { text: '' }) }) } var portalDescribeArg = null -portalCon.describe = function(arg) { +portalCon.describe = function (arg) { portalDescribeArg = arg - process.nextTick(function() { + process.nextTick(function () { portalCon.emit('rowDescription', { fields: [] }) }) } -portalCon.flush = function() {} -portalCon.sync = function() { - process.nextTick(function() { +portalCon.flush = function () {} +portalCon.sync = function () { + process.nextTick(function () { portalCon.emit('readyForQuery') }) } -test('prepared statement with explicit portal', function() { +test('prepared statement with explicit portal', function () { assert.ok(portalClient.connection.emit('readyForQuery')) var query = portalClient.query( @@ -141,16 +141,16 @@ test('prepared statement with explicit portal', function() { }) ) - assert.emits(query, 'end', function() { - test('bind argument', function() { + assert.emits(query, 'end', function () { + test('bind argument', function () { assert.equal(portalBindArg.portal, 'myportal') }) - test('describe argument', function() { + test('describe argument', function () { assert.equal(portalDescribeArg.name, 'myportal') }) - test('execute argument', function() { + test('execute argument', function () { assert.equal(portalExecuteArg.portal, 'myportal') }) }) diff --git a/packages/pg/test/unit/client/query-queue-tests.js b/packages/pg/test/unit/client/query-queue-tests.js index c02a698d9..9364ce822 100644 --- a/packages/pg/test/unit/client/query-queue-tests.js +++ b/packages/pg/test/unit/client/query-queue-tests.js @@ -2,17 +2,17 @@ var helper = require(__dirname + '/test-helper') var Connection = require(__dirname + '/../../../lib/connection') -test('drain', function() { +test('drain', function () { var con = new Connection({ stream: 'NO' }) var client = new Client({ connection: con }) - con.connect = function() { + con.connect = function () { con.emit('connect') } - con.query = function() {} + con.query = function () {} client.connect() var raisedDrain = false - client.on('drain', function() { + client.on('drain', function () { raisedDrain = true }) @@ -20,31 +20,31 @@ test('drain', function() { client.query('sup') client.query('boom') - test('with pending queries', function() { - test('does not emit drain', function() { + test('with pending queries', function () { + test('does not emit drain', function () { assert.equal(raisedDrain, false) }) }) - test('after some queries executed', function() { + test('after some queries executed', function () { con.emit('readyForQuery') - test('does not emit drain', function() { + test('does not emit drain', function () { assert.equal(raisedDrain, false) }) }) - test('when all queries are sent', function() { + test('when all queries are sent', function () { con.emit('readyForQuery') con.emit('readyForQuery') - test('does not emit drain', function() { + test('does not emit drain', function () { assert.equal(raisedDrain, false) }) }) - test('after last query finishes', function() { + test('after last query finishes', function () { con.emit('readyForQuery') - test('emits drain', function() { - process.nextTick(function() { + test('emits drain', function () { + process.nextTick(function () { assert.ok(raisedDrain) }) }) diff --git a/packages/pg/test/unit/client/result-metadata-tests.js b/packages/pg/test/unit/client/result-metadata-tests.js index 4dc3a0162..f3e005949 100644 --- a/packages/pg/test/unit/client/result-metadata-tests.js +++ b/packages/pg/test/unit/client/result-metadata-tests.js @@ -1,8 +1,8 @@ 'use strict' var helper = require(__dirname + '/test-helper') -var testForTag = function(tagText, callback) { - test('includes command tag data for tag ' + tagText, function() { +var testForTag = function (tagText, callback) { + test('includes command tag data for tag ' + tagText, function () { var client = helper.client() client.connection.emit('readyForQuery') @@ -23,8 +23,8 @@ var testForTag = function(tagText, callback) { }) } -var check = function(oid, rowCount, command) { - return function(result) { +var check = function (oid, rowCount, command) { + return function (result) { if (oid != null) { assert.equal(result.oid, oid) } diff --git a/packages/pg/test/unit/client/sasl-scram-tests.js b/packages/pg/test/unit/client/sasl-scram-tests.js index f0d17dadb..f60c8c4c9 100644 --- a/packages/pg/test/unit/client/sasl-scram-tests.js +++ b/packages/pg/test/unit/client/sasl-scram-tests.js @@ -3,11 +3,11 @@ require('./test-helper') var sasl = require('../../../lib/sasl') -test('sasl/scram', function() { - test('startSession', function() { - test('fails when mechanisms does not include SCRAM-SHA-256', function() { +test('sasl/scram', function () { + test('startSession', function () { + test('fails when mechanisms does not include SCRAM-SHA-256', function () { assert.throws( - function() { + function () { sasl.startSession([]) }, { @@ -16,7 +16,7 @@ test('sasl/scram', function() { ) }) - test('returns expected session data', function() { + test('returns expected session data', function () { const session = sasl.startSession(['SCRAM-SHA-256']) assert.equal(session.mechanism, 'SCRAM-SHA-256') @@ -26,7 +26,7 @@ test('sasl/scram', function() { assert(session.response.match(/^n,,n=\*,r=.{24}/)) }) - test('creates random nonces', function() { + test('creates random nonces', function () { const session1 = sasl.startSession(['SCRAM-SHA-256']) const session2 = sasl.startSession(['SCRAM-SHA-256']) @@ -34,10 +34,10 @@ test('sasl/scram', function() { }) }) - test('continueSession', function() { - test('fails when last session message was not SASLInitialResponse', function() { + test('continueSession', function () { + test('fails when last session message was not SASLInitialResponse', function () { assert.throws( - function() { + function () { sasl.continueSession({}) }, { @@ -46,9 +46,9 @@ test('sasl/scram', function() { ) }) - test('fails when nonce is missing in server message', function() { + test('fails when nonce is missing in server message', function () { assert.throws( - function() { + function () { sasl.continueSession( { message: 'SASLInitialResponse', @@ -62,9 +62,9 @@ test('sasl/scram', function() { ) }) - test('fails when salt is missing in server message', function() { + test('fails when salt is missing in server message', function () { assert.throws( - function() { + function () { sasl.continueSession( { message: 'SASLInitialResponse', @@ -78,9 +78,9 @@ test('sasl/scram', function() { ) }) - test('fails when iteration is missing in server message', function() { + test('fails when iteration is missing in server message', function () { assert.throws( - function() { + function () { sasl.continueSession( { message: 'SASLInitialResponse', @@ -94,9 +94,9 @@ test('sasl/scram', function() { ) }) - test('fails when server nonce does not start with client nonce', function() { + test('fails when server nonce does not start with client nonce', function () { assert.throws( - function() { + function () { sasl.continueSession( { message: 'SASLInitialResponse', @@ -111,7 +111,7 @@ test('sasl/scram', function() { ) }) - test('sets expected session data', function() { + test('sets expected session data', function () { const session = { message: 'SASLInitialResponse', clientNonce: 'a', @@ -126,10 +126,10 @@ test('sasl/scram', function() { }) }) - test('continueSession', function() { - test('fails when last session message was not SASLResponse', function() { + test('continueSession', function () { + test('fails when last session message was not SASLResponse', function () { assert.throws( - function() { + function () { sasl.finalizeSession({}) }, { @@ -138,9 +138,9 @@ test('sasl/scram', function() { ) }) - test('fails when server signature does not match', function() { + test('fails when server signature does not match', function () { assert.throws( - function() { + function () { sasl.finalizeSession( { message: 'SASLResponse', @@ -155,7 +155,7 @@ test('sasl/scram', function() { ) }) - test('does not fail when eveything is ok', function() { + test('does not fail when eveything is ok', function () { sasl.finalizeSession( { message: 'SASLResponse', diff --git a/packages/pg/test/unit/client/simple-query-tests.js b/packages/pg/test/unit/client/simple-query-tests.js index be709bd19..b0d5b8674 100644 --- a/packages/pg/test/unit/client/simple-query-tests.js +++ b/packages/pg/test/unit/client/simple-query-tests.js @@ -2,9 +2,9 @@ var helper = require(__dirname + '/test-helper') var Query = require('../../../lib/query') -test('executing query', function() { - test('queing query', function() { - test('when connection is ready', function() { +test('executing query', function () { + test('queing query', function () { + test('when connection is ready', function () { var client = helper.client() assert.empty(client.connection.queries) client.connection.emit('readyForQuery') @@ -13,22 +13,22 @@ test('executing query', function() { assert.equal(client.connection.queries, 'yes') }) - test('when connection is not ready', function() { + test('when connection is not ready', function () { var client = helper.client() - test('query is not sent', function() { + test('query is not sent', function () { client.query('boom') assert.empty(client.connection.queries) }) - test('sends query to connection once ready', function() { + test('sends query to connection once ready', function () { assert.ok(client.connection.emit('readyForQuery')) assert.lengthIs(client.connection.queries, 1) assert.equal(client.connection.queries[0], 'boom') }) }) - test('multiple in the queue', function() { + test('multiple in the queue', function () { var client = helper.client() var connection = client.connection var queries = connection.queries @@ -37,18 +37,18 @@ test('executing query', function() { client.query('three') assert.empty(queries) - test('after one ready for query', function() { + test('after one ready for query', function () { connection.emit('readyForQuery') assert.lengthIs(queries, 1) assert.equal(queries[0], 'one') }) - test('after two ready for query', function() { + test('after two ready for query', function () { connection.emit('readyForQuery') assert.lengthIs(queries, 2) }) - test('after a bunch more', function() { + test('after a bunch more', function () { connection.emit('readyForQuery') connection.emit('readyForQuery') connection.emit('readyForQuery') @@ -60,22 +60,22 @@ test('executing query', function() { }) }) - test('query event binding and flow', function() { + test('query event binding and flow', function () { var client = helper.client() var con = client.connection var query = client.query(new Query('whatever')) - test('has no queries sent before ready', function() { + test('has no queries sent before ready', function () { assert.empty(con.queries) }) - test('sends query on readyForQuery event', function() { + test('sends query on readyForQuery event', function () { con.emit('readyForQuery') assert.lengthIs(con.queries, 1) assert.equal(con.queries[0], 'whatever') }) - test('handles rowDescription message', function() { + test('handles rowDescription message', function () { var handled = con.emit('rowDescription', { fields: [ { @@ -86,15 +86,15 @@ test('executing query', function() { assert.ok(handled, 'should have handlded rowDescription') }) - test('handles dataRow messages', function() { - assert.emits(query, 'row', function(row) { + test('handles dataRow messages', function () { + assert.emits(query, 'row', function (row) { assert.equal(row['boom'], 'hi') }) var handled = con.emit('dataRow', { fields: ['hi'] }) assert.ok(handled, 'should have handled first data row message') - assert.emits(query, 'row', function(row) { + assert.emits(query, 'row', function (row) { assert.equal(row['boom'], 'bye') }) @@ -104,29 +104,29 @@ test('executing query', function() { // multiple command complete messages will be sent // when multiple queries are in a simple command - test('handles command complete messages', function() { + test('handles command complete messages', function () { con.emit('commandComplete', { text: 'INSERT 31 1', }) }) - test('removes itself after another readyForQuery message', function() { + test('removes itself after another readyForQuery message', function () { return false - assert.emits(query, 'end', function(msg) { + assert.emits(query, 'end', function (msg) { // TODO do we want to check the complete messages? }) con.emit('readyForQuery') // this would never actually happen - ;['dataRow', 'rowDescription', 'commandComplete'].forEach(function(msg) { + ;['dataRow', 'rowDescription', 'commandComplete'].forEach(function (msg) { assert.equal(con.emit(msg), false, "Should no longer be picking up '" + msg + "' messages") }) }) }) - test('handles errors', function() { + test('handles errors', function () { var client = helper.client() - test('throws an error when config is null', function() { + test('throws an error when config is null', function () { try { client.query(null, undefined) } catch (error) { @@ -138,7 +138,7 @@ test('executing query', function() { } }) - test('throws an error when config is undefined', function() { + test('throws an error when config is undefined', function () { try { client.query() } catch (error) { diff --git a/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js index 5a73486c9..9b0a3560b 100644 --- a/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js +++ b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js @@ -3,18 +3,18 @@ var helper = require(__dirname + '/test-helper') var Connection = require(__dirname + '/../../../lib/connection') var Client = require(__dirname + '/../../../lib/client') -test('emits end when not in query', function() { +test('emits end when not in query', function () { var stream = new (require('events').EventEmitter)() - stream.write = function() { + stream.write = function () { // NOOP } var client = new Client({ connection: new Connection({ stream: stream }) }) client.connect( - assert.calls(function() { + assert.calls(function () { client.query( 'SELECT NOW()', - assert.calls(function(err, result) { + assert.calls(function (err, result) { assert(err) }) ) @@ -23,11 +23,11 @@ test('emits end when not in query', function() { assert.emits(client, 'error') assert.emits(client, 'end') client.connection.emit('connect') - process.nextTick(function() { + process.nextTick(function () { client.connection.emit('readyForQuery') assert.equal(client.queryQueue.length, 0) assert(client.activeQuery, 'client should have issued query') - process.nextTick(function() { + process.nextTick(function () { stream.emit('close') }) }) diff --git a/packages/pg/test/unit/client/test-helper.js b/packages/pg/test/unit/client/test-helper.js index 814e94a94..8d1859033 100644 --- a/packages/pg/test/unit/client/test-helper.js +++ b/packages/pg/test/unit/client/test-helper.js @@ -2,11 +2,11 @@ var helper = require('../test-helper') var Connection = require('../../../lib/connection') -var makeClient = function() { +var makeClient = function () { var connection = new Connection({ stream: 'no' }) - connection.startup = function() {} - connection.connect = function() {} - connection.query = function(text) { + connection.startup = function () {} + connection.connect = function () {} + connection.query = function (text) { this.queries.push(text) } connection.queries = [] diff --git a/packages/pg/test/unit/client/throw-in-type-parser-tests.js b/packages/pg/test/unit/client/throw-in-type-parser-tests.js index cc8ec3c74..8f71fdc02 100644 --- a/packages/pg/test/unit/client/throw-in-type-parser-tests.js +++ b/packages/pg/test/unit/client/throw-in-type-parser-tests.js @@ -7,7 +7,7 @@ const suite = new helper.Suite() var typeParserError = new Error('TEST: Throw in type parsers') -types.setTypeParser('special oid that will throw', function() { +types.setTypeParser('special oid that will throw', function () { throw typeParserError }) @@ -31,20 +31,20 @@ const emitFakeEvents = (con) => { }) } -suite.test('emits error', function(done) { +suite.test('emits error', function (done) { var handled var client = helper.client() var con = client.connection var query = client.query(new Query('whatever')) emitFakeEvents(con) - assert.emits(query, 'error', function(err) { + assert.emits(query, 'error', function (err) { assert.equal(err, typeParserError) done() }) }) -suite.test('calls callback with error', function(done) { +suite.test('calls callback with error', function (done) { var handled var callbackCalled = 0 @@ -52,13 +52,13 @@ suite.test('calls callback with error', function(done) { var client = helper.client() var con = client.connection emitFakeEvents(con) - var query = client.query('whatever', function(err) { + var query = client.query('whatever', function (err) { assert.equal(err, typeParserError) done() }) }) -suite.test('rejects promise with error', function(done) { +suite.test('rejects promise with error', function (done) { var client = helper.client() var con = client.connection emitFakeEvents(con) diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index 30b510fc5..820b320a5 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -9,13 +9,13 @@ for (var key in process.env) { delete process.env[key] } -test('ConnectionParameters construction', function() { +test('ConnectionParameters construction', function () { assert.ok(new ConnectionParameters(), 'with null config') assert.ok(new ConnectionParameters({ user: 'asdf' }), 'with config object') assert.ok(new ConnectionParameters('postgres://localhost/postgres'), 'with connection string') }) -var compare = function(actual, expected, type) { +var compare = function (actual, expected, type) { const expectedDatabase = expected.database === undefined ? expected.user : expected.database assert.equal(actual.user, expected.user, type + ' user') @@ -32,13 +32,13 @@ var compare = function(actual, expected, type) { ) } -test('ConnectionParameters initializing from defaults', function() { +test('ConnectionParameters initializing from defaults', function () { var subject = new ConnectionParameters() compare(subject, defaults, 'defaults') assert.ok(subject.isDomainSocket === false) }) -test('ConnectionParameters initializing from defaults with connectionString set', function() { +test('ConnectionParameters initializing from defaults with connectionString set', function () { var config = { user: 'brians-are-the-best', database: 'scoobysnacks', @@ -59,7 +59,7 @@ test('ConnectionParameters initializing from defaults with connectionString set' compare(subject, config, 'defaults-connectionString') }) -test('ConnectionParameters initializing from config', function() { +test('ConnectionParameters initializing from config', function () { var config = { user: 'brian', database: 'home', @@ -79,7 +79,7 @@ test('ConnectionParameters initializing from config', function() { assert.ok(subject.isDomainSocket === false) }) -test('ConnectionParameters initializing from config and config.connectionString', function() { +test('ConnectionParameters initializing from config and config.connectionString', function () { var subject1 = new ConnectionParameters({ connectionString: 'postgres://test@host/db', }) @@ -101,31 +101,31 @@ test('ConnectionParameters initializing from config and config.connectionString' assert.equal(subject4.ssl, true) }) -test('escape spaces if present', function() { +test('escape spaces if present', function () { var subject = new ConnectionParameters('postgres://localhost/post gres') assert.equal(subject.database, 'post gres') }) -test('do not double escape spaces', function() { +test('do not double escape spaces', function () { var subject = new ConnectionParameters('postgres://localhost/post%20gres') assert.equal(subject.database, 'post gres') }) -test('initializing with unix domain socket', function() { +test('initializing with unix domain socket', function () { var subject = new ConnectionParameters('/var/run/') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/var/run/') assert.equal(subject.database, defaults.user) }) -test('initializing with unix domain socket and a specific database, the simple way', function() { +test('initializing with unix domain socket and a specific database, the simple way', function () { var subject = new ConnectionParameters('/var/run/ mydb') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/var/run/') assert.equal(subject.database, 'mydb') }) -test('initializing with unix domain socket, the health way', function() { +test('initializing with unix domain socket, the health way', function () { var subject = new ConnectionParameters('socket:/some path/?db=my[db]&encoding=utf8') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/some path/') @@ -133,7 +133,7 @@ test('initializing with unix domain socket, the health way', function() { assert.equal(subject.client_encoding, 'utf8') }) -test('initializing with unix domain socket, the escaped health way', function() { +test('initializing with unix domain socket, the escaped health way', function () { var subject = new ConnectionParameters('socket:/some%20path/?db=my%2Bdb&encoding=utf8') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/some path/') @@ -141,12 +141,12 @@ test('initializing with unix domain socket, the escaped health way', function() assert.equal(subject.client_encoding, 'utf8') }) -test('libpq connection string building', function() { - var checkForPart = function(array, part) { +test('libpq connection string building', function () { + var checkForPart = function (array, part) { assert.ok(array.indexOf(part) > -1, array.join(' ') + ' did not contain ' + part) } - test('builds simple string', function() { + test('builds simple string', function () { var config = { user: 'brian', password: 'xyz', @@ -156,7 +156,7 @@ test('libpq connection string building', function() { } var subject = new ConnectionParameters(config) subject.getLibpqConnectionString( - assert.calls(function(err, constring) { + assert.calls(function (err, constring) { assert(!err) var parts = constring.split(' ') checkForPart(parts, "user='brian'") @@ -168,7 +168,7 @@ test('libpq connection string building', function() { ) }) - test('builds dns string', function() { + test('builds dns string', function () { var config = { user: 'brian', password: 'asdf', @@ -177,7 +177,7 @@ test('libpq connection string building', function() { } var subject = new ConnectionParameters(config) subject.getLibpqConnectionString( - assert.calls(function(err, constring) { + assert.calls(function (err, constring) { assert(!err) var parts = constring.split(' ') checkForPart(parts, "user='brian'") @@ -186,7 +186,7 @@ test('libpq connection string building', function() { ) }) - test('error when dns fails', function() { + test('error when dns fails', function () { var config = { user: 'brian', password: 'asf', @@ -195,14 +195,14 @@ test('libpq connection string building', function() { } var subject = new ConnectionParameters(config) subject.getLibpqConnectionString( - assert.calls(function(err, constring) { + assert.calls(function (err, constring) { assert.ok(err) assert.isNull(constring) }) ) }) - test('connecting to unix domain socket', function() { + test('connecting to unix domain socket', function () { var config = { user: 'brian', password: 'asf', @@ -211,7 +211,7 @@ test('libpq connection string building', function() { } var subject = new ConnectionParameters(config) subject.getLibpqConnectionString( - assert.calls(function(err, constring) { + assert.calls(function (err, constring) { assert(!err) var parts = constring.split(' ') checkForPart(parts, "user='brian'") @@ -220,7 +220,7 @@ test('libpq connection string building', function() { ) }) - test('config contains quotes and backslashes', function() { + test('config contains quotes and backslashes', function () { var config = { user: 'not\\brian', password: "bad'chars", @@ -229,7 +229,7 @@ test('libpq connection string building', function() { } var subject = new ConnectionParameters(config) subject.getLibpqConnectionString( - assert.calls(function(err, constring) { + assert.calls(function (err, constring) { assert(!err) var parts = constring.split(' ') checkForPart(parts, "user='not\\\\brian'") @@ -238,13 +238,13 @@ test('libpq connection string building', function() { ) }) - test('encoding can be specified by config', function() { + test('encoding can be specified by config', function () { var config = { client_encoding: 'utf-8', } var subject = new ConnectionParameters(config) subject.getLibpqConnectionString( - assert.calls(function(err, constring) { + assert.calls(function (err, constring) { assert(!err) var parts = constring.split(' ') checkForPart(parts, "client_encoding='utf-8'") @@ -252,7 +252,7 @@ test('libpq connection string building', function() { ) }) - test('password contains < and/or > characters', function() { + test('password contains < and/or > characters', function () { return false var sourceConfig = { user: 'brian', @@ -276,7 +276,7 @@ test('libpq connection string building', function() { assert.equal(subject.password, sourceConfig.password) }) - test('username or password contains weird characters', function() { + test('username or password contains weird characters', function () { var defaults = require('../../../lib/defaults') defaults.ssl = true var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000' @@ -287,7 +287,7 @@ test('libpq connection string building', function() { assert.equal(subject.ssl, true) }) - test('url is properly encoded', function() { + test('url is properly encoded', function () { var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl' var subject = new ConnectionParameters(encoded) assert.equal(subject.user, 'bi%na%%ry ') @@ -296,7 +296,7 @@ test('libpq connection string building', function() { assert.equal(subject.database, ' u%20rl') }) - test('ssl is set on client', function() { + test('ssl is set on client', function () { var Client = require('../../../lib/client') var defaults = require('../../../lib/defaults') defaults.ssl = true @@ -304,7 +304,7 @@ test('libpq connection string building', function() { assert(c.ssl, 'Client should have ssl enabled via defaults') }) - test('ssl is set on client', function() { + test('ssl is set on client', function () { var sourceConfig = { user: 'brian', password: 'helloe', @@ -324,7 +324,7 @@ test('libpq connection string building', function() { defaults.ssl = true var c = new ConnectionParameters(sourceConfig) c.getLibpqConnectionString( - assert.calls(function(err, pgCString) { + assert.calls(function (err, pgCString) { assert(!err) assert.equal( pgCString.indexOf("sslrootcert='/path/root.crt'") !== -1, diff --git a/packages/pg/test/unit/connection-parameters/environment-variable-tests.js b/packages/pg/test/unit/connection-parameters/environment-variable-tests.js index e1decf625..45d481e30 100644 --- a/packages/pg/test/unit/connection-parameters/environment-variable-tests.js +++ b/packages/pg/test/unit/connection-parameters/environment-variable-tests.js @@ -11,7 +11,7 @@ for (var key in process.env) { delete process.env[key] } -test('ConnectionParameters initialized from environment variables', function(t) { +test('ConnectionParameters initialized from environment variables', function (t) { process.env['PGHOST'] = 'local' process.env['PGUSER'] = 'bmc2' process.env['PGPORT'] = 7890 @@ -26,7 +26,7 @@ test('ConnectionParameters initialized from environment variables', function(t) assert.equal(subject.password, 'open', 'env password') }) -test('ConnectionParameters initialized from mix', function(t) { +test('ConnectionParameters initialized from mix', function (t) { delete process.env['PGPASSWORD'] delete process.env['PGDATABASE'] var subject = new ConnectionParameters({ @@ -45,7 +45,7 @@ for (var key in process.env) { delete process.env[key] } -test('connection string parsing', function(t) { +test('connection string parsing', function (t) { var string = 'postgres://brian:pw@boom:381/lala' var subject = new ConnectionParameters(string) assert.equal(subject.host, 'boom', 'string host') @@ -55,7 +55,7 @@ test('connection string parsing', function(t) { assert.equal(subject.database, 'lala', 'string database') }) -test('connection string parsing - ssl', function(t) { +test('connection string parsing - ssl', function (t) { var string = 'postgres://brian:pw@boom:381/lala?ssl=true' var subject = new ConnectionParameters(string) assert.equal(subject.ssl, true, 'ssl') @@ -82,18 +82,18 @@ for (var key in process.env) { delete process.env[key] } -test('ssl is false by default', function() { +test('ssl is false by default', function () { var subject = new ConnectionParameters() assert.equal(subject.ssl, false) }) -var testVal = function(mode, expected) { +var testVal = function (mode, expected) { // clear process.env for (var key in process.env) { delete process.env[key] } process.env.PGSSLMODE = mode - test('ssl is ' + expected + ' when $PGSSLMODE=' + mode, function() { + test('ssl is ' + expected + ' when $PGSSLMODE=' + mode, function () { var subject = new ConnectionParameters() assert.equal(subject.ssl, expected) }) diff --git a/packages/pg/test/unit/connection/error-tests.js b/packages/pg/test/unit/connection/error-tests.js index 43c06cc3c..5075c770d 100644 --- a/packages/pg/test/unit/connection/error-tests.js +++ b/packages/pg/test/unit/connection/error-tests.js @@ -5,9 +5,9 @@ var net = require('net') const suite = new helper.Suite() -suite.test('connection emits stream errors', function(done) { +suite.test('connection emits stream errors', function (done) { var con = new Connection({ stream: new MemoryStream() }) - assert.emits(con, 'error', function(err) { + assert.emits(con, 'error', function (err) { assert.equal(err.message, 'OMG!') done() }) @@ -15,10 +15,10 @@ suite.test('connection emits stream errors', function(done) { con.stream.emit('error', new Error('OMG!')) }) -suite.test('connection emits ECONNRESET errors during normal operation', function(done) { +suite.test('connection emits ECONNRESET errors during normal operation', function (done) { var con = new Connection({ stream: new MemoryStream() }) con.connect() - assert.emits(con, 'error', function(err) { + assert.emits(con, 'error', function (err) { assert.equal(err.code, 'ECONNRESET') done() }) @@ -27,7 +27,7 @@ suite.test('connection emits ECONNRESET errors during normal operation', functio con.stream.emit('error', e) }) -suite.test('connection does not emit ECONNRESET errors during disconnect', function(done) { +suite.test('connection does not emit ECONNRESET errors during disconnect', function (done) { var con = new Connection({ stream: new MemoryStream() }) con.connect() var e = new Error('Connection Reset') @@ -60,20 +60,20 @@ var SSLNegotiationPacketTests = [ for (var i = 0; i < SSLNegotiationPacketTests.length; i++) { var tc = SSLNegotiationPacketTests[i] - suite.test(tc.testName, function(done) { + suite.test(tc.testName, function (done) { // our fake postgres server var socket - var server = net.createServer(function(c) { + var server = net.createServer(function (c) { socket = c - c.once('data', function(data) { + c.once('data', function (data) { c.write(Buffer.from(tc.response)) }) }) - server.listen(7778, function() { + server.listen(7778, function () { var con = new Connection({ ssl: true }) con.connect(7778, 'localhost') - assert.emits(con, tc.responseType, function(err) { + assert.emits(con, tc.responseType, function (err) { if (tc.errorMessage !== null || err) { assert.equal(err.message, tc.errorMessage) } diff --git a/packages/pg/test/unit/connection/inbound-parser-tests.js b/packages/pg/test/unit/connection/inbound-parser-tests.js index 866c614ab..5f92cdc52 100644 --- a/packages/pg/test/unit/connection/inbound-parser-tests.js +++ b/packages/pg/test/unit/connection/inbound-parser-tests.js @@ -2,7 +2,7 @@ require(__dirname + '/test-helper') var Connection = require(__dirname + '/../../../lib/connection') var buffers = require(__dirname + '/../../test-buffers') -var PARSE = function(buffer) { +var PARSE = function (buffer) { return new Parser(buffer).parse() } @@ -15,7 +15,7 @@ var parseCompleteBuffer = buffers.parseComplete() var bindCompleteBuffer = buffers.bindComplete() var portalSuspendedBuffer = buffers.portalSuspended() -var addRow = function(bufferList, name, offset) { +var addRow = function (bufferList, name, offset) { return bufferList .addCString(name) // field name .addInt32(offset++) // table id @@ -112,20 +112,20 @@ var expectedTwoRowMessage = { fieldCount: 2, } -var testForMessage = function(buffer, expectedMessage) { +var testForMessage = function (buffer, expectedMessage) { var lastMessage = {} - test('recieves and parses ' + expectedMessage.name, function() { + test('recieves and parses ' + expectedMessage.name, function () { var stream = new MemoryStream() var client = new Connection({ stream: stream, }) client.connect() - client.on('message', function(msg) { + client.on('message', function (msg) { lastMessage = msg }) - client.on(expectedMessage.name, function() { + client.on(expectedMessage.name, function () { client.removeAllListeners(expectedMessage.name) }) @@ -171,16 +171,16 @@ var expectedNotificationResponseMessage = { payload: 'boom', } -test('Connection', function() { +test('Connection', function () { testForMessage(authOkBuffer, expectedAuthenticationOkayMessage) testForMessage(plainPasswordBuffer, expectedPlainPasswordMessage) var msgMD5 = testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage) - test('md5 has right salt', function() { + test('md5 has right salt', function () { assert.equalBuffers(msgMD5.salt, Buffer.from([1, 2, 3, 4])) }) var msgSASL = testForMessage(SASLBuffer, expectedSASLMessage) - test('SASL has the right mechanisms', function() { + test('SASL has the right mechanisms', function () { assert.deepStrictEqual(msgSASL.mechanisms, ['SCRAM-SHA-256']) }) testForMessage(SASLContinueBuffer, expectedSASLContinueMessage) @@ -191,25 +191,25 @@ test('Connection', function() { testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage) testForMessage(commandCompleteBuffer, expectedCommandCompleteMessage) testForMessage(notificationResponseBuffer, expectedNotificationResponseMessage) - test('empty row message', function() { + test('empty row message', function () { var message = testForMessage(emptyRowDescriptionBuffer, expectedEmptyRowDescriptionMessage) - test('has no fields', function() { + test('has no fields', function () { assert.equal(message.fields.length, 0) }) }) - test('no data message', function() { + test('no data message', function () { testForMessage(Buffer.from([0x6e, 0, 0, 0, 4]), { name: 'noData', }) }) - test('one row message', function() { + test('one row message', function () { var message = testForMessage(oneRowDescBuff, expectedOneRowMessage) - test('has one field', function() { + test('has one field', function () { assert.equal(message.fields.length, 1) }) - test('has correct field info', function() { + test('has correct field info', function () { assert.same(message.fields[0], { name: 'id', tableID: 1, @@ -222,12 +222,12 @@ test('Connection', function() { }) }) - test('two row message', function() { + test('two row message', function () { var message = testForMessage(twoRowBuf, expectedTwoRowMessage) - test('has two fields', function() { + test('has two fields', function () { assert.equal(message.fields.length, 2) }) - test('has correct first field', function() { + test('has correct first field', function () { assert.same(message.fields[0], { name: 'bang', tableID: 1, @@ -238,7 +238,7 @@ test('Connection', function() { format: 'text', }) }) - test('has correct second field', function() { + test('has correct second field', function () { assert.same(message.fields[1], { name: 'whoah', tableID: 10, @@ -251,33 +251,33 @@ test('Connection', function() { }) }) - test('parsing rows', function() { - test('parsing empty row', function() { + test('parsing rows', function () { + test('parsing empty row', function () { var message = testForMessage(emptyRowFieldBuf, { name: 'dataRow', fieldCount: 0, }) - test('has 0 fields', function() { + test('has 0 fields', function () { assert.equal(message.fields.length, 0) }) }) - test('parsing data row with fields', function() { + test('parsing data row with fields', function () { var message = testForMessage(oneFieldBuf, { name: 'dataRow', fieldCount: 1, }) - test('has 1 field', function() { + test('has 1 field', function () { assert.equal(message.fields.length, 1) }) - test('field is correct', function() { + test('field is correct', function () { assert.equal(message.fields[0], 'test') }) }) }) - test('notice message', function() { + test('notice message', function () { // this uses the same logic as error message var buff = buffers.notice([{ type: 'C', value: 'code' }]) testForMessage(buff, { @@ -286,14 +286,14 @@ test('Connection', function() { }) }) - test('error messages', function() { - test('with no fields', function() { + test('error messages', function () { + test('with no fields', function () { var msg = testForMessage(buffers.error(), { name: 'error', }) }) - test('with all the fields', function() { + test('with all the fields', function () { var buffer = buffers.error([ { type: 'S', @@ -367,25 +367,25 @@ test('Connection', function() { }) }) - test('parses parse complete command', function() { + test('parses parse complete command', function () { testForMessage(parseCompleteBuffer, { name: 'parseComplete', }) }) - test('parses bind complete command', function() { + test('parses bind complete command', function () { testForMessage(bindCompleteBuffer, { name: 'bindComplete', }) }) - test('parses portal suspended message', function() { + test('parses portal suspended message', function () { testForMessage(portalSuspendedBuffer, { name: 'portalSuspended', }) }) - test('parses replication start message', function() { + test('parses replication start message', function () { testForMessage(Buffer.from([0x57, 0x00, 0x00, 0x00, 0x04]), { name: 'replicationStart', length: 4, @@ -396,7 +396,7 @@ test('Connection', function() { // since the data message on a stream can randomly divide the incomming // tcp packets anywhere, we need to make sure we can parse every single // split on a tcp message -test('split buffer, single message parsing', function() { +test('split buffer, single message parsing', function () { var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']) var stream = new MemoryStream() stream.readyState = 'open' @@ -405,11 +405,11 @@ test('split buffer, single message parsing', function() { }) client.connect() var message = null - client.on('message', function(msg) { + client.on('message', function (msg) { message = msg }) - test('parses when full buffer comes in', function() { + test('parses when full buffer comes in', function () { stream.emit('data', fullBuffer) assert.lengthIs(message.fields, 5) assert.equal(message.fields[0], null) @@ -419,7 +419,7 @@ test('split buffer, single message parsing', function() { assert.equal(message.fields[4], '!') }) - var testMessageRecievedAfterSpiltAt = function(split) { + var testMessageRecievedAfterSpiltAt = function (split) { var firstBuffer = Buffer.alloc(fullBuffer.length - split) var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) fullBuffer.copy(firstBuffer, 0, 0) @@ -434,22 +434,22 @@ test('split buffer, single message parsing', function() { assert.equal(message.fields[4], '!') } - test('parses when split in the middle', function() { + test('parses when split in the middle', function () { testMessageRecievedAfterSpiltAt(6) }) - test('parses when split at end', function() { + test('parses when split at end', function () { testMessageRecievedAfterSpiltAt(2) }) - test('parses when split at beginning', function() { + test('parses when split at beginning', function () { testMessageRecievedAfterSpiltAt(fullBuffer.length - 2) testMessageRecievedAfterSpiltAt(fullBuffer.length - 1) testMessageRecievedAfterSpiltAt(fullBuffer.length - 5) }) }) -test('split buffer, multiple message parsing', function() { +test('split buffer, multiple message parsing', function () { var dataRowBuffer = buffers.dataRow(['!']) var readyForQueryBuffer = buffers.readyForQuery() var fullBuffer = Buffer.alloc(dataRowBuffer.length + readyForQueryBuffer.length) @@ -462,11 +462,11 @@ test('split buffer, multiple message parsing', function() { stream: stream, }) client.connect() - client.on('message', function(msg) { + client.on('message', function (msg) { messages.push(msg) }) - var verifyMessages = function() { + var verifyMessages = function () { assert.lengthIs(messages, 2) assert.same(messages[0], { name: 'dataRow', @@ -479,11 +479,11 @@ test('split buffer, multiple message parsing', function() { messages = [] } // sanity check - test('recieves both messages when packet is not split', function() { + test('recieves both messages when packet is not split', function () { stream.emit('data', fullBuffer) verifyMessages() }) - var splitAndVerifyTwoMessages = function(split) { + var splitAndVerifyTwoMessages = function (split) { var firstBuffer = Buffer.alloc(fullBuffer.length - split) var secondBuffer = Buffer.alloc(fullBuffer.length - firstBuffer.length) fullBuffer.copy(firstBuffer, 0, 0) @@ -492,17 +492,17 @@ test('split buffer, multiple message parsing', function() { stream.emit('data', secondBuffer) } - test('recieves both messages when packet is split', function() { - test('in the middle', function() { + test('recieves both messages when packet is split', function () { + test('in the middle', function () { splitAndVerifyTwoMessages(11) }) - test('at the front', function() { + test('at the front', function () { splitAndVerifyTwoMessages(fullBuffer.length - 1) splitAndVerifyTwoMessages(fullBuffer.length - 4) splitAndVerifyTwoMessages(fullBuffer.length - 6) }) - test('at the end', function() { + test('at the end', function () { splitAndVerifyTwoMessages(8) splitAndVerifyTwoMessages(1) }) diff --git a/packages/pg/test/unit/connection/outbound-sending-tests.js b/packages/pg/test/unit/connection/outbound-sending-tests.js index c6c8e90c2..b40af0005 100644 --- a/packages/pg/test/unit/connection/outbound-sending-tests.js +++ b/packages/pg/test/unit/connection/outbound-sending-tests.js @@ -6,13 +6,13 @@ var con = new Connection({ stream: stream, }) -assert.received = function(stream, buffer) { +assert.received = function (stream, buffer) { assert.lengthIs(stream.packets, 1) var packet = stream.packets.pop() assert.equalBuffers(packet, buffer) } -test('sends startup message', function() { +test('sends startup message', function () { con.startup({ user: 'brian', database: 'bang', @@ -33,58 +33,43 @@ test('sends startup message', function() { ) }) -test('sends password message', function() { +test('sends password message', function () { con.password('!') assert.received(stream, new BufferList().addCString('!').join(true, 'p')) }) -test('sends SASLInitialResponseMessage message', function() { +test('sends SASLInitialResponseMessage message', function () { con.sendSASLInitialResponseMessage('mech', 'data') - assert.received( - stream, - new BufferList() - .addCString('mech') - .addInt32(4) - .addString('data') - .join(true, 'p') - ) + assert.received(stream, new BufferList().addCString('mech').addInt32(4).addString('data').join(true, 'p')) }) -test('sends SCRAMClientFinalMessage message', function() { +test('sends SCRAMClientFinalMessage message', function () { con.sendSCRAMClientFinalMessage('data') assert.received(stream, new BufferList().addString('data').join(true, 'p')) }) -test('sends query message', function() { +test('sends query message', function () { var txt = 'select * from boom' con.query(txt) assert.received(stream, new BufferList().addCString(txt).join(true, 'Q')) }) -test('sends parse message', function() { +test('sends parse message', function () { con.parse({ text: '!' }) - var expected = new BufferList() - .addCString('') - .addCString('!') - .addInt16(0) - .join(true, 'P') + var expected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P') assert.received(stream, expected) }) -test('sends parse message with named query', function() { +test('sends parse message with named query', function () { con.parse({ name: 'boom', text: 'select * from boom', types: [], }) - var expected = new BufferList() - .addCString('boom') - .addCString('select * from boom') - .addInt16(0) - .join(true, 'P') + var expected = new BufferList().addCString('boom').addCString('select * from boom').addInt16(0).join(true, 'P') assert.received(stream, expected) - test('with multiple parameters', function() { + test('with multiple parameters', function () { con.parse({ name: 'force', text: 'select * from bang where name = $1', @@ -103,8 +88,8 @@ test('sends parse message with named query', function() { }) }) -test('bind messages', function() { - test('with no values', function() { +test('bind messages', function () { + test('with no values', function () { con.bind() var expectedBuffer = new BufferList() @@ -117,7 +102,7 @@ test('bind messages', function() { assert.received(stream, expectedBuffer) }) - test('with named statement, portal, and values', function() { + test('with named statement, portal, and values', function () { con.bind({ portal: 'bang', statement: 'woo', @@ -141,7 +126,7 @@ test('bind messages', function() { }) }) -test('with named statement, portal, and buffer value', function() { +test('with named statement, portal, and buffer value', function () { con.bind({ portal: 'bang', statement: 'woo', @@ -168,64 +153,52 @@ test('with named statement, portal, and buffer value', function() { assert.received(stream, expectedBuffer) }) -test('sends execute message', function() { - test('for unamed portal with no row limit', function() { +test('sends execute message', function () { + test('for unamed portal with no row limit', function () { con.execute() - var expectedBuffer = new BufferList() - .addCString('') - .addInt32(0) - .join(true, 'E') + var expectedBuffer = new BufferList().addCString('').addInt32(0).join(true, 'E') assert.received(stream, expectedBuffer) }) - test('for named portal with row limit', function() { + test('for named portal with row limit', function () { con.execute({ portal: 'my favorite portal', rows: 100, }) - var expectedBuffer = new BufferList() - .addCString('my favorite portal') - .addInt32(100) - .join(true, 'E') + var expectedBuffer = new BufferList().addCString('my favorite portal').addInt32(100).join(true, 'E') assert.received(stream, expectedBuffer) }) }) -test('sends flush command', function() { +test('sends flush command', function () { con.flush() var expected = new BufferList().join(true, 'H') assert.received(stream, expected) }) -test('sends sync command', function() { +test('sends sync command', function () { con.sync() var expected = new BufferList().join(true, 'S') assert.received(stream, expected) }) -test('sends end command', function() { +test('sends end command', function () { con.end() var expected = Buffer.from([0x58, 0, 0, 0, 4]) assert.received(stream, expected) assert.equal(stream.closed, true) }) -test('sends describe command', function() { - test('describe statement', function() { +test('sends describe command', function () { + test('describe statement', function () { con.describe({ type: 'S', name: 'bang' }) - var expected = new BufferList() - .addChar('S') - .addCString('bang') - .join(true, 'D') + var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D') assert.received(stream, expected) }) - test('describe unnamed portal', function() { + test('describe unnamed portal', function () { con.describe({ type: 'P' }) - var expected = new BufferList() - .addChar('P') - .addCString('') - .join(true, 'D') + var expected = new BufferList().addChar('P').addCString('').join(true, 'D') assert.received(stream, expected) }) }) diff --git a/packages/pg/test/unit/connection/startup-tests.js b/packages/pg/test/unit/connection/startup-tests.js index 9bf973d35..09a710c7a 100644 --- a/packages/pg/test/unit/connection/startup-tests.js +++ b/packages/pg/test/unit/connection/startup-tests.js @@ -1,17 +1,17 @@ 'use strict' require(__dirname + '/test-helper') var Connection = require(__dirname + '/../../../lib/connection') -test('connection can take existing stream', function() { +test('connection can take existing stream', function () { var stream = new MemoryStream() var con = new Connection({ stream: stream }) assert.equal(con.stream, stream) }) -test('using closed stream', function() { - var makeStream = function() { +test('using closed stream', function () { + var makeStream = function () { var stream = new MemoryStream() stream.readyState = 'closed' - stream.connect = function(port, host) { + stream.connect = function (port, host) { this.connectCalled = true this.port = port this.host = host @@ -25,22 +25,22 @@ test('using closed stream', function() { con.connect(1234, 'bang') - test('makes stream connect', function() { + test('makes stream connect', function () { assert.equal(stream.connectCalled, true) }) - test('uses configured port', function() { + test('uses configured port', function () { assert.equal(stream.port, 1234) }) - test('uses configured host', function() { + test('uses configured host', function () { assert.equal(stream.host, 'bang') }) - test('after stream connects client emits connected event', function() { + test('after stream connects client emits connected event', function () { var hit = false - con.once('connect', function() { + con.once('connect', function () { hit = true }) @@ -48,34 +48,34 @@ test('using closed stream', function() { assert.ok(hit) }) - test('after stream emits connected event init TCP-keepalive', function() { + test('after stream emits connected event init TCP-keepalive', function () { var stream = makeStream() var con = new Connection({ stream: stream, keepAlive: true }) con.connect(123, 'test') var res = false - stream.setKeepAlive = function(bit) { + stream.setKeepAlive = function (bit) { res = bit } assert.ok(stream.emit('connect')) - setTimeout(function() { + setTimeout(function () { assert.equal(res, true) }) }) }) -test('using opened stream', function() { +test('using opened stream', function () { var stream = new MemoryStream() stream.readyState = 'open' - stream.connect = function() { + stream.connect = function () { assert.ok(false, 'Should not call open') } var con = new Connection({ stream: stream }) - test('does not call open', function() { + test('does not call open', function () { var hit = false - con.once('connect', function() { + con.once('connect', function () { hit = true }) con.connect() diff --git a/packages/pg/test/unit/test-helper.js b/packages/pg/test/unit/test-helper.js index 0b149cec0..5793251b5 100644 --- a/packages/pg/test/unit/test-helper.js +++ b/packages/pg/test/unit/test-helper.js @@ -4,7 +4,7 @@ var EventEmitter = require('events').EventEmitter var helper = require('../test-helper') var Connection = require('../../lib/connection') -global.MemoryStream = function() { +global.MemoryStream = function () { EventEmitter.call(this) this.packets = [] } @@ -13,22 +13,22 @@ helper.sys.inherits(MemoryStream, EventEmitter) var p = MemoryStream.prototype -p.write = function(packet, cb) { +p.write = function (packet, cb) { this.packets.push(packet) if (cb) { cb() } } -p.end = function() { +p.end = function () { p.closed = true } -p.setKeepAlive = function() {} +p.setKeepAlive = function () {} p.closed = false p.writable = true -const createClient = function() { +const createClient = function () { var stream = new MemoryStream() stream.readyState = 'open' var client = new Client({ diff --git a/packages/pg/test/unit/utils-tests.js b/packages/pg/test/unit/utils-tests.js index 3ebc9a55a..3d087ad0d 100644 --- a/packages/pg/test/unit/utils-tests.js +++ b/packages/pg/test/unit/utils-tests.js @@ -3,7 +3,7 @@ var helper = require('./test-helper') var utils = require('./../../lib/utils') var defaults = require('./../../lib').defaults -test('ensure types is exported on root object', function() { +test('ensure types is exported on root object', function () { var pg = require('../../lib') assert(pg.types) assert(pg.types.getTypeParser) @@ -13,12 +13,12 @@ test('ensure types is exported on root object', function() { // this tests the monkey patching // to ensure comptability with older // versions of node -test('EventEmitter.once', function(t) { +test('EventEmitter.once', function (t) { // an event emitter var stream = new MemoryStream() var callCount = 0 - stream.once('single', function() { + stream.once('single', function () { callCount++ }) @@ -27,9 +27,9 @@ test('EventEmitter.once', function(t) { assert.equal(callCount, 1) }) -test('normalizing query configs', function() { +test('normalizing query configs', function () { var config - var callback = function() {} + var callback = function () {} config = utils.normalizeQueryConfig({ text: 'TEXT' }) assert.same(config, { text: 'TEXT' }) @@ -47,13 +47,13 @@ test('normalizing query configs', function() { assert.deepEqual(config, { text: 'TEXT', values: [10], callback: callback }) }) -test('prepareValues: buffer prepared properly', function() { +test('prepareValues: buffer prepared properly', function () { var buf = Buffer.from('quack') var out = utils.prepareValue(buf) assert.strictEqual(buf, out) }) -test('prepareValues: Uint8Array prepared properly', function() { +test('prepareValues: Uint8Array prepared properly', function () { var buf = new Uint8Array([1, 2, 3]).subarray(1, 2) var out = utils.prepareValue(buf) assert.ok(Buffer.isBuffer(out)) @@ -61,7 +61,7 @@ test('prepareValues: Uint8Array prepared properly', function() { assert.deepEqual(out[0], 2) }) -test('prepareValues: date prepared properly', function() { +test('prepareValues: date prepared properly', function () { helper.setTimezoneOffset(-330) var date = new Date(2014, 1, 1, 11, 11, 1, 7) @@ -71,7 +71,7 @@ test('prepareValues: date prepared properly', function() { helper.resetTimezoneOffset() }) -test('prepareValues: date prepared properly as UTC', function() { +test('prepareValues: date prepared properly as UTC', function () { defaults.parseInputDatesAsUTC = true // make a date in the local timezone that represents a specific UTC point in time @@ -82,7 +82,7 @@ test('prepareValues: date prepared properly as UTC', function() { defaults.parseInputDatesAsUTC = false }) -test('prepareValues: BC date prepared properly', function() { +test('prepareValues: BC date prepared properly', function () { helper.setTimezoneOffset(-330) var date = new Date(-3245, 1, 1, 11, 11, 1, 7) @@ -92,7 +92,7 @@ test('prepareValues: BC date prepared properly', function() { helper.resetTimezoneOffset() }) -test('prepareValues: 1 BC date prepared properly', function() { +test('prepareValues: 1 BC date prepared properly', function () { helper.setTimezoneOffset(-330) // can't use the multi-argument constructor as year 0 would be interpreted as 1900 @@ -103,47 +103,47 @@ test('prepareValues: 1 BC date prepared properly', function() { helper.resetTimezoneOffset() }) -test('prepareValues: undefined prepared properly', function() { +test('prepareValues: undefined prepared properly', function () { var out = utils.prepareValue(void 0) assert.strictEqual(out, null) }) -test('prepareValue: null prepared properly', function() { +test('prepareValue: null prepared properly', function () { var out = utils.prepareValue(null) assert.strictEqual(out, null) }) -test('prepareValue: true prepared properly', function() { +test('prepareValue: true prepared properly', function () { var out = utils.prepareValue(true) assert.strictEqual(out, 'true') }) -test('prepareValue: false prepared properly', function() { +test('prepareValue: false prepared properly', function () { var out = utils.prepareValue(false) assert.strictEqual(out, 'false') }) -test('prepareValue: number prepared properly', function() { +test('prepareValue: number prepared properly', function () { var out = utils.prepareValue(3.042) assert.strictEqual(out, '3.042') }) -test('prepareValue: string prepared properly', function() { +test('prepareValue: string prepared properly', function () { var out = utils.prepareValue('big bad wolf') assert.strictEqual(out, 'big bad wolf') }) -test('prepareValue: simple array prepared properly', function() { +test('prepareValue: simple array prepared properly', function () { var out = utils.prepareValue([1, null, 3, undefined, [5, 6, 'squ,awk']]) assert.strictEqual(out, '{"1",NULL,"3",NULL,{"5","6","squ,awk"}}') }) -test('prepareValue: complex array prepared properly', function() { +test('prepareValue: complex array prepared properly', function () { var out = utils.prepareValue([{ x: 42 }, { y: 84 }]) assert.strictEqual(out, '{"{\\"x\\":42}","{\\"y\\":84}"}') }) -test('prepareValue: date array prepared properly', function() { +test('prepareValue: date array prepared properly', function () { helper.setTimezoneOffset(-330) var date = new Date(2014, 1, 1, 11, 11, 1, 7) @@ -153,14 +153,14 @@ test('prepareValue: date array prepared properly', function() { helper.resetTimezoneOffset() }) -test('prepareValue: arbitrary objects prepared properly', function() { +test('prepareValue: arbitrary objects prepared properly', function () { var out = utils.prepareValue({ x: 42 }) assert.strictEqual(out, '{"x":42}') }) -test('prepareValue: objects with simple toPostgres prepared properly', function() { +test('prepareValue: objects with simple toPostgres prepared properly', function () { var customType = { - toPostgres: function() { + toPostgres: function () { return 'zomgcustom!' }, } @@ -168,17 +168,17 @@ test('prepareValue: objects with simple toPostgres prepared properly', function( assert.strictEqual(out, 'zomgcustom!') }) -test('prepareValue: buffer array prepared properly', function() { +test('prepareValue: buffer array prepared properly', function () { var buffer1 = Buffer.from('dead', 'hex') var buffer2 = Buffer.from('beef', 'hex') var out = utils.prepareValue([buffer1, buffer2]) assert.strictEqual(out, '{\\\\xdead,\\\\xbeef}') }) -test('prepareValue: objects with complex toPostgres prepared properly', function() { +test('prepareValue: objects with complex toPostgres prepared properly', function () { var buf = Buffer.from('zomgcustom!') var customType = { - toPostgres: function() { + toPostgres: function () { return [1, 2] }, } @@ -186,19 +186,19 @@ test('prepareValue: objects with complex toPostgres prepared properly', function assert.strictEqual(out, '{"1","2"}') }) -test('prepareValue: objects with toPostgres receive prepareValue', function() { +test('prepareValue: objects with toPostgres receive prepareValue', function () { var customRange = { lower: { - toPostgres: function() { + toPostgres: function () { return 5 }, }, upper: { - toPostgres: function() { + toPostgres: function () { return 10 }, }, - toPostgres: function(prepare) { + toPostgres: function (prepare) { return '[' + prepare(this.lower) + ',' + prepare(this.upper) + ']' }, } @@ -206,12 +206,12 @@ test('prepareValue: objects with toPostgres receive prepareValue', function() { assert.strictEqual(out, '[5,10]') }) -test('prepareValue: objects with circular toPostgres rejected', function() { +test('prepareValue: objects with circular toPostgres rejected', function () { var buf = Buffer.from('zomgcustom!') var customType = { - toPostgres: function() { + toPostgres: function () { return { - toPostgres: function() { + toPostgres: function () { return customType }, } @@ -229,9 +229,9 @@ test('prepareValue: objects with circular toPostgres rejected', function() { throw new Error('Expected prepareValue to throw exception') }) -test('prepareValue: can safely be used to map an array of values including those with toPostgres functions', function() { +test('prepareValue: can safely be used to map an array of values including those with toPostgres functions', function () { var customType = { - toPostgres: function() { + toPostgres: function () { return 'zomgcustom!' }, } diff --git a/yarn.lock b/yarn.lock index a127d9cc6..f309fe973 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4632,10 +4632,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@1.19.1: - version "1.19.1" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" - integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== +prettier@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.4.tgz#2d1bae173e355996ee355ec9830a7a1ee05457ef" + integrity sha512-SVJIQ51spzFDvh4fIbCLvciiDMCrRhlN3mbZvv/+ycjvmF5E73bKdGfU8QDLNmjYJf+lsGnDBC4UUnvTe5OO0w== process-nextick-args@~2.0.0: version "2.0.1" From 12049b7dbcb3835c4757fa9e89be6f2486088435 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 10 Apr 2020 11:33:46 -0500 Subject: [PATCH 0623/1037] Actually run lint in ci --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9ab3733fc..dd32e85b6 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "packages/*" ], "scripts": { - "test": "yarn lerna exec yarn test", + "test": "yarn lint && yarn lerna exec yarn test", "build": "yarn lerna exec --scope pg-protocol yarn build", "pretest": "yarn build", "lint": "!([[ -e node_modules/.bin/prettier ]]) || eslint '*/**/*.{js,ts,tsx}'" From 3d9678e2e91e32d7aea022eab361fab0034f0fd5 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 10 Apr 2020 12:09:16 -0500 Subject: [PATCH 0624/1037] Remove packages from linting themselves in ci as its done at the 'top level' --- packages/pg-cursor/package.json | 3 +-- packages/pg-query-stream/package.json | 3 +-- packages/pg/package.json | 9 +-------- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 04f4d77eb..3ce12975d 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -7,8 +7,7 @@ "test": "test" }, "scripts": { - "test": "mocha && eslint .", - "lint": "eslint ." + "test": "mocha" }, "repository": { "type": "git", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 7f8f2f806..05a3f970d 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -4,8 +4,7 @@ "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { - "test": "mocha", - "lint": "eslint ." + "test": "mocha" }, "repository": { "type": "git", diff --git a/packages/pg/package.json b/packages/pg/package.json index 91e78d33f..5386ec2e8 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -32,18 +32,11 @@ "async": "0.9.0", "bluebird": "3.5.2", "co": "4.6.0", - "eslint": "^6.0.1", - "eslint-config-standard": "^13.0.1", - "eslint-plugin-import": "^2.18.1", - "eslint-plugin-node": "^9.1.0", - "eslint-plugin-promise": "^4.2.1", - "eslint-plugin-standard": "^4.0.0", "pg-copy-streams": "0.3.0" }, "minNativeVersion": "2.0.0", "scripts": { - "test": "make test-all", - "lint": "make lint" + "test": "make test-all" }, "files": [ "lib", From 7de8b49ad7d26dcb9f9fdd371ed6b99f596e03db Mon Sep 17 00:00:00 2001 From: Johan Levin Date: Wed, 15 Apr 2020 11:46:15 +0200 Subject: [PATCH 0625/1037] Refactor pg-pool to avoid potential memory leak Reduce the closure scope captured by the "release once" lambda function in _acquireClient so that it does not retain the pendingItem promise. --- packages/pg-pool/index.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 27875c1f8..eef490f91 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -252,16 +252,7 @@ class Pool extends EventEmitter { this.emit('acquire', client) - let released = false - - client.release = (err) => { - if (released) { - throwOnDoubleRelease() - } - - released = true - this._release(client, idleListener, err) - } + client.release = this._releaseOnce(client, idleListener) client.removeListener('error', idleListener) @@ -287,6 +278,20 @@ class Pool extends EventEmitter { } } + // returns a function that wraps _release and throws if called more than once + _releaseOnce(client, idleListener) { + let released = false + + return (err) => { + if (released) { + throwOnDoubleRelease() + } + + released = true + this._release(client, idleListener, err) + } + } + // release a client back to the poll, include an error // to remove it from the pool _release(client, idleListener, err) { From 149f48232445da0fb3022044e4f1c53509040ad3 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 21 Apr 2020 23:20:48 -0700 Subject: [PATCH 0626/1037] Replace uses of private/undocumented `readyState` API The `readyState` of a newly-created `net.Socket` changed from `'closed'` to `'open'` in Node 14.0.0, so this makes the JS driver work on Node 14. `Connection` now always calls `connect` on its `stream` when `connect` is called on it. --- packages/pg/lib/client.js | 2 +- packages/pg/lib/connection-fast.js | 11 ++++------ packages/pg/lib/connection.js | 11 ++++------ ...tream-and-query-error-interaction-tests.js | 3 +++ .../unit/connection/inbound-parser-tests.js | 1 - .../unit/connection/outbound-sending-tests.js | 1 + .../pg/test/unit/connection/startup-tests.js | 20 +------------------ packages/pg/test/unit/test-helper.js | 5 ++++- 8 files changed, 18 insertions(+), 36 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 04124f8a0..76906712b 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -566,7 +566,7 @@ Client.prototype.end = function (cb) { this._ending = true // if we have never connected, then end is a noop, callback immediately - if (this.connection.stream.readyState === 'closed') { + if (!this.connection._connecting) { if (cb) { cb() } else { diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index acc5c0e8c..6344b4174 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -42,13 +42,10 @@ util.inherits(Connection, EventEmitter) Connection.prototype.connect = function (port, host) { var self = this - if (this.stream.readyState === 'closed') { - this.stream.connect(port, host) - } else if (this.stream.readyState === 'open') { - this.emit('connect') - } + this._connecting = true + this.stream.connect(port, host) - this.stream.on('connect', function () { + this.stream.once('connect', function () { if (self._keepAlive) { self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis) } @@ -187,7 +184,7 @@ const endBuffer = serialize.end() Connection.prototype.end = function () { // 0x58 = 'X' this._ending = true - if (!this.stream.writable) { + if (!this._connecting || !this.stream.writable) { this.stream.end() return } diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 243872c93..c3f30aa0f 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -50,13 +50,10 @@ util.inherits(Connection, EventEmitter) Connection.prototype.connect = function (port, host) { var self = this - if (this.stream.readyState === 'closed') { - this.stream.connect(port, host) - } else if (this.stream.readyState === 'open') { - this.emit('connect') - } + this._connecting = true + this.stream.connect(port, host) - this.stream.on('connect', function () { + this.stream.once('connect', function () { if (self._keepAlive) { self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis) } @@ -316,7 +313,7 @@ Connection.prototype.end = function () { // 0x58 = 'X' this.writer.add(emptyBuffer) this._ending = true - if (!this.stream.writable) { + if (!this._connecting || !this.stream.writable) { this.stream.end() return } diff --git a/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js index 9b0a3560b..041af010d 100644 --- a/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js +++ b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js @@ -5,6 +5,9 @@ var Client = require(__dirname + '/../../../lib/client') test('emits end when not in query', function () { var stream = new (require('events').EventEmitter)() + stream.connect = function () { + // NOOP + } stream.write = function () { // NOOP } diff --git a/packages/pg/test/unit/connection/inbound-parser-tests.js b/packages/pg/test/unit/connection/inbound-parser-tests.js index 5f92cdc52..f3690cc63 100644 --- a/packages/pg/test/unit/connection/inbound-parser-tests.js +++ b/packages/pg/test/unit/connection/inbound-parser-tests.js @@ -399,7 +399,6 @@ test('Connection', function () { test('split buffer, single message parsing', function () { var fullBuffer = buffers.dataRow([null, 'bang', 'zug zug', null, '!']) var stream = new MemoryStream() - stream.readyState = 'open' var client = new Connection({ stream: stream, }) diff --git a/packages/pg/test/unit/connection/outbound-sending-tests.js b/packages/pg/test/unit/connection/outbound-sending-tests.js index b40af0005..8b21de4ce 100644 --- a/packages/pg/test/unit/connection/outbound-sending-tests.js +++ b/packages/pg/test/unit/connection/outbound-sending-tests.js @@ -5,6 +5,7 @@ var stream = new MemoryStream() var con = new Connection({ stream: stream, }) +con._connecting = true assert.received = function (stream, buffer) { assert.lengthIs(stream.packets, 1) diff --git a/packages/pg/test/unit/connection/startup-tests.js b/packages/pg/test/unit/connection/startup-tests.js index 09a710c7a..6e317d70f 100644 --- a/packages/pg/test/unit/connection/startup-tests.js +++ b/packages/pg/test/unit/connection/startup-tests.js @@ -7,10 +7,9 @@ test('connection can take existing stream', function () { assert.equal(con.stream, stream) }) -test('using closed stream', function () { +test('using any stream', function () { var makeStream = function () { var stream = new MemoryStream() - stream.readyState = 'closed' stream.connect = function (port, host) { this.connectCalled = true this.port = port @@ -65,20 +64,3 @@ test('using closed stream', function () { }) }) }) - -test('using opened stream', function () { - var stream = new MemoryStream() - stream.readyState = 'open' - stream.connect = function () { - assert.ok(false, 'Should not call open') - } - var con = new Connection({ stream: stream }) - test('does not call open', function () { - var hit = false - con.once('connect', function () { - hit = true - }) - con.connect() - assert.ok(hit) - }) -}) diff --git a/packages/pg/test/unit/test-helper.js b/packages/pg/test/unit/test-helper.js index 5793251b5..918b14187 100644 --- a/packages/pg/test/unit/test-helper.js +++ b/packages/pg/test/unit/test-helper.js @@ -13,6 +13,10 @@ helper.sys.inherits(MemoryStream, EventEmitter) var p = MemoryStream.prototype +p.connect = function () { + // NOOP +} + p.write = function (packet, cb) { this.packets.push(packet) if (cb) { @@ -30,7 +34,6 @@ p.writable = true const createClient = function () { var stream = new MemoryStream() - stream.readyState = 'open' var client = new Client({ connection: new Connection({ stream: stream }), }) From c8fb4168d48b70753d38bb0b05867efcdeaa3b31 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 21 Apr 2020 23:23:52 -0700 Subject: [PATCH 0627/1037] Add Node 14 to CI --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 579ad5ac9..0518579d7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ node_js: # if 13.8 still has this problem when it comes down I'll talk to the node team about the change # in the mean time...peg to 13.6 - 13.6 + - 14 addons: postgresql: "10" From a86cb900434291f8c5c5f474cc543ee9d771db99 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 22 Apr 2020 11:04:14 -0500 Subject: [PATCH 0628/1037] lockfile --- yarn.lock | 204 ++---------------------------------------------------- 1 file changed, 6 insertions(+), 198 deletions(-) diff --git a/yarn.lock b/yarn.lock index f309fe973..0d9360977 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1098,14 +1098,6 @@ array-ify@^1.0.0: resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece" integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4= -array-includes@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.0.tgz#48a929ef4c6bb1fa6dc4a92c9b023a261b0ca404" - integrity sha512-ONOEQoKrvXPKk7Su92Co0YMqYO32FfqJTzkKU9u2UpIXyYZIzLSvpdg4AwvSw4mSUW0czu6inK+zby6Oj6gDjQ== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.0" - array-union@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" @@ -1123,14 +1115,6 @@ array-unique@^0.3.2: resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= -array.prototype.flat@^1.2.1: - version "1.2.3" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz#0de82b426b0318dbfdb940089e38b043d37f6c7b" - integrity sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -1637,11 +1621,6 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -contains-path@^0.1.0: - version "0.1.0" - resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" - integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= - conventional-changelog-angular@^5.0.3: version "5.0.6" resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.6.tgz#269540c624553aded809c29a3508fdc2b544c059" @@ -1818,7 +1797,7 @@ debug@3.2.6, debug@^3.1.0: dependencies: ms "^2.1.1" -debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: +debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -1953,14 +1932,6 @@ dir-glob@^2.2.2: dependencies: path-type "^3.0.0" -doctrine@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" - integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= - dependencies: - esutils "^2.0.2" - isarray "^1.0.0" - doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -2046,7 +2017,7 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.17.0-next.0, es-abstract@^1.17.0-next.1: +es-abstract@^1.17.0-next.1: version "1.17.0-next.1" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0-next.1.tgz#94acc93e20b05a6e96dacb5ab2f1cb3a81fc2172" integrity sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw== @@ -2096,35 +2067,6 @@ eslint-config-prettier@^6.10.1: dependencies: get-stdin "^6.0.0" -eslint-config-standard@^13.0.1: - version "13.0.1" - resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-13.0.1.tgz#c9c6ffe0cfb8a51535bc5c7ec9f70eafb8c6b2c0" - integrity sha512-zLKp4QOgq6JFgRm1dDCVv1Iu0P5uZ4v5Wa4DTOkg2RFMxdCX/9Qf7lz9ezRj2dBRa955cWQF/O/LWEiYWAHbTw== - -eslint-import-resolver-node@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" - integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== - dependencies: - debug "^2.6.9" - resolve "^1.5.0" - -eslint-module-utils@^2.4.1: - version "2.5.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.5.0.tgz#cdf0b40d623032274ccd2abd7e64c4e524d6e19c" - integrity sha512-kCo8pZaNz2dsAW7nCUjuVoI11EBXXpIzfNxmaoLhXoRDOnqXLC4iSGVRdZPhOitfbdEfMEfKOiENaK6wDPZEGw== - dependencies: - debug "^2.6.9" - pkg-dir "^2.0.0" - -eslint-plugin-es@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-1.4.1.tgz#12acae0f4953e76ba444bfd1b2271081ac620998" - integrity sha512-5fa/gR2yR3NxQf+UXkeLeP8FBBl6tSgdrAz1+cF84v1FMM4twGwQoqTnn+QxFLcPOrF4pdKEJKDB/q9GoyJrCA== - dependencies: - eslint-utils "^1.4.2" - regexpp "^2.0.1" - eslint-plugin-es@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.0.tgz#98cb1bc8ab0aa807977855e11ad9d1c9422d014b" @@ -2133,24 +2075,6 @@ eslint-plugin-es@^3.0.0: eslint-utils "^2.0.0" regexpp "^3.0.0" -eslint-plugin-import@^2.18.1: - version "2.19.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.19.1.tgz#5654e10b7839d064dd0d46cd1b88ec2133a11448" - integrity sha512-x68131aKoCZlCae7rDXKSAQmbT5DQuManyXo2sK6fJJ0aK5CWAkv6A6HJZGgqC8IhjQxYPgo6/IY4Oz8AFsbBw== - dependencies: - array-includes "^3.0.3" - array.prototype.flat "^1.2.1" - contains-path "^0.1.0" - debug "^2.6.9" - doctrine "1.5.0" - eslint-import-resolver-node "^0.3.2" - eslint-module-utils "^2.4.1" - has "^1.0.3" - minimatch "^3.0.4" - object.values "^1.1.0" - read-pkg-up "^2.0.0" - resolve "^1.12.0" - eslint-plugin-node@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-11.1.0.tgz#c95544416ee4ada26740a30474eefc5402dc671d" @@ -2163,18 +2087,6 @@ eslint-plugin-node@^11.1.0: resolve "^1.10.1" semver "^6.1.0" -eslint-plugin-node@^9.1.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-9.2.0.tgz#b1911f111002d366c5954a6d96d3cd5bf2a3036a" - integrity sha512-2abNmzAH/JpxI4gEOwd6K8wZIodK3BmHbTxz4s79OIYwwIt2gkpEXlAouJXu4H1c9ySTnRso0tsuthSOZbUMlA== - dependencies: - eslint-plugin-es "^1.4.1" - eslint-utils "^1.4.2" - ignore "^5.1.1" - minimatch "^3.0.4" - resolve "^1.10.1" - semver "^6.1.0" - eslint-plugin-prettier@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz#432e5a667666ab84ce72f945c72f77d996a5c9ba" @@ -2187,16 +2099,6 @@ eslint-plugin-promise@^3.5.0: resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621" integrity sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ== -eslint-plugin-promise@^4.2.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.2.1.tgz#845fd8b2260ad8f82564c1222fce44ad71d9418a" - integrity sha512-VoM09vT7bfA7D+upt+FjeBO5eHIJQBUWki1aPvB+vbNiHS3+oGIJGIeyBtKQTME6UPXXy3vV07OL1tHd3ANuDw== - -eslint-plugin-standard@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.1.tgz#ff0519f7ffaff114f76d1bd7c3996eef0f6e20b4" - integrity sha512-v/KBnfyaOMPmZc/dmc6ozOdWqekGp7bBGq4jLAecEfPGmfKiWS4sA8sC0LqiV9w5qmXAtXVn4M3p1jSyhY85SQ== - eslint-scope@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" @@ -2205,7 +2107,7 @@ eslint-scope@^5.0.0: esrecurse "^4.1.0" estraverse "^4.1.1" -eslint-utils@^1.4.2, eslint-utils@^1.4.3: +eslint-utils@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== @@ -2224,49 +2126,6 @@ eslint-visitor-keys@^1.1.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== -eslint@^6.0.1: - version "6.7.2" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.7.2.tgz#c17707ca4ad7b2d8af986a33feba71e18a9fecd1" - integrity sha512-qMlSWJaCSxDFr8fBPvJM9kJwbazrhNcBU3+DszDW1OlEwKBBRWsJc7NJFelvwQpanHCR14cOLD41x8Eqvo3Nng== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob-parent "^5.0.0" - globals "^12.1.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^7.0.0" - is-glob "^4.0.0" - js-yaml "^3.13.1" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.3" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" - table "^5.2.3" - text-table "^0.2.0" - v8-compile-cache "^2.0.3" - eslint@^6.8.0: version "6.8.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" @@ -2520,7 +2379,7 @@ find-up@^1.0.0: path-exists "^2.0.0" pinkie-promise "^2.0.0" -find-up@^2.0.0, find-up@^2.1.0: +find-up@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= @@ -3351,7 +3210,7 @@ is-windows@^1.0.0, is-windows@^1.0.2: resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== -isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: +isarray@1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= @@ -3519,16 +3378,6 @@ load-json-file@^1.0.0: pinkie-promise "^2.0.0" strip-bom "^2.0.0" -load-json-file@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-2.0.0.tgz#7947e42149af80d696cbf797bcaabcfe1fe29ca8" - integrity sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg= - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - strip-bom "^3.0.0" - load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" @@ -4224,16 +4073,6 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" -object.values@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" - integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - function-bind "^1.1.1" - has "^1.0.3" - octokit-pagination-methods@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4" @@ -4490,13 +4329,6 @@ path-type@^1.0.0: pify "^2.0.0" pinkie-promise "^2.0.0" -path-type@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-2.0.0.tgz#f012ccb8415b7096fc2daa1054c3d72389594c73" - integrity sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM= - dependencies: - pify "^2.0.0" - path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -4579,13 +4411,6 @@ pinkie@^2.0.0: resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= -pkg-dir@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-2.0.0.tgz#f6d5d1109e19d63edf428e0bd57e12777615334b" - integrity sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s= - dependencies: - find-up "^2.1.0" - pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" @@ -4775,14 +4600,6 @@ read-pkg-up@^1.0.1: find-up "^1.0.0" read-pkg "^1.0.0" -read-pkg-up@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz#6b72a8048984e0c41e79510fd5e9fa99b3b549be" - integrity sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4= - dependencies: - find-up "^2.0.0" - read-pkg "^2.0.0" - read-pkg-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-3.0.0.tgz#3ed496685dba0f8fe118d0691dc51f4a1ff96f07" @@ -4800,15 +4617,6 @@ read-pkg@^1.0.0: normalize-package-data "^2.3.2" path-type "^1.0.0" -read-pkg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-2.0.0.tgz#8ef1c0623c6a6db0dc6713c4bfac46332b2368f8" - integrity sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg= - dependencies: - load-json-file "^2.0.0" - normalize-package-data "^2.3.2" - path-type "^2.0.0" - read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -4973,7 +4781,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.10.0, resolve@^1.10.1, resolve@^1.12.0, resolve@^1.5.0: +resolve@^1.10.0, resolve@^1.10.1: version "1.14.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.0.tgz#6d14c6f9db9f8002071332b600039abf82053f64" integrity sha512-uviWSi5N67j3t3UKFxej1loCH0VZn5XuqdNxoLShPcYPw6cUZn74K1VRj+9myynRX03bxIBEkwlkob/ujLsJVw== From 35328807e3612cb267bee86dccb2551ad186624a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 22 Apr 2020 11:04:51 -0500 Subject: [PATCH 0629/1037] Publish - pg-cursor@2.1.10 - pg-pool@3.1.1 - pg-protocol@1.2.2 - pg-query-stream@3.0.7 - pg@8.0.3 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 3ce12975d..d4bbec5cf 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.1.9", + "version": "2.1.10", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -17,6 +17,6 @@ "license": "MIT", "devDependencies": { "mocha": "^6.2.2", - "pg": "^8.0.2" + "pg": "^8.0.3" } } diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 4eb998ed1..fdb95a960 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.1.0", + "version": "3.1.1", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 476941dd4..60bc2027d 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.2.1", + "version": "1.2.2", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 05a3f970d..fd828f82d 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.0.6", + "version": "3.0.7", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -26,12 +26,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^6.2.2", - "pg": "^8.0.2", + "pg": "^8.0.3", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.1.9" + "pg-cursor": "^2.1.10" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 5386ec2e8..da8a75f26 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.0.2", + "version": "8.0.3", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -22,8 +22,8 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "0.1.3", - "pg-pool": "^3.1.0", - "pg-protocol": "^1.2.1", + "pg-pool": "^3.1.1", + "pg-protocol": "^1.2.2", "pg-types": "^2.1.0", "pgpass": "1.x", "semver": "4.3.2" From 3a831fc77c8f65353e72d3120be5e3d8d197a1b3 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 28 Apr 2020 10:02:38 -0500 Subject: [PATCH 0630/1037] Run lint --fix --- packages/pg-connection-string/index.d.ts | 20 +- packages/pg-connection-string/index.js | 72 +-- packages/pg-connection-string/test/parse.js | 491 ++++++++++---------- yarn.lock | 336 +++++++++++++- 4 files changed, 629 insertions(+), 290 deletions(-) diff --git a/packages/pg-connection-string/index.d.ts b/packages/pg-connection-string/index.d.ts index 1d2f1606e..b1b7abd9c 100644 --- a/packages/pg-connection-string/index.d.ts +++ b/packages/pg-connection-string/index.d.ts @@ -1,14 +1,14 @@ -export function parse(connectionString: string): ConnectionOptions; +export function parse(connectionString: string): ConnectionOptions export interface ConnectionOptions { - host: string | null; - password?: string; - user?: string; - port?: string | null; - database: string | null | undefined; - client_encoding?: string; - ssl?: boolean | string; + host: string | null + password?: string + user?: string + port?: string | null + database: string | null | undefined + client_encoding?: string + ssl?: boolean | string - application_name?: string; - fallback_application_name?: string; + application_name?: string + fallback_application_name?: string } diff --git a/packages/pg-connection-string/index.js b/packages/pg-connection-string/index.js index 7e914ba1b..65951c374 100644 --- a/packages/pg-connection-string/index.js +++ b/packages/pg-connection-string/index.js @@ -1,7 +1,7 @@ -'use strict'; +'use strict' -var url = require('url'); -var fs = require('fs'); +var url = require('url') +var fs = require('fs') //Parse method copied from https://github.com/brianc/node-postgres //Copyright (c) 2010-2014 Brian Carlson (brian.m.carlson@gmail.com) @@ -10,78 +10,80 @@ var fs = require('fs'); //parses a connection string function parse(str) { //unix socket - if(str.charAt(0) === '/') { - var config = str.split(' '); - return { host: config[0], database: config[1] }; + if (str.charAt(0) === '/') { + var config = str.split(' ') + return { host: config[0], database: config[1] } } // url parse expects spaces encoded as %20 - var result = url.parse(/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str) ? encodeURI(str).replace(/\%25(\d\d)/g, "%$1") : str, true); - var config = result.query; + var result = url.parse( + / |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str) ? encodeURI(str).replace(/\%25(\d\d)/g, '%$1') : str, + true + ) + var config = result.query for (var k in config) { if (Array.isArray(config[k])) { - config[k] = config[k][config[k].length-1]; + config[k] = config[k][config[k].length - 1] } } - var auth = (result.auth || ':').split(':'); - config.user = auth[0]; - config.password = auth.splice(1).join(':'); + var auth = (result.auth || ':').split(':') + config.user = auth[0] + config.password = auth.splice(1).join(':') - config.port = result.port; - if(result.protocol == 'socket:') { - config.host = decodeURI(result.pathname); - config.database = result.query.db; - config.client_encoding = result.query.encoding; - return config; + config.port = result.port + if (result.protocol == 'socket:') { + config.host = decodeURI(result.pathname) + config.database = result.query.db + config.client_encoding = result.query.encoding + return config } if (!config.host) { // Only set the host if there is no equivalent query param. - config.host = result.hostname; + config.host = result.hostname } // If the host is missing it might be a URL-encoded path to a socket. - var pathname = result.pathname; + var pathname = result.pathname if (!config.host && pathname && /^%2f/i.test(pathname)) { - var pathnameSplit = pathname.split('/'); - config.host = decodeURIComponent(pathnameSplit[0]); - pathname = pathnameSplit.splice(1).join('/'); + var pathnameSplit = pathname.split('/') + config.host = decodeURIComponent(pathnameSplit[0]) + pathname = pathnameSplit.splice(1).join('/') } // result.pathname is not always guaranteed to have a '/' prefix (e.g. relative urls) // only strip the slash if it is present. if (pathname && pathname.charAt(0) === '/') { - pathname = pathname.slice(1) || null; + pathname = pathname.slice(1) || null } - config.database = pathname && decodeURI(pathname); + config.database = pathname && decodeURI(pathname) if (config.ssl === 'true' || config.ssl === '1') { - config.ssl = true; + config.ssl = true } if (config.ssl === '0') { - config.ssl = false; + config.ssl = false } if (config.sslcert || config.sslkey || config.sslrootcert) { - config.ssl = {}; + config.ssl = {} } if (config.sslcert) { - config.ssl.cert = fs.readFileSync(config.sslcert).toString(); + config.ssl.cert = fs.readFileSync(config.sslcert).toString() } if (config.sslkey) { - config.ssl.key = fs.readFileSync(config.sslkey).toString(); + config.ssl.key = fs.readFileSync(config.sslkey).toString() } if (config.sslrootcert) { - config.ssl.ca = fs.readFileSync(config.sslrootcert).toString(); + config.ssl.ca = fs.readFileSync(config.sslrootcert).toString() } - return config; + return config } +module.exports = parse -module.exports = parse; - -parse.parse = parse; +parse.parse = parse diff --git a/packages/pg-connection-string/test/parse.js b/packages/pg-connection-string/test/parse.js index 07f886e1f..957f06441 100644 --- a/packages/pg-connection-string/test/parse.js +++ b/packages/pg-connection-string/test/parse.js @@ -1,257 +1,274 @@ -'use strict'; - -var chai = require('chai'); -var expect = chai.expect; -chai.should(); - -var parse = require('../').parse; - -describe('parse', function(){ - - it('using connection string in client constructor', function(){ - var subject = parse('postgres://brian:pw@boom:381/lala'); - subject.user.should.equal('brian'); - subject.password.should.equal( 'pw'); - subject.host.should.equal( 'boom'); - subject.port.should.equal( '381'); - subject.database.should.equal( 'lala'); - }); - - it('escape spaces if present', function(){ - var subject = parse('postgres://localhost/post gres'); - subject.database.should.equal('post gres'); - }); - - it('do not double escape spaces', function(){ - var subject = parse('postgres://localhost/post%20gres'); - subject.database.should.equal('post gres'); - }); - - it('initializing with unix domain socket', function(){ - var subject = parse('/var/run/'); - subject.host.should.equal('/var/run/'); - }); - - it('initializing with unix domain socket and a specific database, the simple way', function(){ - var subject = parse('/var/run/ mydb'); - subject.host.should.equal('/var/run/'); - subject.database.should.equal('mydb'); - }); - - it('initializing with unix domain socket, the health way', function(){ - var subject = parse('socket:/some path/?db=my[db]&encoding=utf8'); - subject.host.should.equal('/some path/'); - subject.database.should.equal('my[db]', 'must to be escaped and unescaped trough "my%5Bdb%5D"'); - subject.client_encoding.should.equal('utf8'); - }); - - it('initializing with unix domain socket, the escaped health way', function(){ - var subject = parse('socket:/some%20path/?db=my%2Bdb&encoding=utf8'); - subject.host.should.equal('/some path/'); - subject.database.should.equal('my+db'); - subject.client_encoding.should.equal('utf8'); - }); - - it('initializing with unix domain socket, username and password', function(){ - var subject = parse('socket://brian:pw@/var/run/?db=mydb'); - subject.user.should.equal('brian'); - subject.password.should.equal('pw'); - subject.host.should.equal('/var/run/'); - subject.database.should.equal('mydb'); - }); - - it('password contains < and/or > characters', function(){ +'use strict' + +var chai = require('chai') +var expect = chai.expect +chai.should() + +var parse = require('../').parse + +describe('parse', function () { + it('using connection string in client constructor', function () { + var subject = parse('postgres://brian:pw@boom:381/lala') + subject.user.should.equal('brian') + subject.password.should.equal('pw') + subject.host.should.equal('boom') + subject.port.should.equal('381') + subject.database.should.equal('lala') + }) + + it('escape spaces if present', function () { + var subject = parse('postgres://localhost/post gres') + subject.database.should.equal('post gres') + }) + + it('do not double escape spaces', function () { + var subject = parse('postgres://localhost/post%20gres') + subject.database.should.equal('post gres') + }) + + it('initializing with unix domain socket', function () { + var subject = parse('/var/run/') + subject.host.should.equal('/var/run/') + }) + + it('initializing with unix domain socket and a specific database, the simple way', function () { + var subject = parse('/var/run/ mydb') + subject.host.should.equal('/var/run/') + subject.database.should.equal('mydb') + }) + + it('initializing with unix domain socket, the health way', function () { + var subject = parse('socket:/some path/?db=my[db]&encoding=utf8') + subject.host.should.equal('/some path/') + subject.database.should.equal('my[db]', 'must to be escaped and unescaped trough "my%5Bdb%5D"') + subject.client_encoding.should.equal('utf8') + }) + + it('initializing with unix domain socket, the escaped health way', function () { + var subject = parse('socket:/some%20path/?db=my%2Bdb&encoding=utf8') + subject.host.should.equal('/some path/') + subject.database.should.equal('my+db') + subject.client_encoding.should.equal('utf8') + }) + + it('initializing with unix domain socket, username and password', function () { + var subject = parse('socket://brian:pw@/var/run/?db=mydb') + subject.user.should.equal('brian') + subject.password.should.equal('pw') + subject.host.should.equal('/var/run/') + subject.database.should.equal('mydb') + }) + + it('password contains < and/or > characters', function () { var sourceConfig = { - user:'brian', + user: 'brian', password: 'helloe', port: 5432, host: 'localhost', - database: 'postgres' - }; - var connectionString = 'postgres://' + sourceConfig.user + ':' + sourceConfig.password + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database; - var subject = parse(connectionString); - subject.password.should.equal(sourceConfig.password); - }); - - it('password contains colons', function(){ + database: 'postgres', + } + var connectionString = + 'postgres://' + + sourceConfig.user + + ':' + + sourceConfig.password + + '@' + + sourceConfig.host + + ':' + + sourceConfig.port + + '/' + + sourceConfig.database + var subject = parse(connectionString) + subject.password.should.equal(sourceConfig.password) + }) + + it('password contains colons', function () { var sourceConfig = { - user:'brian', + user: 'brian', password: 'hello:pass:world', port: 5432, host: 'localhost', - database: 'postgres' - }; - var connectionString = 'postgres://' + sourceConfig.user + ':' + sourceConfig.password + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database; - var subject = parse(connectionString); - subject.password.should.equal(sourceConfig.password); - }); - - it('username or password contains weird characters', function(){ - var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000'; - var subject = parse(strang); - subject.user.should.equal('my f%irst name'); - subject.password.should.equal('is&%awesome!'); - subject.host.should.equal('localhost'); - }); - - it('url is properly encoded', function(){ - var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl'; - var subject = parse(encoded); - subject.user.should.equal('bi%na%%ry '); - subject.password.should.equal('s@f#'); - subject.host.should.equal('localhost'); - subject.database.should.equal(' u%20rl'); - }); - - it('relative url sets database', function(){ - var relative = 'different_db_on_default_host'; - var subject = parse(relative); - subject.database.should.equal('different_db_on_default_host'); - }); + database: 'postgres', + } + var connectionString = + 'postgres://' + + sourceConfig.user + + ':' + + sourceConfig.password + + '@' + + sourceConfig.host + + ':' + + sourceConfig.port + + '/' + + sourceConfig.database + var subject = parse(connectionString) + subject.password.should.equal(sourceConfig.password) + }) + + it('username or password contains weird characters', function () { + var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000' + var subject = parse(strang) + subject.user.should.equal('my f%irst name') + subject.password.should.equal('is&%awesome!') + subject.host.should.equal('localhost') + }) + + it('url is properly encoded', function () { + var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl' + var subject = parse(encoded) + subject.user.should.equal('bi%na%%ry ') + subject.password.should.equal('s@f#') + subject.host.should.equal('localhost') + subject.database.should.equal(' u%20rl') + }) + + it('relative url sets database', function () { + var relative = 'different_db_on_default_host' + var subject = parse(relative) + subject.database.should.equal('different_db_on_default_host') + }) it('no pathname returns null database', function () { - var subject = parse('pg://myhost'); - (subject.database === null).should.equal(true); - }); + var subject = parse('pg://myhost') + ;(subject.database === null).should.equal(true) + }) it('pathname of "/" returns null database', function () { - var subject = parse('pg://myhost/'); - subject.host.should.equal('myhost'); - (subject.database === null).should.equal(true); - }); - - it('configuration parameter host', function() { - var subject = parse('pg://user:pass@/dbname?host=/unix/socket'); - subject.user.should.equal('user'); - subject.password.should.equal('pass'); - subject.host.should.equal('/unix/socket'); - subject.database.should.equal('dbname'); - }); - - it('configuration parameter host overrides url host', function() { - var subject = parse('pg://user:pass@localhost/dbname?host=/unix/socket'); - subject.host.should.equal('/unix/socket'); - }); - - it('url with encoded socket', function() { - var subject = parse('pg://user:pass@%2Funix%2Fsocket/dbname'); - subject.user.should.equal('user'); - subject.password.should.equal('pass'); - subject.host.should.equal('/unix/socket'); - subject.database.should.equal('dbname'); - }); - - it('url with real host and an encoded db name', function() { - var subject = parse('pg://user:pass@localhost/%2Fdbname'); - subject.user.should.equal('user'); - subject.password.should.equal('pass'); - subject.host.should.equal('localhost'); - subject.database.should.equal('%2Fdbname'); - }); - - it('configuration parameter host treats encoded socket as part of the db name', function() { - var subject = parse('pg://user:pass@%2Funix%2Fsocket/dbname?host=localhost'); - subject.user.should.equal('user'); - subject.password.should.equal('pass'); - subject.host.should.equal('localhost'); - subject.database.should.equal('%2Funix%2Fsocket/dbname'); - }); - - it('configuration parameter application_name', function(){ - var connectionString = 'pg:///?application_name=TheApp'; - var subject = parse(connectionString); - subject.application_name.should.equal('TheApp'); - }); - - it('configuration parameter fallback_application_name', function(){ - var connectionString = 'pg:///?fallback_application_name=TheAppFallback'; - var subject = parse(connectionString); - subject.fallback_application_name.should.equal('TheAppFallback'); - }); - - it('configuration parameter fallback_application_name', function(){ - var connectionString = 'pg:///?fallback_application_name=TheAppFallback'; - var subject = parse(connectionString); - subject.fallback_application_name.should.equal('TheAppFallback'); - }); - - it('configuration parameter ssl=true', function(){ - var connectionString = 'pg:///?ssl=true'; - var subject = parse(connectionString); - subject.ssl.should.equal(true); - }); - - it('configuration parameter ssl=1', function(){ - var connectionString = 'pg:///?ssl=1'; - var subject = parse(connectionString); - subject.ssl.should.equal(true); - }); - - it('configuration parameter ssl=0', function(){ - var connectionString = 'pg:///?ssl=0'; - var subject = parse(connectionString); - subject.ssl.should.equal(false); - }); + var subject = parse('pg://myhost/') + subject.host.should.equal('myhost') + ;(subject.database === null).should.equal(true) + }) + + it('configuration parameter host', function () { + var subject = parse('pg://user:pass@/dbname?host=/unix/socket') + subject.user.should.equal('user') + subject.password.should.equal('pass') + subject.host.should.equal('/unix/socket') + subject.database.should.equal('dbname') + }) + + it('configuration parameter host overrides url host', function () { + var subject = parse('pg://user:pass@localhost/dbname?host=/unix/socket') + subject.host.should.equal('/unix/socket') + }) + + it('url with encoded socket', function () { + var subject = parse('pg://user:pass@%2Funix%2Fsocket/dbname') + subject.user.should.equal('user') + subject.password.should.equal('pass') + subject.host.should.equal('/unix/socket') + subject.database.should.equal('dbname') + }) + + it('url with real host and an encoded db name', function () { + var subject = parse('pg://user:pass@localhost/%2Fdbname') + subject.user.should.equal('user') + subject.password.should.equal('pass') + subject.host.should.equal('localhost') + subject.database.should.equal('%2Fdbname') + }) + + it('configuration parameter host treats encoded socket as part of the db name', function () { + var subject = parse('pg://user:pass@%2Funix%2Fsocket/dbname?host=localhost') + subject.user.should.equal('user') + subject.password.should.equal('pass') + subject.host.should.equal('localhost') + subject.database.should.equal('%2Funix%2Fsocket/dbname') + }) + + it('configuration parameter application_name', function () { + var connectionString = 'pg:///?application_name=TheApp' + var subject = parse(connectionString) + subject.application_name.should.equal('TheApp') + }) + + it('configuration parameter fallback_application_name', function () { + var connectionString = 'pg:///?fallback_application_name=TheAppFallback' + var subject = parse(connectionString) + subject.fallback_application_name.should.equal('TheAppFallback') + }) + + it('configuration parameter fallback_application_name', function () { + var connectionString = 'pg:///?fallback_application_name=TheAppFallback' + var subject = parse(connectionString) + subject.fallback_application_name.should.equal('TheAppFallback') + }) + + it('configuration parameter ssl=true', function () { + var connectionString = 'pg:///?ssl=true' + var subject = parse(connectionString) + subject.ssl.should.equal(true) + }) + + it('configuration parameter ssl=1', function () { + var connectionString = 'pg:///?ssl=1' + var subject = parse(connectionString) + subject.ssl.should.equal(true) + }) + + it('configuration parameter ssl=0', function () { + var connectionString = 'pg:///?ssl=0' + var subject = parse(connectionString) + subject.ssl.should.equal(false) + }) it('set ssl', function () { - var subject = parse('pg://myhost/db?ssl=1'); - subject.ssl.should.equal(true); - }); + var subject = parse('pg://myhost/db?ssl=1') + subject.ssl.should.equal(true) + }) - it('configuration parameter sslcert=/path/to/cert', function(){ - var connectionString = 'pg:///?sslcert=' + __dirname + '/example.cert'; - var subject = parse(connectionString); + it('configuration parameter sslcert=/path/to/cert', function () { + var connectionString = 'pg:///?sslcert=' + __dirname + '/example.cert' + var subject = parse(connectionString) subject.ssl.should.eql({ - cert: 'example cert\n' - }); - }); + cert: 'example cert\n', + }) + }) - it('configuration parameter sslkey=/path/to/key', function(){ - var connectionString = 'pg:///?sslkey=' + __dirname + '/example.key'; - var subject = parse(connectionString); + it('configuration parameter sslkey=/path/to/key', function () { + var connectionString = 'pg:///?sslkey=' + __dirname + '/example.key' + var subject = parse(connectionString) subject.ssl.should.eql({ - key: 'example key\n' - }); - }); + key: 'example key\n', + }) + }) - it('configuration parameter sslrootcert=/path/to/ca', function(){ - var connectionString = 'pg:///?sslrootcert=' + __dirname + '/example.ca'; - var subject = parse(connectionString); + it('configuration parameter sslrootcert=/path/to/ca', function () { + var connectionString = 'pg:///?sslrootcert=' + __dirname + '/example.ca' + var subject = parse(connectionString) subject.ssl.should.eql({ - ca: 'example ca\n' - }); - }); - - it('allow other params like max, ...', function () { - var subject = parse('pg://myhost/db?max=18&min=4'); - subject.max.should.equal('18'); - subject.min.should.equal('4'); - }); - - - it('configuration parameter keepalives', function(){ - var connectionString = 'pg:///?keepalives=1'; - var subject = parse(connectionString); - subject.keepalives.should.equal('1'); - }); - - it('unknown configuration parameter is passed into client', function(){ - var connectionString = 'pg:///?ThereIsNoSuchPostgresParameter=1234'; - var subject = parse(connectionString); - subject.ThereIsNoSuchPostgresParameter.should.equal('1234'); - }); - - it('do not override a config field with value from query string', function(){ - var subject = parse('socket:/some path/?db=my[db]&encoding=utf8&client_encoding=bogus'); - subject.host.should.equal('/some path/'); - subject.database.should.equal('my[db]', 'must to be escaped and unescaped through "my%5Bdb%5D"'); - subject.client_encoding.should.equal('utf8'); - }); - - - it('return last value of repeated parameter', function(){ - var connectionString = 'pg:///?keepalives=1&keepalives=0'; - var subject = parse(connectionString); - subject.keepalives.should.equal('0'); - }); -}); + ca: 'example ca\n', + }) + }) + + it('allow other params like max, ...', function () { + var subject = parse('pg://myhost/db?max=18&min=4') + subject.max.should.equal('18') + subject.min.should.equal('4') + }) + + it('configuration parameter keepalives', function () { + var connectionString = 'pg:///?keepalives=1' + var subject = parse(connectionString) + subject.keepalives.should.equal('1') + }) + + it('unknown configuration parameter is passed into client', function () { + var connectionString = 'pg:///?ThereIsNoSuchPostgresParameter=1234' + var subject = parse(connectionString) + subject.ThereIsNoSuchPostgresParameter.should.equal('1234') + }) + + it('do not override a config field with value from query string', function () { + var subject = parse('socket:/some path/?db=my[db]&encoding=utf8&client_encoding=bogus') + subject.host.should.equal('/some path/') + subject.database.should.equal('my[db]', 'must to be escaped and unescaped through "my%5Bdb%5D"') + subject.client_encoding.should.equal('utf8') + }) + + it('return last value of repeated parameter', function () { + var connectionString = 'pg:///?keepalives=1&keepalives=0' + var subject = parse(connectionString) + subject.keepalives.should.equal('0') + }) +}) diff --git a/yarn.lock b/yarn.lock index 0d9360977..796307ce2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -948,6 +948,11 @@ abbrev@1: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abbrev@1.0.x: + version "1.0.9" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" + integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= + acorn-jsx@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" @@ -989,6 +994,11 @@ ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +amdefine@>=0.0.4: + version "1.0.1" + resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" + integrity sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU= + ansi-colors@3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" @@ -1166,6 +1176,11 @@ async@0.9.0: resolved "https://registry.yarnpkg.com/async/-/async-0.9.0.tgz#ac3613b1da9bed1b47510bb4651b8931e47146c7" integrity sha1-rDYTsdqb7RtHUQu0ZRuJMeRxRsc= +async@1.x: + version "1.5.2" + resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" + integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -1273,6 +1288,11 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" +browser-stdout@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" + integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= + browser-stdout@1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" @@ -1410,7 +1430,7 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chai@^4.2.0: +chai@^4.1.1, chai@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== @@ -1558,6 +1578,13 @@ commander@2.15.1: resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== +commander@2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" + integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q= + dependencies: + graceful-readlink ">= 1.0.0" + commander@~2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -1736,6 +1763,17 @@ cosmiconfig@^5.1.0: js-yaml "^3.13.1" parse-json "^4.0.0" +coveralls@^3.0.4: + version "3.1.0" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.0.tgz#13c754d5e7a2dd8b44fe5269e21ca394fb4d615b" + integrity sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ== + dependencies: + js-yaml "^3.13.1" + lcov-parse "^1.0.0" + log-driver "^1.2.7" + minimist "^1.2.5" + request "^2.88.2" + cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -1783,6 +1821,13 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== +debug@2.6.8: + version "2.6.8" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" + integrity sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw= + dependencies: + ms "2.0.0" + debug@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -1915,6 +1960,11 @@ dezalgo@^1.0.0: asap "^2.0.0" wrappy "1" +diff@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" + integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k= + diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -2060,6 +2110,18 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escodegen@1.8.x: + version "1.8.1" + resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" + integrity sha1-WltTr0aTEQvrsIZ6o0MN07cKEBg= + dependencies: + esprima "^2.7.1" + estraverse "^1.9.1" + esutils "^2.0.2" + optionator "^0.8.1" + optionalDependencies: + source-map "~0.2.0" + eslint-config-prettier@^6.10.1: version "6.10.1" resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.10.1.tgz#129ef9ec575d5ddc0e269667bf09defcd898642a" @@ -2178,6 +2240,11 @@ espree@^6.1.2: acorn-jsx "^5.1.0" eslint-visitor-keys "^1.1.0" +esprima@2.7.x, esprima@^2.7.1: + version "2.7.3" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" + integrity sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE= + esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" @@ -2197,6 +2264,11 @@ esrecurse@^4.1.0: dependencies: estraverse "^4.1.0" +estraverse@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" + integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= + estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" @@ -2642,6 +2714,18 @@ glob-to-regexp@^0.3.0: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= +glob@7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" + integrity sha1-gFIR3wT6rxxjo2ADBs31reULLsg= + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.2" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" @@ -2666,6 +2750,17 @@ glob@7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" +glob@^5.0.15: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= + dependencies: + inflight "^1.0.4" + inherits "2" + minimatch "2 || 3" + once "^1.3.0" + path-is-absolute "^1.0.0" + glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" @@ -2704,11 +2799,33 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= + growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== +growl@1.9.2: + version "1.9.2" + resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" + integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8= + +handlebars@^4.0.1: + version "4.7.6" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e" + integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA== + dependencies: + minimist "^1.2.5" + neo-async "^2.6.0" + source-map "^0.6.1" + wordwrap "^1.0.0" + optionalDependencies: + uglify-js "^3.1.4" + handlebars@^4.4.0: version "4.5.3" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" @@ -2725,7 +2842,7 @@ har-schema@^2.0.0: resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= -har-validator@~5.1.0: +har-validator@~5.1.0, har-validator@~5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== @@ -2733,6 +2850,11 @@ har-validator@~5.1.0: ajv "^6.5.5" har-schema "^2.0.0" +has-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" + integrity sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo= + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" @@ -3242,12 +3364,32 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= +istanbul@^0.4.5: + version "0.4.5" + resolved "https://registry.yarnpkg.com/istanbul/-/istanbul-0.4.5.tgz#65c7d73d4c4da84d4f3ac310b918fb0b8033733b" + integrity sha1-ZcfXPUxNqE1POsMQuRj7C4Azczs= + dependencies: + abbrev "1.0.x" + async "1.x" + escodegen "1.8.x" + esprima "2.7.x" + glob "^5.0.15" + handlebars "^4.0.1" + js-yaml "3.x" + mkdirp "0.5.x" + nopt "3.x" + once "1.x" + resolve "1.1.x" + supports-color "^3.1.0" + which "^1.1.1" + wordwrap "^1.0.0" + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.13.1, js-yaml@^3.13.1: +js-yaml@3.13.1, js-yaml@3.x, js-yaml@^3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -3285,6 +3427,11 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json3@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" + integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -3336,6 +3483,11 @@ kind-of@^6.0.0, kind-of@^6.0.2: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== +lcov-parse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-1.0.0.tgz#eb0d46b54111ebc561acb4c408ef9363bdc8f7e0" + integrity sha1-6w1GtUER68VhrLTECO+TY73I9+A= + lerna@^3.19.0: version "3.19.0" resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.19.0.tgz#6d53b613eca7da426ab1e97c01ce6fb39754da6c" @@ -3415,6 +3567,34 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +lodash._baseassign@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" + integrity sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4= + dependencies: + lodash._basecopy "^3.0.0" + lodash.keys "^3.0.0" + +lodash._basecopy@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" + integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= + +lodash._basecreate@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" + integrity sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE= + +lodash._getnative@^3.0.0: + version "3.9.1" + resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" + integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= + +lodash._isiterateecall@^3.0.0: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" + integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= + lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -3425,16 +3605,44 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= +lodash.create@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" + integrity sha1-1/KEnw29p+BGgruM1yqwIkYd6+c= + dependencies: + lodash._baseassign "^3.0.0" + lodash._basecreate "^3.0.0" + lodash._isiterateecall "^3.0.0" + lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= +lodash.isarguments@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" + integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= + +lodash.isarray@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" + integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= + lodash.ismatch@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= +lodash.keys@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" + integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= + dependencies: + lodash._getnative "^3.0.0" + lodash.isarguments "^3.0.0" + lodash.isarray "^3.0.0" + lodash.set@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" @@ -3470,6 +3678,11 @@ lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2. resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== +log-driver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" + integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== + log-symbols@2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" @@ -3653,7 +3866,7 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -minimatch@3.0.4, minimatch@^3.0.4: +"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -3678,6 +3891,11 @@ minimist@^1.1.3, minimist@^1.2.0: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= +minimist@^1.2.5: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + minimist@~0.0.1: version "0.0.10" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" @@ -3736,6 +3954,31 @@ mkdirp@*, mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: dependencies: minimist "0.0.8" +mkdirp@0.5.x: + version "0.5.5" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" + integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== + dependencies: + minimist "^1.2.5" + +mocha@^3.5.0: + version "3.5.3" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d" + integrity sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg== + dependencies: + browser-stdout "1.3.0" + commander "2.9.0" + debug "2.6.8" + diff "3.2.0" + escape-string-regexp "1.0.5" + glob "7.1.1" + growl "1.9.2" + he "1.1.1" + json3 "3.3.2" + lodash.create "3.1.1" + mkdirp "0.5.1" + supports-color "3.1.2" + mocha@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" @@ -3914,6 +4157,13 @@ node-gyp@^5.0.2: tar "^4.4.12" which "^1.3.1" +nopt@3.x: + version "3.0.6" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-3.0.6.tgz#c6465dbf08abcd4db359317f79ac68a646b28ff9" + integrity sha1-xkZdvwirzU2zWTF/eaxopkayj/k= + dependencies: + abbrev "1" + nopt@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" @@ -4078,7 +4328,7 @@ octokit-pagination-methods@^1.1.0: resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4" integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ== -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@1.x, once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -4107,7 +4357,7 @@ optimist@^0.6.1: minimist "~0.0.1" wordwrap "~0.0.2" -optionator@^0.8.3: +optionator@^0.8.1, optionator@^0.8.3: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -4514,6 +4764,11 @@ psl@^1.1.24: resolved "https://registry.yarnpkg.com/psl/-/psl-1.6.0.tgz#60557582ee23b6c43719d9890fb4170ecd91e110" integrity sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA== +psl@^1.1.28: + version "1.8.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" + integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== + pump@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" @@ -4544,7 +4799,7 @@ punycode@^1.4.1: resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= -punycode@^2.1.0: +punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== @@ -4749,6 +5004,32 @@ request@^2.88.0: tunnel-agent "^0.6.0" uuid "^3.3.2" +request@^2.88.2: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" @@ -4781,6 +5062,11 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= +resolve@1.1.x: + version "1.1.7" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" + integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= + resolve@^1.10.0, resolve@^1.10.1: version "1.14.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.0.tgz#6d14c6f9db9f8002071332b600039abf82053f64" @@ -5036,6 +5322,13 @@ source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +source-map@~0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.2.0.tgz#dab73fbcfc2ba819b4de03bd6f6eaa48164b3f9d" + integrity sha1-2rc/vPwrqBm03gO9b26qSBZLP50= + dependencies: + amdefine ">=0.0.4" + spdx-correct@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" @@ -5288,6 +5581,13 @@ strong-log-transformer@^2.0.0: minimist "^1.2.0" through "^2.3.4" +supports-color@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" + integrity sha1-cqJiiU2dQIuVbKBf83su2KbiotU= + dependencies: + has-flag "^1.0.0" + supports-color@5.4.0: version "5.4.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" @@ -5302,6 +5602,13 @@ supports-color@6.0.0: dependencies: has-flag "^3.0.0" +supports-color@^3.1.0: + version "3.2.3" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" + integrity sha1-ZawFBLOVQXHYpklGsq48u4pfVPY= + dependencies: + has-flag "^1.0.0" + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -5443,6 +5750,14 @@ tough-cookie@~2.4.3: psl "^1.1.24" punycode "^1.4.1" +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + tr46@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" @@ -5702,7 +6017,7 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1.3.1, which@^1.2.9, which@^1.3.1: +which@1.3.1, which@^1.1.1, which@^1.2.9, which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== @@ -5728,6 +6043,11 @@ word-wrap@~1.2.3: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== +wordwrap@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" + integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= + wordwrap@~0.0.2: version "0.0.3" resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" From 16344cbfcdcd6fdaa8cc637f63b4ec65e652859e Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 28 Apr 2020 10:07:12 -0500 Subject: [PATCH 0631/1037] Update test command for travis I think the new syntax I'm using here is compatible with `sh`...let's see. --- .eslintrc | 14 +++----------- package.json | 2 +- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/.eslintrc b/.eslintrc index 57948b711..e03680342 100644 --- a/.eslintrc +++ b/.eslintrc @@ -1,16 +1,8 @@ { - "plugins": [ - "prettier" - ], + "plugins": ["prettier"], "parser": "@typescript-eslint/parser", - "extends": [ - "plugin:prettier/recommended", - "prettier/@typescript-eslint" - ], - "ignorePatterns": [ - "node_modules", - "packages/pg-protocol/dist/**/*" - ], + "extends": ["plugin:prettier/recommended", "prettier/@typescript-eslint"], + "ignorePatterns": ["node_modules", "coverage", "packages/pg-protocol/dist/**/*"], "parserOptions": { "ecmaVersion": 2017, "sourceType": "module" diff --git a/package.json b/package.json index dd32e85b6..5fb9b187e 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "test": "yarn lint && yarn lerna exec yarn test", "build": "yarn lerna exec --scope pg-protocol yarn build", "pretest": "yarn build", - "lint": "!([[ -e node_modules/.bin/prettier ]]) || eslint '*/**/*.{js,ts,tsx}'" + "lint": "if [ -x ./node_modules/.bin/eslint ]; then eslint '*/**/*.{js,ts,tsx}'; fi;" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^2.27.0", From ddf81128ab5a7c0920da02ff027dd9a0356bd8b9 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 28 Apr 2020 10:20:22 -0500 Subject: [PATCH 0632/1037] Check for the correct binary --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5fb9b187e..282ca9376 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "test": "yarn lint && yarn lerna exec yarn test", "build": "yarn lerna exec --scope pg-protocol yarn build", "pretest": "yarn build", - "lint": "if [ -x ./node_modules/.bin/eslint ]; then eslint '*/**/*.{js,ts,tsx}'; fi;" + "lint": "if [ -x ./node_modules/.bin/prettier ]; then eslint '*/**/*.{js,ts,tsx}'; fi;" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^2.27.0", From afd14cb5f9517baaf72d8a0c27ebf18f9c8acdb6 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 28 Apr 2020 21:56:25 -0500 Subject: [PATCH 0633/1037] Publish - pg-connection-string@2.2.1 --- packages/pg-connection-string/package.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index 49345369c..a2f7f07d8 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "2.2.0", + "version": "2.2.1", "description": "Functions for dealing with a PostgresSQL connection string", "main": "./index.js", "types": "./index.d.ts", @@ -25,7 +25,6 @@ "url": "https://github.com/iceddev/pg-connection-string/issues" }, "homepage": "https://github.com/iceddev/pg-connection-string", - "dependencies": {}, "devDependencies": { "chai": "^4.1.1", "coveralls": "^3.0.4", From abb1f34020abfc9eaa006aaa36d4c44d5fb43fa7 Mon Sep 17 00:00:00 2001 From: Andreas Lind Date: Tue, 5 May 2020 09:26:42 +0200 Subject: [PATCH 0634/1037] Fix repository field in package.json --- packages/pg-connection-string/package.json | 2 +- packages/pg-cursor/package.json | 2 +- packages/pg-pool/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index a2f7f07d8..4968c709c 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -11,7 +11,7 @@ }, "repository": { "type": "git", - "url": "https://github.com/iceddev/pg-connection-string" + "url": "git://github.com/brianc/node-postgres.git" }, "keywords": [ "pg", diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index d4bbec5cf..f242ebb04 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -11,7 +11,7 @@ }, "repository": { "type": "git", - "url": "git://github.com/brianc/node-pg-cursor.git" + "url": "git://github.com/brianc/node-postgres.git" }, "author": "Brian M. Carlson", "license": "MIT", diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index fdb95a960..7c9541273 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -11,7 +11,7 @@ }, "repository": { "type": "git", - "url": "git://github.com/brianc/node-pg-pool.git" + "url": "git://github.com/brianc/node-postgres.git" }, "keywords": [ "pg", From 6937a2428b6e54c4ebe93fa54899631bae861ec3 Mon Sep 17 00:00:00 2001 From: Ben Salili-James Date: Tue, 5 May 2020 13:24:11 +0100 Subject: [PATCH 0635/1037] Add `PGSSLMODE=noverify` support to opt-out of rejecting self-signed certs --- packages/pg/lib/connection-parameters.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index b34e0df5f..71161e2c8 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -34,6 +34,8 @@ var useSsl = function () { case 'verify-ca': case 'verify-full': return true + case 'no-verify': + return { rejectUnauthorized: false } } return defaults.ssl } From 698993ec6d082ccd8be87404be3995364c08c7fa Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 5 May 2020 09:43:31 -0500 Subject: [PATCH 0636/1037] Use monorepo connection string --- packages/pg/package.json | 2 +- yarn.lock | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/pg/package.json b/packages/pg/package.json index da8a75f26..7e7803a76 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -21,7 +21,7 @@ "dependencies": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-connection-string": "0.1.3", + "pg-connection-string": "^2.2.1", "pg-pool": "^3.1.1", "pg-protocol": "^1.2.2", "pg-types": "^2.1.0", diff --git a/yarn.lock b/yarn.lock index 796307ce2..a1f07fa34 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4596,11 +4596,6 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -pg-connection-string@0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/pg-connection-string/-/pg-connection-string-0.1.3.tgz#da1847b20940e42ee1492beaf65d49d91b245df7" - integrity sha1-2hhHsglA5C7hSSvq9l1J2RskXfc= - pg-copy-streams@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/pg-copy-streams/-/pg-copy-streams-0.3.0.tgz#a4fbc2a3b788d4e9da6f77ceb35422d8d7043b7f" From 3a2af0f52c66624d28557c51003732bd75806f2a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 5 May 2020 09:50:53 -0500 Subject: [PATCH 0637/1037] Fix relative path import Closes #2188 --- packages/pg/lib/connection-fast.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index 6344b4174..54e628ff5 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -11,8 +11,7 @@ var net = require('net') var EventEmitter = require('events').EventEmitter var util = require('util') -// eslint-disable-next-line -const { parse, serialize } = require('../../pg-protocol/dist') +const { parse, serialize } = require('pg-protocol/dist') // TODO(bmc) support binary mode here // var BINARY_MODE = 1 From 9e11004e8a50e6011df5c33cef9521af8c71ff6d Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 5 May 2020 09:53:56 -0500 Subject: [PATCH 0638/1037] No need to import from dist --- packages/pg/lib/connection-fast.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js index 54e628ff5..7cc2ed8cf 100644 --- a/packages/pg/lib/connection-fast.js +++ b/packages/pg/lib/connection-fast.js @@ -11,10 +11,9 @@ var net = require('net') var EventEmitter = require('events').EventEmitter var util = require('util') -const { parse, serialize } = require('pg-protocol/dist') +const { parse, serialize } = require('pg-protocol') -// TODO(bmc) support binary mode here -// var BINARY_MODE = 1 +// TODO(bmc) support binary mode at some point console.log('***using faster connection***') var Connection = function (config) { EventEmitter.call(this) From b89eb0f81df36b32d28bf94d8cbc31186ed66574 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 5 May 2020 10:58:34 -0500 Subject: [PATCH 0639/1037] Write tests & unify treatment of no-verify --- packages/pg/lib/connection-parameters.js | 14 ++++- .../environment-variable-tests.js | 59 ++++++++++++------- 2 files changed, 48 insertions(+), 25 deletions(-) diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index 71161e2c8..eead3c39f 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -25,8 +25,15 @@ var val = function (key, config, envVar) { return config[key] || envVar || defaults[key] } -var useSsl = function () { - switch (process.env.PGSSLMODE) { +var useSsl = function (modeFromConfig) { + // if the ssl parameter passed to config is not a string, just return it + // directly (it will be passed directly to tls.connect) + if (modeFromConfig !== undefined && typeof modeFromConfig !== 'string') { + return modeFromConfig + } + const mode = modeFromConfig || process.env.PGSSLMODE + + switch (mode) { case 'disable': return false case 'prefer': @@ -70,7 +77,8 @@ var ConnectionParameters = function (config) { }) this.binary = val('binary', config) - this.ssl = typeof config.ssl === 'undefined' ? useSsl() : config.ssl + // this.ssl = typeof config.ssl === 'undefined' ? useSsl() : config.ssl + this.ssl = useSsl(config.ssl) this.client_encoding = val('client_encoding', config) this.replication = val('replication', config) // a domain socket begins with '/' diff --git a/packages/pg/test/unit/connection-parameters/environment-variable-tests.js b/packages/pg/test/unit/connection-parameters/environment-variable-tests.js index 45d481e30..c64edee87 100644 --- a/packages/pg/test/unit/connection-parameters/environment-variable-tests.js +++ b/packages/pg/test/unit/connection-parameters/environment-variable-tests.js @@ -1,5 +1,7 @@ 'use strict' var helper = require(__dirname + '/../test-helper') +const Suite = require('../../suite') + var assert = require('assert') var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters') var defaults = require(__dirname + '/../../../lib').defaults @@ -11,7 +13,17 @@ for (var key in process.env) { delete process.env[key] } -test('ConnectionParameters initialized from environment variables', function (t) { +const suite = new Suite('ConnectionParameters') + +const clearEnv = () => { + // clear process.env + for (var key in process.env) { + delete process.env[key] + } +} + +suite.test('ConnectionParameters initialized from environment variables', function () { + clearEnv() process.env['PGHOST'] = 'local' process.env['PGUSER'] = 'bmc2' process.env['PGPORT'] = 7890 @@ -26,7 +38,13 @@ test('ConnectionParameters initialized from environment variables', function (t) assert.equal(subject.password, 'open', 'env password') }) -test('ConnectionParameters initialized from mix', function (t) { +suite.test('ConnectionParameters initialized from mix', function () { + clearEnv() + process.env['PGHOST'] = 'local' + process.env['PGUSER'] = 'bmc2' + process.env['PGPORT'] = 7890 + process.env['PGDATABASE'] = 'allyerbase' + process.env['PGPASSWORD'] = 'open' delete process.env['PGPASSWORD'] delete process.env['PGDATABASE'] var subject = new ConnectionParameters({ @@ -40,12 +58,8 @@ test('ConnectionParameters initialized from mix', function (t) { assert.equal(subject.password, defaults.password, 'defaults password') }) -// clear process.env -for (var key in process.env) { - delete process.env[key] -} - -test('connection string parsing', function (t) { +suite.test('connection string parsing', function () { + clearEnv() var string = 'postgres://brian:pw@boom:381/lala' var subject = new ConnectionParameters(string) assert.equal(subject.host, 'boom', 'string host') @@ -55,7 +69,10 @@ test('connection string parsing', function (t) { assert.equal(subject.database, 'lala', 'string database') }) -test('connection string parsing - ssl', function (t) { +suite.test('connection string parsing - ssl', function () { + // clear process.env + clearEnv() + var string = 'postgres://brian:pw@boom:381/lala?ssl=true' var subject = new ConnectionParameters(string) assert.equal(subject.ssl, true, 'ssl') @@ -75,27 +92,24 @@ test('connection string parsing - ssl', function (t) { string = 'postgres://brian:pw@boom:381/lala' subject = new ConnectionParameters(string) assert.equal(!!subject.ssl, false, 'ssl') -}) -// clear process.env -for (var key in process.env) { - delete process.env[key] -} + string = 'postgres://brian:pw@boom:381/lala?ssl=no-verify' + subject = new ConnectionParameters(string) + assert.deepStrictEqual(subject.ssl, { rejectUnauthorized: false }, 'ssl') +}) -test('ssl is false by default', function () { +suite.test('ssl is false by default', function () { + clearEnv() var subject = new ConnectionParameters() assert.equal(subject.ssl, false) }) var testVal = function (mode, expected) { - // clear process.env - for (var key in process.env) { - delete process.env[key] - } - process.env.PGSSLMODE = mode - test('ssl is ' + expected + ' when $PGSSLMODE=' + mode, function () { + suite.test('ssl is ' + expected + ' when $PGSSLMODE=' + mode, function () { + clearEnv() + process.env.PGSSLMODE = mode var subject = new ConnectionParameters() - assert.equal(subject.ssl, expected) + assert.deepStrictEqual(subject.ssl, expected) }) } @@ -106,6 +120,7 @@ testVal('prefer', true) testVal('require', true) testVal('verify-ca', true) testVal('verify-full', true) +testVal('no-verify', { rejectUnauthorized: false }) // restore process.env for (var key in realEnv) { From e9073f5a00f225670899b2a466fe18b5b047201d Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 5 May 2020 11:03:29 -0500 Subject: [PATCH 0640/1037] Cleanup & comments --- packages/pg/lib/connection-parameters.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index eead3c39f..83aa1e4e3 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -25,9 +25,11 @@ var val = function (key, config, envVar) { return config[key] || envVar || defaults[key] } -var useSsl = function (modeFromConfig) { +var normalizeSSLConfig = function (modeFromConfig) { // if the ssl parameter passed to config is not a string, just return it // directly (it will be passed directly to tls.connect) + // this way you can pass all the ssl params in via constructor: + // new Client({ ssl: { minDHSize: 1024 } }) etc if (modeFromConfig !== undefined && typeof modeFromConfig !== 'string') { return modeFromConfig } @@ -41,6 +43,11 @@ var useSsl = function (modeFromConfig) { case 'verify-ca': case 'verify-full': return true + // no-verify is not standard to libpq but allows specifying + // you require ssl but want to bypass server certificate validation. + // this is a very common way to connect in heroku so we support it + // vai both environment variables (PGSSLMODE=no-verify) as well + // as in connection string params ?ssl=no-verify case 'no-verify': return { rejectUnauthorized: false } } @@ -77,8 +84,8 @@ var ConnectionParameters = function (config) { }) this.binary = val('binary', config) - // this.ssl = typeof config.ssl === 'undefined' ? useSsl() : config.ssl - this.ssl = useSsl(config.ssl) + + this.ssl = normalizeSSLConfig(config.ssl) this.client_encoding = val('client_encoding', config) this.replication = val('replication', config) // a domain socket begins with '/' From 18649107782196d67b16871bcf2172241c80dda7 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 5 May 2020 11:08:05 -0500 Subject: [PATCH 0641/1037] Add test for no-verify string config option --- packages/pg/test/unit/client/configuration-tests.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/pg/test/unit/client/configuration-tests.js b/packages/pg/test/unit/client/configuration-tests.js index e6cbc0dcc..d4b16d101 100644 --- a/packages/pg/test/unit/client/configuration-tests.js +++ b/packages/pg/test/unit/client/configuration-tests.js @@ -1,5 +1,6 @@ 'use strict' require(__dirname + '/test-helper') +var assert = require('assert') var pguser = process.env['PGUSER'] || process.env.USER var pgdatabase = process.env['PGDATABASE'] || process.env.USER @@ -43,6 +44,11 @@ test('client settings', function () { assert.equal(client.ssl, true) }) + test('ssl no-verify', function () { + var client = new Client({ ssl: 'no-verify' }) + assert.deepStrictEqual(client.ssl, { rejectUnauthorized: false }) + }) + test('custom ssl force off', function () { var old = process.env.PGSSLMODE process.env.PGSSLMODE = 'prefer' From 8d1b200a3acb0915fb677fc124d175d9aa9b4ef9 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 6 May 2020 11:54:39 -0500 Subject: [PATCH 0642/1037] Update SPONSORS.md --- SPONSORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SPONSORS.md b/SPONSORS.md index 9b0431654..d01c1090d 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -7,6 +7,7 @@ node-postgres is made possible by the helpful contributors from the community as - [Timescale](https://timescale.com) - [Nafundi](https://nafundi.com) - [CrateDB](https://crate.io/) +- [BitMEX](https://www.bitmex.com/app/trade/XBTUSD) # Supporters From a7aa1bbb1d4b9d42706a807bd4feb7bbab7f8898 Mon Sep 17 00:00:00 2001 From: Julien Bouquillon Date: Wed, 6 May 2020 18:56:16 +0200 Subject: [PATCH 0643/1037] doc: add pg-connection-string in readme packages --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d963edc20..34aceea3b 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ This repo is a monorepo which contains the core [pg](https://github.com/brianc/n - [pg-pool](https://github.com/brianc/node-postgres/tree/master/packages/pg-pool) - [pg-cursor](https://github.com/brianc/node-postgres/tree/master/packages/pg-cursor) - [pg-query-stream](https://github.com/brianc/node-postgres/tree/master/packages/pg-query-stream) +- [pg-connection-string](https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string) ## Documenation From 7929f6ae44a63b76b2ea58e5d9fc016a2d3f14df Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 7 May 2020 11:36:39 -0500 Subject: [PATCH 0644/1037] Make change less invasive and fully backwards compatible for native binding config --- packages/pg/lib/connection-parameters.js | 26 +++++++------------ .../test/unit/client/configuration-tests.js | 5 ---- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index 83aa1e4e3..e1d838929 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -25,17 +25,8 @@ var val = function (key, config, envVar) { return config[key] || envVar || defaults[key] } -var normalizeSSLConfig = function (modeFromConfig) { - // if the ssl parameter passed to config is not a string, just return it - // directly (it will be passed directly to tls.connect) - // this way you can pass all the ssl params in via constructor: - // new Client({ ssl: { minDHSize: 1024 } }) etc - if (modeFromConfig !== undefined && typeof modeFromConfig !== 'string') { - return modeFromConfig - } - const mode = modeFromConfig || process.env.PGSSLMODE - - switch (mode) { +var readSSLConfigFromEnvironment = function () { + switch (process.env.PGSSLMODE) { case 'disable': return false case 'prefer': @@ -43,11 +34,6 @@ var normalizeSSLConfig = function (modeFromConfig) { case 'verify-ca': case 'verify-full': return true - // no-verify is not standard to libpq but allows specifying - // you require ssl but want to bypass server certificate validation. - // this is a very common way to connect in heroku so we support it - // vai both environment variables (PGSSLMODE=no-verify) as well - // as in connection string params ?ssl=no-verify case 'no-verify': return { rejectUnauthorized: false } } @@ -85,7 +71,13 @@ var ConnectionParameters = function (config) { this.binary = val('binary', config) - this.ssl = normalizeSSLConfig(config.ssl) + this.ssl = typeof config.ssl === 'undefined' ? readSSLConfigFromEnvironment() : config.ssl + + // support passing in ssl=no-verify via connection string + if (this.ssl === 'no-verify') { + this.ssl = { rejectUnauthorized: false } + } + this.client_encoding = val('client_encoding', config) this.replication = val('replication', config) // a domain socket begins with '/' diff --git a/packages/pg/test/unit/client/configuration-tests.js b/packages/pg/test/unit/client/configuration-tests.js index d4b16d101..e604513bf 100644 --- a/packages/pg/test/unit/client/configuration-tests.js +++ b/packages/pg/test/unit/client/configuration-tests.js @@ -44,11 +44,6 @@ test('client settings', function () { assert.equal(client.ssl, true) }) - test('ssl no-verify', function () { - var client = new Client({ ssl: 'no-verify' }) - assert.deepStrictEqual(client.ssl, { rejectUnauthorized: false }) - }) - test('custom ssl force off', function () { var old = process.env.PGSSLMODE process.env.PGSSLMODE = 'prefer' From 3f5bc58a86cda3b4812addc1e42a06d61d31e614 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 8 May 2020 10:42:57 -0500 Subject: [PATCH 0645/1037] Publish - pg-connection-string@2.2.2 - pg-cursor@2.1.11 - pg-pool@3.2.0 - pg-query-stream@3.0.8 - pg@8.1.0 --- packages/pg-connection-string/package.json | 2 +- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index 4968c709c..cdbbf527a 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "2.2.1", + "version": "2.2.2", "description": "Functions for dealing with a PostgresSQL connection string", "main": "./index.js", "types": "./index.d.ts", diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index f242ebb04..14af348ea 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.1.10", + "version": "2.1.11", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -17,6 +17,6 @@ "license": "MIT", "devDependencies": { "mocha": "^6.2.2", - "pg": "^8.0.3" + "pg": "^8.1.0" } } diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 7c9541273..176a3e41c 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.1.1", + "version": "3.2.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index fd828f82d..d6c8e96b4 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.0.7", + "version": "3.0.8", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -26,12 +26,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^6.2.2", - "pg": "^8.0.3", + "pg": "^8.1.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.1.10" + "pg-cursor": "^2.1.11" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 7e7803a76..1fda0daeb 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.0.3", + "version": "8.1.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -21,8 +21,8 @@ "dependencies": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-connection-string": "^2.2.1", - "pg-pool": "^3.1.1", + "pg-connection-string": "^2.2.2", + "pg-pool": "^3.2.0", "pg-protocol": "^1.2.2", "pg-types": "^2.1.0", "pgpass": "1.x", From bd7caf57427e28eea8552b660cc2161e9aaca811 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 8 May 2020 10:51:08 -0500 Subject: [PATCH 0646/1037] Remove sponsor logo --- CHANGELOG.md | 379 ------------------------------------------ packages/pg/README.md | 73 ++++---- 2 files changed, 34 insertions(+), 418 deletions(-) delete mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index ab356e0f7..000000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,379 +0,0 @@ -All major and minor releases are briefly explained below. - -For richer information consult the commit log on github with referenced pull requests. - -We do not include break-fix version release in this file. - -### pg-pool@3.1.0 - -- Add [maxUses](https://github.com/brianc/node-postgres/pull/2157) config option. - -### pg@8.0.0 - -#### note: for detailed release notes please [check here](https://node-postgres.com/announcements#2020-02-25) - -- Remove versions of node older than `6 lts` from the test matrix. `pg>=8.0` may still work on older versions but it is no longer officially supported. -- Change default behavior when not specifying `rejectUnauthorized` with the SSL connection parameters. Previously we defaulted to `rejectUnauthorized: false` when it was not specifically included. We now default to `rejectUnauthorized: true.` Manually specify `{ ssl: { rejectUnauthorized: false } }` for old behavior. -- Change [default database](https://github.com/brianc/node-postgres/pull/1679) when not specified to use the `user` config option if available. Previously `process.env.USER` was used. -- Change `pg.Pool` and `pg.Query` to [be](https://github.com/brianc/node-postgres/pull/2126) an [es6 class](https://github.com/brianc/node-postgres/pull/2063). -- Make `pg.native` non enumerable. -- `notice` messages are [no longer instances](https://github.com/brianc/node-postgres/pull/2090) of `Error`. -- Passwords no longer [show up](https://github.com/brianc/node-postgres/pull/2070) when instances of clients or pools are logged. - -### pg@7.18.0 - -- This will likely be the last minor release before pg@8.0. -- This version contains a few bug fixes and adds a deprecation warning for [a pending change in 8.0](https://github.com/brianc/node-postgres/issues/2009#issuecomment-579371651) which will flip the default behavior over SSL from `rejectUnauthorized` from `false` to `true` making things more secure in the general use case. - -### pg-query-stream@3.0.0 - -- [Rewrote stream internals](https://github.com/brianc/node-postgres/pull/2051) to better conform to node stream semantics. This should make pg-query-stream much better at respecting [highWaterMark](https://nodejs.org/api/stream.html#stream_new_stream_readable_options) and getting rid of some edge case bugs when using pg-query-stream as an async iterator. Due to the size and nature of this change (effectively a full re-write) it's safest to bump the semver major here, though almost all tests remain untouched and still passing, which brings us to a breaking change to the API.... -- Changed `stream.close` to `stream.destroy` which is the [official](https://nodejs.org/api/stream.html#stream_readable_destroy_error) way to terminate a readable stream. This is a __breaking change__ if you rely on the `stream.close` method on pg-query-stream...though should be just a find/replace type operation to upgrade as the semantics remain very similar (not exactly the same, since internals are rewritten, but more in line with how streams are "supposed" to behave). -- Unified the `config.batchSize` and `config.highWaterMark` to both do the same thing: control how many rows are buffered in memory. The `ReadableStream` will manage exactly how many rows are requested from the cursor at a time. This should give better out of the box performance and help with efficient async iteration. - -### pg@7.17.0 - -- Add support for `idle_in_transaction_session_timeout` [option](https://github.com/brianc/node-postgres/pull/2049). - -### 7.16.0 -- Add optional, opt-in behavior to test new, [faster query pipeline](https://github.com/brianc/node-postgres/pull/2044). This is experimental, and not documented yet. The pipeline changes will grow significantly after the 8.0 release. - -### 7.15.0 - -- Change repository structure to support lerna & future monorepo [development](https://github.com/brianc/node-postgres/pull/2014). -- [Warn about deprecation](https://github.com/brianc/node-postgres/pull/2021) for calling constructors without `new`. - -### 7.14.0 - -- Reverts 7.13.0 as it contained [an accidental breaking change](https://github.com/brianc/node-postgres/pull/2010) for self-signed SSL cert verification. 7.14.0 is identical to 7.12.1. - -### 7.13.0 - -- Add support for [all tls.connect()](https://github.com/brianc/node-postgres/pull/1996) options. - -### 7.12.0 - -- Add support for [async password lookup](https://github.com/brianc/node-postgres/pull/1926). - -### 7.11.0 - -- Add support for [connection_timeout](https://github.com/brianc/node-postgres/pull/1847/files#diff-5391bde944956870128be1136e7bc176R63) and [keepalives_idle](https://github.com/brianc/node-postgres/pull/1847). - -### 7.10.0 - -- Add support for [per-query types](https://github.com/brianc/node-postgres/pull/1825). - -### 7.9.0 - -- Add support for [sasl/scram authentication](https://github.com/brianc/node-postgres/pull/1835). - -### 7.8.0 - -- Add support for passing [secureOptions](https://github.com/brianc/node-postgres/pull/1804) SSL config. -- Upgrade [pg-types](https://github.com/brianc/node-postgres/pull/1806) to 2.0. - -### 7.7.0 - -- Add support for configurable [query timeout](https://github.com/brianc/node-postgres/pull/1760) on a client level. - -### 7.6.0 - -- Add support for ["bring your own promise"](https://github.com/brianc/node-postgres/pull/1518) - -### 7.5.0 - -- Better [error message](https://github.com/brianc/node-postgres/commit/11a4793452d618c53e019416cc886ad38deb1aa7) when passing `null` or `undefined` to `client.query`. -- Better [error handling](https://github.com/brianc/node-postgres/pull/1503) on queued queries. - -### 7.4.0 - -- Add support for [Uint8Array](https://github.com/brianc/node-postgres/pull/1448) values. - -### 7.3.0 - -- Add support for [statement timeout](https://github.com/brianc/node-postgres/pull/1436). - -### 7.2.0 - -- Pinned pg-pool and pg-types to a tighter semver range. This is likely not a noticeable change for you unless you were specifically installing older versions of those libraries for some reason, but making it a minor bump here just in case it could cause any confusion. - -### 7.1.0 - -#### Enhancements - -- [You can now supply both a connection string and additional config options to clients.](https://github.com/brianc/node-postgres/pull/1363) - -### 7.0.0 - -#### Breaking Changes - -- Drop support for node < `4.x`. -- Remove `pg.connect` `pg.end` and `pg.cancel` singleton methods. -- `Client#connect(callback)` now returns `undefined`. It used to return an event emitter. -- Upgrade [pg-pool](https://github.com/brianc/node-pg-pool) to `2.x`. -- Upgrade [pg-native](https://github.com/brianc/node-pg-native) to `2.x`. -- Standardize error message fields between JS and native driver. The only breaking changes were in the native driver as its field names were brought into alignment with the existing JS driver field names. -- Result from multi-statement text queries such as `SELECT 1; SELECT 2;` are now returned as an array of results instead of a single result with 1 array containing rows from both queries. - -[Please see here for a migration guide](https://node-postgres.com/guides/upgrading) - -#### Enhancements - -- Overhauled documentation: [https://node-postgres.com](https://node-postgres.com). -- Add `Client#connect() => Promise` and `Client#end() => Promise` calls. Promises are now returned from all async methods on clients _if and only if_ no callback was supplied to the method. -- Add `connectionTimeoutMillis` to pg-pool. - -### v6.2.0 - -- Add support for [parsing `replicationStart` messages](https://github.com/brianc/node-postgres/pull/1271/files). - -### v6.1.0 - -- Add optional callback parameter to the pure JavaScript `client.end` method. The native client already supported this. - -### v6.0.0 - -#### Breaking Changes - -- Remove `pg.pools`. There is still a reference kept to the pools created & tracked by `pg.connect` but it has been renamed, is considered private, and should not be used. Accessing this API directly was uncommon and was _supposed_ to be private but was incorrectly documented on the wiki. Therefore, it is a breaking change of an (unintentionally) public interface to remove it by renaming it & making it private. Eventually `pg.connect` itself will be deprecated in favor of instantiating pools directly via `new pg.Pool()` so this property should become completely moot at some point. In the mean time...check out the new features... - -#### New features - -- Replace internal pooling code with [pg-pool](https://github.com/brianc/node-pg-pool). This is the first step in eventually deprecating and removing the singleton `pg.connect`. The pg-pool constructor is exported from node-postgres at `require('pg').Pool`. It provides a backwards compatible interface with `pg.connect` as well as a promise based interface & additional niceties. - -You can now create an instance of a pool and don't have to rely on the `pg` singleton for anything: - -``` -var pg = require('pg') - -var pool = new pg.Pool() - -// your friendly neighborhood pool interface, without the singleton -pool.connect(function(err, client, done) { - // ... -}) -``` - -Promise support & other goodness lives now in [pg-pool](https://github.com/brianc/node-pg-pool). - -**Please** read the readme at [pg-pool](https://github.com/brianc/node-pg-pool) for the full api. - -- Included support for tcp keep alive. Enable it as follows: - -```js -var client = new Client({ keepAlive: true }); -``` - -This should help with backends incorrectly considering idle clients to be dead and prematurely disconnecting them. - -### v5.1.0 - -- Make the query object returned from `client.query` implement the promise interface. This is the first step towards promisifying more of the node-postgres api. - -Example: - -```js -var client = new Client(); -client.connect(); -client.query("SELECT $1::text as name", ["brianc"]).then(function(res) { - console.log("hello from", res.rows[0]); - client.end(); -}); -``` - -### v5.0.0 - -#### Breaking Changes - -- `require('pg').native` now returns null if the native bindings cannot be found; previously, this threw an exception. - -#### New Features - -- better error message when passing `undefined` as a query parameter -- support for `defaults.connectionString` -- support for `returnToHead` being passed to [generic pool](https://github.com/coopernurse/node-pool) - -### v4.5.0 - -- Add option to parse JS date objects in query parameters as [UTC](https://github.com/brianc/node-postgres/pull/943) - -### v4.4.0 - -- Warn to `stderr` if a named query exceeds 63 characters which is the max length supported by postgres. - -### v4.3.0 - -- Unpin `pg-types` semver. Allow it to float against `pg-types@1.x`. - -### v4.2.0 - -- Support for additional error fields in postgres >= 9.3 if available. - -### v4.1.0 - -- Allow type parser overrides on a [per-client basis](https://github.com/brianc/node-postgres/pull/679) - -### v4.0.0 - -- Make [native bindings](https://github.com/brianc/node-pg-native.git) an optional install with `npm install pg-native` -- No longer surround query result callback with `try/catch` block. -- Remove built in COPY IN / COPY OUT support - better implementations provided by [pg-copy-streams](https://github.com/brianc/node-pg-copy-streams.git) and [pg-native](https://github.com/brianc/node-pg-native.git) - -### v3.6.0 - -- Include support for (parsing JSONB)[https://github.com/brianc/node-pg-types/pull/13] (supported in postgres 9.4) - -### v3.5.0 - -- Include support for parsing boolean arrays - -### v3.4.0 - -- Include port as connection parameter to [unix sockets](https://github.com/brianc/node-postgres/pull/604) -- Better support for odd [date parsing](https://github.com/brianc/node-pg-types/pull/8) - -### v3.2.0 - -- Add support for parsing [date arrays](https://github.com/brianc/node-pg-types/pull/3) -- Expose array parsers on [pg.types](https://github.com/brianc/node-pg-types/pull/2) -- Allow [pool](https://github.com/brianc/node-postgres/pull/591) to be configured - -### v3.1.0 - -- Add [count of the number of times a client has been checked out from the pool](https://github.com/brianc/node-postgres/pull/556) -- Emit `end` from `pg` object [when a pool is drained](https://github.com/brianc/node-postgres/pull/571) - -### v3.0.0 - -#### Breaking changes - -- [Parse the DATE PostgreSQL type as local time](https://github.com/brianc/node-postgres/pull/514) - -After [some discussion](https://github.com/brianc/node-postgres/issues/510) it was decided node-postgres was non-compliant in how it was handling DATE results. They were being converted to UTC, but the PostgreSQL documentation specifies they should be returned in the client timezone. This is a breaking change, and if you use the `date` type you might want to examine your code and make sure nothing is impacted. - -- [Fix possible numeric precision loss on numeric & int8 arrays](https://github.com/brianc/node-postgres/pull/501) - -pg@v2.0 included changes to not convert large integers into their JavaScript number representation because of possibility for numeric precision loss. The same types in arrays were not taken into account. This fix applies the same type of type-coercion rules to arrays of those types, so there will be no more possible numeric loss on an array of very large int8s for example. This is a breaking change because now a return type from a query of `int8[]` will contain _string_ representations -of the integers. Use your favorite JavaScript bignum module to represent them without precision loss, or punch over the type converter to return the old style arrays again. - -- [Fix to input array of dates being improperly converted to utc](https://github.com/benesch/node-postgres/commit/c41eedc3e01e5527a3d5c242fa1896f02ef0b261#diff-7172adb1fec2457a2700ed29008a8e0aR108) - -Single `date` parameters were properly sent to the PostgreSQL server properly in local time, but an input array of dates was being changed into utc dates. This is a violation of what PostgreSQL expects. Small breaking change, but none-the-less something you should check out if you are inserting an array of dates. - -- [Query no longer emits `end` event if it ends due to an error](https://github.com/brianc/node-postgres/commit/357b64d70431ec5ca721eb45a63b082c18e6ffa3) - -This is a small change to bring the semantics of query more in line with other EventEmitters. The tests all passed after this change, but I suppose it could still be a breaking change in certain use cases. If you are doing clever things with the `end` and `error` events of a query object you might want to check to make sure its still behaving normally, though it is most likely not an issue. - -#### New features - -- [Supercharge `prepareValue`](https://github.com/brianc/node-postgres/pull/555) - -The long & short of it is now any object you supply in the list of query values will be inspected for a `.toPostgres` method. If the method is present it will be called and its result used as the raw text value sent to PostgreSQL for that value. This allows the same type of custom type coercion on query parameters as was previously afforded to query result values. - -- [Domain aware connection pool](https://github.com/brianc/node-postgres/pull/531) - -If domains are active node-postgres will honor them and do everything it can to ensure all callbacks are properly fired in the active domain. If you have tried to use domains with node-postgres (or many other modules which pool long lived event emitters) you may have run into an issue where the active domain changes before and after a callback. This has been a longstanding footgun within node-postgres and I am happy to get it fixed. - -- [Disconnected clients now removed from pool](https://github.com/brianc/node-postgres/pull/543) - -Avoids a scenario where your pool could fill up with disconnected & unusable clients. - -- [Break type parsing code into separate module](https://github.com/brianc/node-postgres/pull/541) - -To provide better documentation and a clearer explanation of how to override the query result parsing system we broke the type converters [into their own module](https://github.com/brianc/node-pg-types). There is still work around removing the 'global-ness' of the type converters so each query or connection can return types differently, but this is a good first step and allow a lot more obvious way to return int8 results as JavaScript numbers, for example - -### v2.11.0 - -- Add support for [application_name](https://github.com/brianc/node-postgres/pull/497) - -### v2.10.0 - -- Add support for [the password file](http://www.postgresql.org/docs/9.3/static/libpq-pgpass.html) - -### v2.9.0 - -- Add better support for [unix domain socket](https://github.com/brianc/node-postgres/pull/487) connections - -### v2.8.0 - -- Add support for parsing JSON[] and UUID[] result types - -### v2.7.0 - -- Use single row mode in native bindings when available [@rpedela] - - reduces memory consumption when handling row values in 'row' event -- Automatically bind buffer type parameters as binary [@eugeneware] - -### v2.6.0 - -- Respect PGSSLMODE environment variable - -### v2.5.0 - -- Ability to opt-in to int8 parsing via `pg.defaults.parseInt8 = true` - -### v2.4.0 - -- Use eval in the result set parser to increase performance - -### v2.3.0 - -- Remove built-in support for binary Int64 parsing. - _Due to the low usage & required compiled dependency this will be pushed into a 3rd party add-on_ - -### v2.2.0 - -- [Add support for excapeLiteral and escapeIdentifier in both JavaScript and the native bindings](https://github.com/brianc/node-postgres/pull/396) - -### v2.1.0 - -- Add support for SSL connections in JavaScript driver -- this means you can connect to heroku postgres from your local machine without the native bindings! -- [Add field metadata to result object](https://github.com/brianc/node-postgres/blob/master/test/integration/client/row-description-on-results-tests.js) -- [Add ability for rows to be returned as arrays instead of objects](https://github.com/brianc/node-postgres/blob/master/test/integration/client/results-as-array-tests.js) - -### v2.0.0 - -- Properly handle various PostgreSQL to JavaScript type conversions to avoid data loss: - -``` -PostgreSQL | pg@v2.0 JavaScript | pg@v1.0 JavaScript ---------------------------------|---------------- -float4 | number (float) | string -float8 | number (float) | string -int8 | string | number (int) -numeric | string | number (float) -decimal | string | number (float) -``` - -For more information see https://github.com/brianc/node-postgres/pull/353 -If you are unhappy with these changes you can always [override the built in type parsing fairly easily](https://github.com/brianc/node-pg-parse-float). - -### v1.3.0 - -- Make client_encoding configurable and optional - -### v1.2.0 - -- return field metadata on result object: access via result.fields[i].name/dataTypeID - -### v1.1.0 - -- built in support for `JSON` data type for PostgreSQL Server @ v9.2.0 or greater - -### v1.0.0 - -- remove deprecated functionality - - Callback function passed to `pg.connect` now **requires** 3 arguments - - Client#pauseDrain() / Client#resumeDrain removed - - numeric, decimal, and float data types no longer parsed into float before being returned. Will be returned from query results as `String` - -### v0.15.0 - -- client now emits `end` when disconnected from back-end server -- if client is disconnected in the middle of a query, query receives an error - -### v0.14.0 - -- add deprecation warnings in prep for v1.0 -- fix read/write failures in native module under node v0.9.x diff --git a/packages/pg/README.md b/packages/pg/README.md index 0d7953f4e..0d471dd42 100644 --- a/packages/pg/README.md +++ b/packages/pg/README.md @@ -5,7 +5,7 @@ NPM version NPM downloads -Non-blocking PostgreSQL client for Node.js. Pure JavaScript and optional native libpq bindings. +Non-blocking PostgreSQL client for Node.js. Pure JavaScript and optional native libpq bindings. ## Install @@ -14,30 +14,31 @@ $ npm install pg ``` --- -## :star: [Documentation](https://node-postgres.com) :star: +## :star: [Documentation](https://node-postgres.com) :star: ### Features -* Pure JavaScript client and native libpq bindings share _the same API_ -* Connection pooling -* Extensible JS ↔ PostgreSQL data-type coercion -* Supported PostgreSQL features - * Parameterized queries - * Named statements with query plan caching - * Async notifications with `LISTEN/NOTIFY` - * Bulk import & export with `COPY TO/COPY FROM` +- Pure JavaScript client and native libpq bindings share _the same API_ +- Connection pooling +- Extensible JS ↔ PostgreSQL data-type coercion +- Supported PostgreSQL features + - Parameterized queries + - Named statements with query plan caching + - Async notifications with `LISTEN/NOTIFY` + - Bulk import & export with `COPY TO/COPY FROM` ### Extras -node-postgres is by design pretty light on abstractions. These are some handy modules we've been using over the years to complete the picture. +node-postgres is by design pretty light on abstractions. These are some handy modules we've been using over the years to complete the picture. The entire list can be found on our [wiki](https://github.com/brianc/node-postgres/wiki/Extras). ## Support -node-postgres is free software. If you encounter a bug with the library please open an issue on the [GitHub repo](https://github.com/brianc/node-postgres). If you have questions unanswered by the documentation please open an issue pointing out how the documentation was unclear & I will do my best to make it better! +node-postgres is free software. If you encounter a bug with the library please open an issue on the [GitHub repo](https://github.com/brianc/node-postgres). If you have questions unanswered by the documentation please open an issue pointing out how the documentation was unclear & I will do my best to make it better! When you open an issue please provide: + - version of Node - version of Postgres - smallest possible snippet of code to reproduce the problem @@ -49,10 +50,6 @@ You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) and these featured sponsors:
- - - - @@ -60,19 +57,18 @@ node-postgres's continued development has been made possible in part by generous If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable [please consider supporting](https://github.com/sponsors/brianc) its development. - ## Contributing -__:heart: contributions!__ +**:heart: contributions!** -I will __happily__ accept your pull request if it: -- __has tests__ +I will **happily** accept your pull request if it: + +- **has tests** - looks reasonable - does not break backwards compatibility If your change involves breaking backwards compatibility please please point that out in the pull request & we can discuss & plan when and how to release it and what type of documentation or communicate it will require. - ## Troubleshooting and FAQ The causes and solutions to common errors can be found among the [Frequently Asked Questions (FAQ)](https://github.com/brianc/node-postgres/wiki/FAQ) @@ -81,21 +77,20 @@ The causes and solutions to common errors can be found among the [Frequently Ask Copyright (c) 2010-2020 Brian Carlson (brian.m.carlson@gmail.com) - 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. - +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. From c55758fca09e4ef6fcee60b4a9ac0469e46f98ba Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 8 May 2020 10:51:13 -0500 Subject: [PATCH 0647/1037] Update changelog --- CHANGELOG.md | 389 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 389 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..6e92a7b0a --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,389 @@ +All major and minor releases are briefly explained below. + +For richer information consult the commit log on github with referenced pull requests. + +We do not include break-fix version release in this file. + +### pg@8.1.0 + +- Switch to using [monorepo](https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string) version of `pg-connection-string`. This includes better support for SSL argument parsing from connection strings and ensures continuity of support. +- Add `&ssl=no-verify` option to connection string and `PGSSLMODE=no-verify` environment variable support for the pure JS driver. This is equivalent of passing `{ ssl: { rejectUnauthorize: false } }` to the client/pool constructor. The advantage of having support in connection strings and environment variables is it can be "externally" configured via environment variables and CLI arguments much more easily, and should remove the need to directly edit any application code for [the SSL default changes in 8.0](https://node-postgres.com/announcements#2020-02-25). This should make using `pg@8.x` significantly less difficult on environments like Heroku for example. + +### pg-pool@3.2.0 + +- Same changes to `pg` impact `pg-pool` as they both use the same connection parameter and connection string parsing code for configuring SSL. + +### pg-pool@3.1.0 + +- Add [maxUses](https://github.com/brianc/node-postgres/pull/2157) config option. + +### pg@8.0.0 + +#### note: for detailed release notes please [check here](https://node-postgres.com/announcements#2020-02-25) + +- Remove versions of node older than `6 lts` from the test matrix. `pg>=8.0` may still work on older versions but it is no longer officially supported. +- Change default behavior when not specifying `rejectUnauthorized` with the SSL connection parameters. Previously we defaulted to `rejectUnauthorized: false` when it was not specifically included. We now default to `rejectUnauthorized: true.` Manually specify `{ ssl: { rejectUnauthorized: false } }` for old behavior. +- Change [default database](https://github.com/brianc/node-postgres/pull/1679) when not specified to use the `user` config option if available. Previously `process.env.USER` was used. +- Change `pg.Pool` and `pg.Query` to [be](https://github.com/brianc/node-postgres/pull/2126) an [es6 class](https://github.com/brianc/node-postgres/pull/2063). +- Make `pg.native` non enumerable. +- `notice` messages are [no longer instances](https://github.com/brianc/node-postgres/pull/2090) of `Error`. +- Passwords no longer [show up](https://github.com/brianc/node-postgres/pull/2070) when instances of clients or pools are logged. + +### pg@7.18.0 + +- This will likely be the last minor release before pg@8.0. +- This version contains a few bug fixes and adds a deprecation warning for [a pending change in 8.0](https://github.com/brianc/node-postgres/issues/2009#issuecomment-579371651) which will flip the default behavior over SSL from `rejectUnauthorized` from `false` to `true` making things more secure in the general use case. + +### pg-query-stream@3.0.0 + +- [Rewrote stream internals](https://github.com/brianc/node-postgres/pull/2051) to better conform to node stream semantics. This should make pg-query-stream much better at respecting [highWaterMark](https://nodejs.org/api/stream.html#stream_new_stream_readable_options) and getting rid of some edge case bugs when using pg-query-stream as an async iterator. Due to the size and nature of this change (effectively a full re-write) it's safest to bump the semver major here, though almost all tests remain untouched and still passing, which brings us to a breaking change to the API.... +- Changed `stream.close` to `stream.destroy` which is the [official](https://nodejs.org/api/stream.html#stream_readable_destroy_error) way to terminate a readable stream. This is a **breaking change** if you rely on the `stream.close` method on pg-query-stream...though should be just a find/replace type operation to upgrade as the semantics remain very similar (not exactly the same, since internals are rewritten, but more in line with how streams are "supposed" to behave). +- Unified the `config.batchSize` and `config.highWaterMark` to both do the same thing: control how many rows are buffered in memory. The `ReadableStream` will manage exactly how many rows are requested from the cursor at a time. This should give better out of the box performance and help with efficient async iteration. + +### pg@7.17.0 + +- Add support for `idle_in_transaction_session_timeout` [option](https://github.com/brianc/node-postgres/pull/2049). + +### 7.16.0 + +- Add optional, opt-in behavior to test new, [faster query pipeline](https://github.com/brianc/node-postgres/pull/2044). This is experimental, and not documented yet. The pipeline changes will grow significantly after the 8.0 release. + +### 7.15.0 + +- Change repository structure to support lerna & future monorepo [development](https://github.com/brianc/node-postgres/pull/2014). +- [Warn about deprecation](https://github.com/brianc/node-postgres/pull/2021) for calling constructors without `new`. + +### 7.14.0 + +- Reverts 7.13.0 as it contained [an accidental breaking change](https://github.com/brianc/node-postgres/pull/2010) for self-signed SSL cert verification. 7.14.0 is identical to 7.12.1. + +### 7.13.0 + +- Add support for [all tls.connect()](https://github.com/brianc/node-postgres/pull/1996) options. + +### 7.12.0 + +- Add support for [async password lookup](https://github.com/brianc/node-postgres/pull/1926). + +### 7.11.0 + +- Add support for [connection_timeout](https://github.com/brianc/node-postgres/pull/1847/files#diff-5391bde944956870128be1136e7bc176R63) and [keepalives_idle](https://github.com/brianc/node-postgres/pull/1847). + +### 7.10.0 + +- Add support for [per-query types](https://github.com/brianc/node-postgres/pull/1825). + +### 7.9.0 + +- Add support for [sasl/scram authentication](https://github.com/brianc/node-postgres/pull/1835). + +### 7.8.0 + +- Add support for passing [secureOptions](https://github.com/brianc/node-postgres/pull/1804) SSL config. +- Upgrade [pg-types](https://github.com/brianc/node-postgres/pull/1806) to 2.0. + +### 7.7.0 + +- Add support for configurable [query timeout](https://github.com/brianc/node-postgres/pull/1760) on a client level. + +### 7.6.0 + +- Add support for ["bring your own promise"](https://github.com/brianc/node-postgres/pull/1518) + +### 7.5.0 + +- Better [error message](https://github.com/brianc/node-postgres/commit/11a4793452d618c53e019416cc886ad38deb1aa7) when passing `null` or `undefined` to `client.query`. +- Better [error handling](https://github.com/brianc/node-postgres/pull/1503) on queued queries. + +### 7.4.0 + +- Add support for [Uint8Array](https://github.com/brianc/node-postgres/pull/1448) values. + +### 7.3.0 + +- Add support for [statement timeout](https://github.com/brianc/node-postgres/pull/1436). + +### 7.2.0 + +- Pinned pg-pool and pg-types to a tighter semver range. This is likely not a noticeable change for you unless you were specifically installing older versions of those libraries for some reason, but making it a minor bump here just in case it could cause any confusion. + +### 7.1.0 + +#### Enhancements + +- [You can now supply both a connection string and additional config options to clients.](https://github.com/brianc/node-postgres/pull/1363) + +### 7.0.0 + +#### Breaking Changes + +- Drop support for node < `4.x`. +- Remove `pg.connect` `pg.end` and `pg.cancel` singleton methods. +- `Client#connect(callback)` now returns `undefined`. It used to return an event emitter. +- Upgrade [pg-pool](https://github.com/brianc/node-pg-pool) to `2.x`. +- Upgrade [pg-native](https://github.com/brianc/node-pg-native) to `2.x`. +- Standardize error message fields between JS and native driver. The only breaking changes were in the native driver as its field names were brought into alignment with the existing JS driver field names. +- Result from multi-statement text queries such as `SELECT 1; SELECT 2;` are now returned as an array of results instead of a single result with 1 array containing rows from both queries. + +[Please see here for a migration guide](https://node-postgres.com/guides/upgrading) + +#### Enhancements + +- Overhauled documentation: [https://node-postgres.com](https://node-postgres.com). +- Add `Client#connect() => Promise` and `Client#end() => Promise` calls. Promises are now returned from all async methods on clients _if and only if_ no callback was supplied to the method. +- Add `connectionTimeoutMillis` to pg-pool. + +### v6.2.0 + +- Add support for [parsing `replicationStart` messages](https://github.com/brianc/node-postgres/pull/1271/files). + +### v6.1.0 + +- Add optional callback parameter to the pure JavaScript `client.end` method. The native client already supported this. + +### v6.0.0 + +#### Breaking Changes + +- Remove `pg.pools`. There is still a reference kept to the pools created & tracked by `pg.connect` but it has been renamed, is considered private, and should not be used. Accessing this API directly was uncommon and was _supposed_ to be private but was incorrectly documented on the wiki. Therefore, it is a breaking change of an (unintentionally) public interface to remove it by renaming it & making it private. Eventually `pg.connect` itself will be deprecated in favor of instantiating pools directly via `new pg.Pool()` so this property should become completely moot at some point. In the mean time...check out the new features... + +#### New features + +- Replace internal pooling code with [pg-pool](https://github.com/brianc/node-pg-pool). This is the first step in eventually deprecating and removing the singleton `pg.connect`. The pg-pool constructor is exported from node-postgres at `require('pg').Pool`. It provides a backwards compatible interface with `pg.connect` as well as a promise based interface & additional niceties. + +You can now create an instance of a pool and don't have to rely on the `pg` singleton for anything: + +``` +var pg = require('pg') + +var pool = new pg.Pool() + +// your friendly neighborhood pool interface, without the singleton +pool.connect(function(err, client, done) { + // ... +}) +``` + +Promise support & other goodness lives now in [pg-pool](https://github.com/brianc/node-pg-pool). + +**Please** read the readme at [pg-pool](https://github.com/brianc/node-pg-pool) for the full api. + +- Included support for tcp keep alive. Enable it as follows: + +```js +var client = new Client({ keepAlive: true }) +``` + +This should help with backends incorrectly considering idle clients to be dead and prematurely disconnecting them. + +### v5.1.0 + +- Make the query object returned from `client.query` implement the promise interface. This is the first step towards promisifying more of the node-postgres api. + +Example: + +```js +var client = new Client() +client.connect() +client.query('SELECT $1::text as name', ['brianc']).then(function (res) { + console.log('hello from', res.rows[0]) + client.end() +}) +``` + +### v5.0.0 + +#### Breaking Changes + +- `require('pg').native` now returns null if the native bindings cannot be found; previously, this threw an exception. + +#### New Features + +- better error message when passing `undefined` as a query parameter +- support for `defaults.connectionString` +- support for `returnToHead` being passed to [generic pool](https://github.com/coopernurse/node-pool) + +### v4.5.0 + +- Add option to parse JS date objects in query parameters as [UTC](https://github.com/brianc/node-postgres/pull/943) + +### v4.4.0 + +- Warn to `stderr` if a named query exceeds 63 characters which is the max length supported by postgres. + +### v4.3.0 + +- Unpin `pg-types` semver. Allow it to float against `pg-types@1.x`. + +### v4.2.0 + +- Support for additional error fields in postgres >= 9.3 if available. + +### v4.1.0 + +- Allow type parser overrides on a [per-client basis](https://github.com/brianc/node-postgres/pull/679) + +### v4.0.0 + +- Make [native bindings](https://github.com/brianc/node-pg-native.git) an optional install with `npm install pg-native` +- No longer surround query result callback with `try/catch` block. +- Remove built in COPY IN / COPY OUT support - better implementations provided by [pg-copy-streams](https://github.com/brianc/node-pg-copy-streams.git) and [pg-native](https://github.com/brianc/node-pg-native.git) + +### v3.6.0 + +- Include support for (parsing JSONB)[https://github.com/brianc/node-pg-types/pull/13] (supported in postgres 9.4) + +### v3.5.0 + +- Include support for parsing boolean arrays + +### v3.4.0 + +- Include port as connection parameter to [unix sockets](https://github.com/brianc/node-postgres/pull/604) +- Better support for odd [date parsing](https://github.com/brianc/node-pg-types/pull/8) + +### v3.2.0 + +- Add support for parsing [date arrays](https://github.com/brianc/node-pg-types/pull/3) +- Expose array parsers on [pg.types](https://github.com/brianc/node-pg-types/pull/2) +- Allow [pool](https://github.com/brianc/node-postgres/pull/591) to be configured + +### v3.1.0 + +- Add [count of the number of times a client has been checked out from the pool](https://github.com/brianc/node-postgres/pull/556) +- Emit `end` from `pg` object [when a pool is drained](https://github.com/brianc/node-postgres/pull/571) + +### v3.0.0 + +#### Breaking changes + +- [Parse the DATE PostgreSQL type as local time](https://github.com/brianc/node-postgres/pull/514) + +After [some discussion](https://github.com/brianc/node-postgres/issues/510) it was decided node-postgres was non-compliant in how it was handling DATE results. They were being converted to UTC, but the PostgreSQL documentation specifies they should be returned in the client timezone. This is a breaking change, and if you use the `date` type you might want to examine your code and make sure nothing is impacted. + +- [Fix possible numeric precision loss on numeric & int8 arrays](https://github.com/brianc/node-postgres/pull/501) + +pg@v2.0 included changes to not convert large integers into their JavaScript number representation because of possibility for numeric precision loss. The same types in arrays were not taken into account. This fix applies the same type of type-coercion rules to arrays of those types, so there will be no more possible numeric loss on an array of very large int8s for example. This is a breaking change because now a return type from a query of `int8[]` will contain _string_ representations +of the integers. Use your favorite JavaScript bignum module to represent them without precision loss, or punch over the type converter to return the old style arrays again. + +- [Fix to input array of dates being improperly converted to utc](https://github.com/benesch/node-postgres/commit/c41eedc3e01e5527a3d5c242fa1896f02ef0b261#diff-7172adb1fec2457a2700ed29008a8e0aR108) + +Single `date` parameters were properly sent to the PostgreSQL server properly in local time, but an input array of dates was being changed into utc dates. This is a violation of what PostgreSQL expects. Small breaking change, but none-the-less something you should check out if you are inserting an array of dates. + +- [Query no longer emits `end` event if it ends due to an error](https://github.com/brianc/node-postgres/commit/357b64d70431ec5ca721eb45a63b082c18e6ffa3) + +This is a small change to bring the semantics of query more in line with other EventEmitters. The tests all passed after this change, but I suppose it could still be a breaking change in certain use cases. If you are doing clever things with the `end` and `error` events of a query object you might want to check to make sure its still behaving normally, though it is most likely not an issue. + +#### New features + +- [Supercharge `prepareValue`](https://github.com/brianc/node-postgres/pull/555) + +The long & short of it is now any object you supply in the list of query values will be inspected for a `.toPostgres` method. If the method is present it will be called and its result used as the raw text value sent to PostgreSQL for that value. This allows the same type of custom type coercion on query parameters as was previously afforded to query result values. + +- [Domain aware connection pool](https://github.com/brianc/node-postgres/pull/531) + +If domains are active node-postgres will honor them and do everything it can to ensure all callbacks are properly fired in the active domain. If you have tried to use domains with node-postgres (or many other modules which pool long lived event emitters) you may have run into an issue where the active domain changes before and after a callback. This has been a longstanding footgun within node-postgres and I am happy to get it fixed. + +- [Disconnected clients now removed from pool](https://github.com/brianc/node-postgres/pull/543) + +Avoids a scenario where your pool could fill up with disconnected & unusable clients. + +- [Break type parsing code into separate module](https://github.com/brianc/node-postgres/pull/541) + +To provide better documentation and a clearer explanation of how to override the query result parsing system we broke the type converters [into their own module](https://github.com/brianc/node-pg-types). There is still work around removing the 'global-ness' of the type converters so each query or connection can return types differently, but this is a good first step and allow a lot more obvious way to return int8 results as JavaScript numbers, for example + +### v2.11.0 + +- Add support for [application_name](https://github.com/brianc/node-postgres/pull/497) + +### v2.10.0 + +- Add support for [the password file](http://www.postgresql.org/docs/9.3/static/libpq-pgpass.html) + +### v2.9.0 + +- Add better support for [unix domain socket](https://github.com/brianc/node-postgres/pull/487) connections + +### v2.8.0 + +- Add support for parsing JSON[] and UUID[] result types + +### v2.7.0 + +- Use single row mode in native bindings when available [@rpedela] + - reduces memory consumption when handling row values in 'row' event +- Automatically bind buffer type parameters as binary [@eugeneware] + +### v2.6.0 + +- Respect PGSSLMODE environment variable + +### v2.5.0 + +- Ability to opt-in to int8 parsing via `pg.defaults.parseInt8 = true` + +### v2.4.0 + +- Use eval in the result set parser to increase performance + +### v2.3.0 + +- Remove built-in support for binary Int64 parsing. + _Due to the low usage & required compiled dependency this will be pushed into a 3rd party add-on_ + +### v2.2.0 + +- [Add support for excapeLiteral and escapeIdentifier in both JavaScript and the native bindings](https://github.com/brianc/node-postgres/pull/396) + +### v2.1.0 + +- Add support for SSL connections in JavaScript driver +- this means you can connect to heroku postgres from your local machine without the native bindings! +- [Add field metadata to result object](https://github.com/brianc/node-postgres/blob/master/test/integration/client/row-description-on-results-tests.js) +- [Add ability for rows to be returned as arrays instead of objects](https://github.com/brianc/node-postgres/blob/master/test/integration/client/results-as-array-tests.js) + +### v2.0.0 + +- Properly handle various PostgreSQL to JavaScript type conversions to avoid data loss: + +``` +PostgreSQL | pg@v2.0 JavaScript | pg@v1.0 JavaScript +--------------------------------|---------------- +float4 | number (float) | string +float8 | number (float) | string +int8 | string | number (int) +numeric | string | number (float) +decimal | string | number (float) +``` + +For more information see https://github.com/brianc/node-postgres/pull/353 +If you are unhappy with these changes you can always [override the built in type parsing fairly easily](https://github.com/brianc/node-pg-parse-float). + +### v1.3.0 + +- Make client_encoding configurable and optional + +### v1.2.0 + +- return field metadata on result object: access via result.fields[i].name/dataTypeID + +### v1.1.0 + +- built in support for `JSON` data type for PostgreSQL Server @ v9.2.0 or greater + +### v1.0.0 + +- remove deprecated functionality + - Callback function passed to `pg.connect` now **requires** 3 arguments + - Client#pauseDrain() / Client#resumeDrain removed + - numeric, decimal, and float data types no longer parsed into float before being returned. Will be returned from query results as `String` + +### v0.15.0 + +- client now emits `end` when disconnected from back-end server +- if client is disconnected in the middle of a query, query receives an error + +### v0.14.0 + +- add deprecation warnings in prep for v1.0 +- fix read/write failures in native module under node v0.9.x From 4a80468a8a2eec92ee0240c37b18300590410d96 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Sat, 9 May 2020 15:44:24 -0400 Subject: [PATCH 0648/1037] test: Add sasl-scram-tests.js Adds tests for SCRAM if SCRAM_TEST_PGUSER and SCRAM_TEST_PGPASSWORD are defined. If not the tests are skipped (default). --- .../integration/client/sasl-scram-tests.js | 100 ++++++++++++------ 1 file changed, 67 insertions(+), 33 deletions(-) diff --git a/packages/pg/test/integration/client/sasl-scram-tests.js b/packages/pg/test/integration/client/sasl-scram-tests.js index f5326d8ae..debc28685 100644 --- a/packages/pg/test/integration/client/sasl-scram-tests.js +++ b/packages/pg/test/integration/client/sasl-scram-tests.js @@ -1,41 +1,75 @@ 'use strict' -var helper = require(__dirname + '/../test-helper') -var pg = helper.pg +const helper = require('./../test-helper') +const pg = helper.pg +const suite = new helper.Suite() +const { native } = helper.args -var suite = new helper.Suite() +/** + * This test only executes if the env variables SCRAM_TEST_PGUSER and + * SCRAM_TEST_PGPASSWORD are defined. You can override additional values + * for the host, port and database with other SCRAM_TEST_ prefixed vars. + * If the variables are not defined the test will be skipped. + * + * SQL to create test role: + * + * SET password_encryption = 'scram-sha-256'; + * CREATE ROLE scram_test login password 'test4scram'; + * + * Add the following entries to pg_hba.conf: + * + * host all scram_test ::1/128 scram-sha-256 + * host all scram_test 0.0.0.0/0 scram-sha-256 + * + * Then run this file with after exporting: + * + * SCRAM_TEST_PGUSER=scram_test + * SCRAM_TEST_PGPASSWORD=test4scram + */ -/* -SQL to create test role: +// Base config for SCRAM tests +const config = { + user: process.env.SCRAM_TEST_PGUSER, + password: process.env.SCRAM_TEST_PGPASSWORD, + host: process.env.SCRAM_TEST_PGHOST, // optional + port: process.env.SCRAM_TEST_PGPORT, // optional + database: process.env.SCRAM_TEST_PGDATABASE, // optional +} -set password_encryption = 'scram-sha-256'; -create role npgtest login password 'test'; +if (native) { + suite.testAsync('skipping SCRAM tests (on native)', () => {}) + return +} +if (!config.user || !config.password) { + suite.testAsync('skipping SCRAM tests (missing env)', () => {}) + return +} -pg_hba: -host all npgtest ::1/128 scram-sha-256 -host all npgtest 0.0.0.0/0 scram-sha-256 - - -*/ -/* -suite.test('can connect using sasl/scram', function () { - var connectionString = 'pg://npgtest:test@localhost/postgres' - const pool = new pg.Pool({ connectionString: connectionString }) - pool.connect( - assert.calls(function (err, client, done) { - assert.ifError(err, 'should have connected') - done() - }) - ) +suite.testAsync('can connect using sasl/scram', async () => { + const client = new pg.Client(config) + let usingSasl = false + client.connection.once('authenticationSASL', () => { + usingSasl = true + }) + await client.connect() + assert.ok(usingSasl, 'Should be using SASL for authentication') + await client.end() }) -suite.test('sasl/scram fails when password is wrong', function () { - var connectionString = 'pg://npgtest:bad@localhost/postgres' - const pool = new pg.Pool({ connectionString: connectionString }) - pool.connect( - assert.calls(function (err, client, done) { - assert.ok(err, 'should have a connection error') - done() - }) - ) +suite.testAsync('sasl/scram fails when password is wrong', async () => { + const client = new pg.Client({ + ...config, + password: config.password + 'append-something-to-make-it-bad', + }) + let usingSasl = false + client.connection.once('authenticationSASL', () => { + usingSasl = true + }) + await assert.rejects( + () => client.connect(), + { + code: '28P01', + }, + 'Error code should be for a password error' + ) + assert.ok(usingSasl, 'Should be using SASL for authentication') }) -*/ From c25e88916a1757491bbf0ebcb30a8332b4a24377 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Sat, 9 May 2020 16:17:54 -0400 Subject: [PATCH 0649/1037] test: Enable scram tests on travis --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0518579d7..9629156e2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ matrix: # Run tests/paths that require password authentication - node_js: lts/erbium env: - - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres PGPASSWORD=test-password + - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres PGPASSWORD=test-password SCRAM_TEST_PGUSER=scram_test SCRAM_TEST_PGPASSWORD=test4scram before_script: | sudo -u postgres sed -i \ -e '/^local/ s/trust$/peer/' \ @@ -36,6 +36,9 @@ matrix: sudo -u postgres psql -c "ALTER ROLE postgres PASSWORD 'test-password'; SELECT pg_reload_conf()" yarn build node packages/pg/script/create-test-tables.js postgresql:/// + sudo -u postgres -- psql \ + -c "SET password_encryption = 'scram-sha-256'" \ + -c "CREATE ROLE scram_test login password 'test4scram'" - node_js: lts/carbon addons: From 520bd3531990f32c3e00b20020c67f6ac6c70261 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 12 May 2020 10:56:14 -0500 Subject: [PATCH 0650/1037] Switch internals to use faster connection This switches the internals to use faster protocol parsing & serializing. This results in a significant (30% - 50%) speed up in some common query patterns. There is quite a bit more performance work I need to do, but this takes care of some initial stuff & removes a big fork in the code. --- .travis.yml | 18 +- packages/pg/lib/client.js | 3 - packages/pg/lib/connection-fast.js | 214 ------- packages/pg/lib/connection.js | 550 ++---------------- .../unit/connection/outbound-sending-tests.js | 205 ------- 5 files changed, 51 insertions(+), 939 deletions(-) delete mode 100644 packages/pg/lib/connection-fast.js delete mode 100644 packages/pg/test/unit/connection/outbound-sending-tests.js diff --git a/.travis.yml b/.travis.yml index 9629156e2..7987f761b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,20 +7,18 @@ before_script: | env: - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres - # test w/ new faster parsing code - - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres PG_FAST_CONNECTION=true node_js: - lts/dubnium - lts/erbium # node 13.7 seems to have changed behavior of async iterators exiting early on streams # if 13.8 still has this problem when it comes down I'll talk to the node team about the change - # in the mean time...peg to 13.6 + # in the mean time...peg to 13.6 - 13.6 - 14 addons: - postgresql: "10" + postgresql: '10' matrix: include: @@ -42,25 +40,25 @@ matrix: - node_js: lts/carbon addons: - postgresql: "9.5" + postgresql: '9.5' dist: precise # different PostgreSQL versions on Node LTS - node_js: lts/erbium addons: - postgresql: "9.3" + postgresql: '9.3' - node_js: lts/erbium addons: - postgresql: "9.4" + postgresql: '9.4' - node_js: lts/erbium addons: - postgresql: "9.5" + postgresql: '9.5' - node_js: lts/erbium addons: - postgresql: "9.6" + postgresql: '9.6' # PostgreSQL 9.2 only works on precise - node_js: lts/carbon addons: - postgresql: "9.2" + postgresql: '9.2' dist: precise diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 76906712b..2c12f2cce 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -18,9 +18,6 @@ var ConnectionParameters = require('./connection-parameters') var Query = require('./query') var defaults = require('./defaults') var Connection = require('./connection') -if (process.env.PG_FAST_CONNECTION) { - Connection = require('./connection-fast') -} var Client = function (config) { EventEmitter.call(this) diff --git a/packages/pg/lib/connection-fast.js b/packages/pg/lib/connection-fast.js deleted file mode 100644 index 7cc2ed8cf..000000000 --- a/packages/pg/lib/connection-fast.js +++ /dev/null @@ -1,214 +0,0 @@ -'use strict' -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ - -var net = require('net') -var EventEmitter = require('events').EventEmitter -var util = require('util') - -const { parse, serialize } = require('pg-protocol') - -// TODO(bmc) support binary mode at some point -console.log('***using faster connection***') -var Connection = function (config) { - EventEmitter.call(this) - config = config || {} - this.stream = config.stream || new net.Socket() - this.stream.setNoDelay(true) - this._keepAlive = config.keepAlive - this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis - this.lastBuffer = false - this.parsedStatements = {} - this.ssl = config.ssl || false - this._ending = false - this._emitMessage = false - var self = this - this.on('newListener', function (eventName) { - if (eventName === 'message') { - self._emitMessage = true - } - }) -} - -util.inherits(Connection, EventEmitter) - -Connection.prototype.connect = function (port, host) { - var self = this - - this._connecting = true - this.stream.connect(port, host) - - this.stream.once('connect', function () { - if (self._keepAlive) { - self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis) - } - self.emit('connect') - }) - - const reportStreamError = function (error) { - // errors about disconnections should be ignored during disconnect - if (self._ending && (error.code === 'ECONNRESET' || error.code === 'EPIPE')) { - return - } - self.emit('error', error) - } - this.stream.on('error', reportStreamError) - - this.stream.on('close', function () { - self.emit('end') - }) - - if (!this.ssl) { - return this.attachListeners(this.stream) - } - - this.stream.once('data', function (buffer) { - var responseCode = buffer.toString('utf8') - switch (responseCode) { - case 'S': // Server supports SSL connections, continue with a secure connection - break - case 'N': // Server does not support SSL connections - self.stream.end() - return self.emit('error', new Error('The server does not support SSL connections')) - default: - // Any other response byte, including 'E' (ErrorResponse) indicating a server error - self.stream.end() - return self.emit('error', new Error('There was an error establishing an SSL connection')) - } - var tls = require('tls') - const options = Object.assign( - { - socket: self.stream, - }, - self.ssl - ) - if (net.isIP(host) === 0) { - options.servername = host - } - self.stream = tls.connect(options) - self.attachListeners(self.stream) - self.stream.on('error', reportStreamError) - - self.emit('sslconnect') - }) -} - -Connection.prototype.attachListeners = function (stream) { - stream.on('end', () => { - this.emit('end') - }) - parse(stream, (msg) => { - var eventName = msg.name === 'error' ? 'errorMessage' : msg.name - if (this._emitMessage) { - this.emit('message', msg) - } - this.emit(eventName, msg) - }) -} - -Connection.prototype.requestSsl = function () { - this.stream.write(serialize.requestSsl()) -} - -Connection.prototype.startup = function (config) { - this.stream.write(serialize.startup(config)) -} - -Connection.prototype.cancel = function (processID, secretKey) { - this._send(serialize.cancel(processID, secretKey)) -} - -Connection.prototype.password = function (password) { - this._send(serialize.password(password)) -} - -Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) { - this._send(serialize.sendSASLInitialResponseMessage(mechanism, initialResponse)) -} - -Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) { - this._send(serialize.sendSCRAMClientFinalMessage(additionalData)) -} - -Connection.prototype._send = function (buffer) { - if (!this.stream.writable) { - return false - } - return this.stream.write(buffer) -} - -Connection.prototype.query = function (text) { - this._send(serialize.query(text)) -} - -// send parse message -Connection.prototype.parse = function (query) { - this._send(serialize.parse(query)) -} - -// send bind message -// "more" === true to buffer the message until flush() is called -Connection.prototype.bind = function (config) { - this._send(serialize.bind(config)) -} - -// send execute message -// "more" === true to buffer the message until flush() is called -Connection.prototype.execute = function (config) { - this._send(serialize.execute(config)) -} - -const flushBuffer = serialize.flush() -Connection.prototype.flush = function () { - if (this.stream.writable) { - this.stream.write(flushBuffer) - } -} - -const syncBuffer = serialize.sync() -Connection.prototype.sync = function () { - this._ending = true - this._send(syncBuffer) - this._send(flushBuffer) -} - -const endBuffer = serialize.end() - -Connection.prototype.end = function () { - // 0x58 = 'X' - this._ending = true - if (!this._connecting || !this.stream.writable) { - this.stream.end() - return - } - return this.stream.write(endBuffer, () => { - this.stream.end() - }) -} - -Connection.prototype.close = function (msg) { - this._send(serialize.close(msg)) -} - -Connection.prototype.describe = function (msg) { - this._send(serialize.describe(msg)) -} - -Connection.prototype.sendCopyFromChunk = function (chunk) { - this._send(serialize.copyData(chunk)) -} - -Connection.prototype.endCopyFrom = function () { - this._send(serialize.copyDone()) -} - -Connection.prototype.sendCopyFail = function (msg) { - this._send(serialize.copyFail(msg)) -} - -module.exports = Connection diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index c3f30aa0f..bce183484 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -11,11 +11,9 @@ var net = require('net') var EventEmitter = require('events').EventEmitter var util = require('util') -var Writer = require('buffer-writer') -var Reader = require('packet-reader') +const { parse, serialize } = require('pg-protocol') -var TEXT_MODE = 0 -var BINARY_MODE = 1 +// TODO(bmc) support binary mode at some point var Connection = function (config) { EventEmitter.call(this) config = config || {} @@ -23,20 +21,10 @@ var Connection = function (config) { this._keepAlive = config.keepAlive this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis this.lastBuffer = false - this.lastOffset = 0 - this.buffer = null - this.offset = null - this.encoding = config.encoding || 'utf8' this.parsedStatements = {} - this.writer = new Writer() this.ssl = config.ssl || false this._ending = false - this._mode = TEXT_MODE this._emitMessage = false - this._reader = new Reader({ - headerSize: 1, - lengthPadding: -4, - }) var self = this this.on('newListener', function (eventName) { if (eventName === 'message') { @@ -101,576 +89,124 @@ Connection.prototype.connect = function (port, host) { options.servername = host } self.stream = tls.connect(options) - self.stream.on('error', reportStreamError) self.attachListeners(self.stream) + self.stream.on('error', reportStreamError) + self.emit('sslconnect') }) } Connection.prototype.attachListeners = function (stream) { - var self = this - stream.on('data', function (buff) { - self._reader.addChunk(buff) - var packet = self._reader.read() - while (packet) { - var msg = self.parseMessage(packet) - var eventName = msg.name === 'error' ? 'errorMessage' : msg.name - if (self._emitMessage) { - self.emit('message', msg) - } - self.emit(eventName, msg) - packet = self._reader.read() - } + stream.on('end', () => { + this.emit('end') }) - stream.on('end', function () { - self.emit('end') + parse(stream, (msg) => { + var eventName = msg.name === 'error' ? 'errorMessage' : msg.name + if (this._emitMessage) { + this.emit('message', msg) + } + this.emit(eventName, msg) }) } Connection.prototype.requestSsl = function () { - var bodyBuffer = this.writer.addInt16(0x04d2).addInt16(0x162f).flush() - - var length = bodyBuffer.length + 4 - - var buffer = new Writer().addInt32(length).add(bodyBuffer).join() - this.stream.write(buffer) + this.stream.write(serialize.requestSsl()) } Connection.prototype.startup = function (config) { - var writer = this.writer.addInt16(3).addInt16(0) - - Object.keys(config).forEach(function (key) { - var val = config[key] - writer.addCString(key).addCString(val) - }) - - writer.addCString('client_encoding').addCString("'utf-8'") - - var bodyBuffer = writer.addCString('').flush() - // this message is sent without a code - - var length = bodyBuffer.length + 4 - - var buffer = new Writer().addInt32(length).add(bodyBuffer).join() - this.stream.write(buffer) + this.stream.write(serialize.startup(config)) } Connection.prototype.cancel = function (processID, secretKey) { - var bodyBuffer = this.writer.addInt16(1234).addInt16(5678).addInt32(processID).addInt32(secretKey).flush() - - var length = bodyBuffer.length + 4 - - var buffer = new Writer().addInt32(length).add(bodyBuffer).join() - this.stream.write(buffer) + this._send(serialize.cancel(processID, secretKey)) } Connection.prototype.password = function (password) { - // 0x70 = 'p' - this._send(0x70, this.writer.addCString(password)) + this._send(serialize.password(password)) } Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) { - // 0x70 = 'p' - this.writer.addCString(mechanism).addInt32(Buffer.byteLength(initialResponse)).addString(initialResponse) - - this._send(0x70) + this._send(serialize.sendSASLInitialResponseMessage(mechanism, initialResponse)) } Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) { - // 0x70 = 'p' - this.writer.addString(additionalData) - - this._send(0x70) + this._send(serialize.sendSCRAMClientFinalMessage(additionalData)) } -Connection.prototype._send = function (code, more) { +Connection.prototype._send = function (buffer) { if (!this.stream.writable) { return false } - if (more === true) { - this.writer.addHeader(code) - } else { - return this.stream.write(this.writer.flush(code)) - } + return this.stream.write(buffer) } Connection.prototype.query = function (text) { - // 0x51 = Q - this.stream.write(this.writer.addCString(text).flush(0x51)) + this._send(serialize.query(text)) } // send parse message -// "more" === true to buffer the message until flush() is called -Connection.prototype.parse = function (query, more) { - // expect something like this: - // { name: 'queryName', - // text: 'select * from blah', - // types: ['int8', 'bool'] } - - // normalize missing query names to allow for null - query.name = query.name || '' - if (query.name.length > 63) { - /* eslint-disable no-console */ - console.error('Warning! Postgres only supports 63 characters for query names.') - console.error('You supplied %s (%s)', query.name, query.name.length) - console.error('This can cause conflicts and silent errors executing queries') - /* eslint-enable no-console */ - } - // normalize null type array - query.types = query.types || [] - var len = query.types.length - var buffer = this.writer - .addCString(query.name) // name of query - .addCString(query.text) // actual query text - .addInt16(len) - for (var i = 0; i < len; i++) { - buffer.addInt32(query.types[i]) - } - - var code = 0x50 - this._send(code, more) +Connection.prototype.parse = function (query) { + this._send(serialize.parse(query)) } // send bind message // "more" === true to buffer the message until flush() is called -Connection.prototype.bind = function (config, more) { - // normalize config - config = config || {} - config.portal = config.portal || '' - config.statement = config.statement || '' - config.binary = config.binary || false - var values = config.values || [] - var len = values.length - var useBinary = false - for (var j = 0; j < len; j++) { - useBinary |= values[j] instanceof Buffer - } - var buffer = this.writer.addCString(config.portal).addCString(config.statement) - if (!useBinary) { - buffer.addInt16(0) - } else { - buffer.addInt16(len) - for (j = 0; j < len; j++) { - buffer.addInt16(values[j] instanceof Buffer) - } - } - buffer.addInt16(len) - for (var i = 0; i < len; i++) { - var val = values[i] - if (val === null || typeof val === 'undefined') { - buffer.addInt32(-1) - } else if (val instanceof Buffer) { - buffer.addInt32(val.length) - buffer.add(val) - } else { - buffer.addInt32(Buffer.byteLength(val)) - buffer.addString(val) - } - } - - if (config.binary) { - buffer.addInt16(1) // format codes to use binary - buffer.addInt16(1) - } else { - buffer.addInt16(0) // format codes to use text - } - // 0x42 = 'B' - this._send(0x42, more) +Connection.prototype.bind = function (config) { + this._send(serialize.bind(config)) } // send execute message // "more" === true to buffer the message until flush() is called -Connection.prototype.execute = function (config, more) { - config = config || {} - config.portal = config.portal || '' - config.rows = config.rows || '' - this.writer.addCString(config.portal).addInt32(config.rows) - - // 0x45 = 'E' - this._send(0x45, more) +Connection.prototype.execute = function (config) { + this._send(serialize.execute(config)) } -var emptyBuffer = Buffer.alloc(0) - +const flushBuffer = serialize.flush() Connection.prototype.flush = function () { - // 0x48 = 'H' - this.writer.add(emptyBuffer) - this._send(0x48) + if (this.stream.writable) { + this.stream.write(flushBuffer) + } } +const syncBuffer = serialize.sync() Connection.prototype.sync = function () { - // clear out any pending data in the writer - this.writer.flush(0) - - this.writer.add(emptyBuffer) this._ending = true - this._send(0x53) + this._send(syncBuffer) + this._send(flushBuffer) } -const END_BUFFER = Buffer.from([0x58, 0x00, 0x00, 0x00, 0x04]) +const endBuffer = serialize.end() Connection.prototype.end = function () { // 0x58 = 'X' - this.writer.add(emptyBuffer) this._ending = true if (!this._connecting || !this.stream.writable) { this.stream.end() return } - return this.stream.write(END_BUFFER, () => { + return this.stream.write(endBuffer, () => { this.stream.end() }) } -Connection.prototype.close = function (msg, more) { - this.writer.addCString(msg.type + (msg.name || '')) - this._send(0x43, more) +Connection.prototype.close = function (msg) { + this._send(serialize.close(msg)) } -Connection.prototype.describe = function (msg, more) { - this.writer.addCString(msg.type + (msg.name || '')) - this._send(0x44, more) +Connection.prototype.describe = function (msg) { + this._send(serialize.describe(msg)) } Connection.prototype.sendCopyFromChunk = function (chunk) { - this.stream.write(this.writer.add(chunk).flush(0x64)) + this._send(serialize.copyData(chunk)) } Connection.prototype.endCopyFrom = function () { - this.stream.write(this.writer.add(emptyBuffer).flush(0x63)) + this._send(serialize.copyDone()) } Connection.prototype.sendCopyFail = function (msg) { - // this.stream.write(this.writer.add(emptyBuffer).flush(0x66)); - this.writer.addCString(msg) - this._send(0x66) + this._send(serialize.copyFail(msg)) } -var Message = function (name, length) { - this.name = name - this.length = length -} - -Connection.prototype.parseMessage = function (buffer) { - this.offset = 0 - var length = buffer.length + 4 - switch (this._reader.header) { - case 0x52: // R - return this.parseR(buffer, length) - - case 0x53: // S - return this.parseS(buffer, length) - - case 0x4b: // K - return this.parseK(buffer, length) - - case 0x43: // C - return this.parseC(buffer, length) - - case 0x5a: // Z - return this.parseZ(buffer, length) - - case 0x54: // T - return this.parseT(buffer, length) - - case 0x44: // D - return this.parseD(buffer, length) - - case 0x45: // E - return this.parseE(buffer, length) - - case 0x4e: // N - return this.parseN(buffer, length) - - case 0x31: // 1 - return new Message('parseComplete', length) - - case 0x32: // 2 - return new Message('bindComplete', length) - - case 0x33: // 3 - return new Message('closeComplete', length) - - case 0x41: // A - return this.parseA(buffer, length) - - case 0x6e: // n - return new Message('noData', length) - - case 0x49: // I - return new Message('emptyQuery', length) - - case 0x73: // s - return new Message('portalSuspended', length) - - case 0x47: // G - return this.parseG(buffer, length) - - case 0x48: // H - return this.parseH(buffer, length) - - case 0x57: // W - return new Message('replicationStart', length) - - case 0x63: // c - return new Message('copyDone', length) - - case 0x64: // d - return this.parsed(buffer, length) - } -} - -Connection.prototype.parseR = function (buffer, length) { - var code = this.parseInt32(buffer) - - var msg = new Message('authenticationOk', length) - - switch (code) { - case 0: // AuthenticationOk - return msg - case 3: // AuthenticationCleartextPassword - if (msg.length === 8) { - msg.name = 'authenticationCleartextPassword' - return msg - } - break - case 5: // AuthenticationMD5Password - if (msg.length === 12) { - msg.name = 'authenticationMD5Password' - msg.salt = Buffer.alloc(4) - buffer.copy(msg.salt, 0, this.offset, this.offset + 4) - this.offset += 4 - return msg - } - - break - case 10: // AuthenticationSASL - msg.name = 'authenticationSASL' - msg.mechanisms = [] - do { - var mechanism = this.parseCString(buffer) - - if (mechanism) { - msg.mechanisms.push(mechanism) - } - } while (mechanism) - - return msg - case 11: // AuthenticationSASLContinue - msg.name = 'authenticationSASLContinue' - msg.data = this.readString(buffer, length - 4) - - return msg - case 12: // AuthenticationSASLFinal - msg.name = 'authenticationSASLFinal' - msg.data = this.readString(buffer, length - 4) - - return msg - } - - throw new Error('Unknown authenticationOk message type' + util.inspect(msg)) -} - -Connection.prototype.parseS = function (buffer, length) { - var msg = new Message('parameterStatus', length) - msg.parameterName = this.parseCString(buffer) - msg.parameterValue = this.parseCString(buffer) - return msg -} - -Connection.prototype.parseK = function (buffer, length) { - var msg = new Message('backendKeyData', length) - msg.processID = this.parseInt32(buffer) - msg.secretKey = this.parseInt32(buffer) - return msg -} - -Connection.prototype.parseC = function (buffer, length) { - var msg = new Message('commandComplete', length) - msg.text = this.parseCString(buffer) - return msg -} - -Connection.prototype.parseZ = function (buffer, length) { - var msg = new Message('readyForQuery', length) - msg.name = 'readyForQuery' - msg.status = this.readString(buffer, 1) - return msg -} - -var ROW_DESCRIPTION = 'rowDescription' -Connection.prototype.parseT = function (buffer, length) { - var msg = new Message(ROW_DESCRIPTION, length) - msg.fieldCount = this.parseInt16(buffer) - var fields = [] - for (var i = 0; i < msg.fieldCount; i++) { - fields.push(this.parseField(buffer)) - } - msg.fields = fields - return msg -} - -var Field = function () { - this.name = null - this.tableID = null - this.columnID = null - this.dataTypeID = null - this.dataTypeSize = null - this.dataTypeModifier = null - this.format = null -} - -var FORMAT_TEXT = 'text' -var FORMAT_BINARY = 'binary' -Connection.prototype.parseField = function (buffer) { - var field = new Field() - field.name = this.parseCString(buffer) - field.tableID = this.parseInt32(buffer) - field.columnID = this.parseInt16(buffer) - field.dataTypeID = this.parseInt32(buffer) - field.dataTypeSize = this.parseInt16(buffer) - field.dataTypeModifier = this.parseInt32(buffer) - if (this.parseInt16(buffer) === TEXT_MODE) { - this._mode = TEXT_MODE - field.format = FORMAT_TEXT - } else { - this._mode = BINARY_MODE - field.format = FORMAT_BINARY - } - return field -} - -var DATA_ROW = 'dataRow' -var DataRowMessage = function (length, fieldCount) { - this.name = DATA_ROW - this.length = length - this.fieldCount = fieldCount - this.fields = [] -} - -// extremely hot-path code -Connection.prototype.parseD = function (buffer, length) { - var fieldCount = this.parseInt16(buffer) - var msg = new DataRowMessage(length, fieldCount) - for (var i = 0; i < fieldCount; i++) { - msg.fields.push(this._readValue(buffer)) - } - return msg -} - -// extremely hot-path code -Connection.prototype._readValue = function (buffer) { - var length = this.parseInt32(buffer) - if (length === -1) return null - if (this._mode === TEXT_MODE) { - return this.readString(buffer, length) - } - return this.readBytes(buffer, length) -} - -// parses error -Connection.prototype.parseE = function (buffer, length, isNotice) { - var fields = {} - var fieldType = this.readString(buffer, 1) - while (fieldType !== '\0') { - fields[fieldType] = this.parseCString(buffer) - fieldType = this.readString(buffer, 1) - } - - // the msg is an Error instance - var msg = isNotice ? { message: fields.M } : new Error(fields.M) - - // for compatibility with Message - msg.name = isNotice ? 'notice' : 'error' - msg.length = length - - msg.severity = fields.S - msg.code = fields.C - msg.detail = fields.D - msg.hint = fields.H - msg.position = fields.P - msg.internalPosition = fields.p - msg.internalQuery = fields.q - msg.where = fields.W - msg.schema = fields.s - msg.table = fields.t - msg.column = fields.c - msg.dataType = fields.d - msg.constraint = fields.n - msg.file = fields.F - msg.line = fields.L - msg.routine = fields.R - return msg -} - -// same thing, different name -Connection.prototype.parseN = function (buffer, length) { - var msg = this.parseE(buffer, length, true) - msg.name = 'notice' - return msg -} - -Connection.prototype.parseA = function (buffer, length) { - var msg = new Message('notification', length) - msg.processId = this.parseInt32(buffer) - msg.channel = this.parseCString(buffer) - msg.payload = this.parseCString(buffer) - return msg -} - -Connection.prototype.parseG = function (buffer, length) { - var msg = new Message('copyInResponse', length) - return this.parseGH(buffer, msg) -} - -Connection.prototype.parseH = function (buffer, length) { - var msg = new Message('copyOutResponse', length) - return this.parseGH(buffer, msg) -} - -Connection.prototype.parseGH = function (buffer, msg) { - var isBinary = buffer[this.offset] !== 0 - this.offset++ - msg.binary = isBinary - var columnCount = this.parseInt16(buffer) - msg.columnTypes = [] - for (var i = 0; i < columnCount; i++) { - msg.columnTypes.push(this.parseInt16(buffer)) - } - return msg -} - -Connection.prototype.parsed = function (buffer, length) { - var msg = new Message('copyData', length) - msg.chunk = this.readBytes(buffer, msg.length - 4) - return msg -} - -Connection.prototype.parseInt32 = function (buffer) { - var value = buffer.readInt32BE(this.offset) - this.offset += 4 - return value -} - -Connection.prototype.parseInt16 = function (buffer) { - var value = buffer.readInt16BE(this.offset) - this.offset += 2 - return value -} - -Connection.prototype.readString = function (buffer, length) { - return buffer.toString(this.encoding, this.offset, (this.offset += length)) -} - -Connection.prototype.readBytes = function (buffer, length) { - return buffer.slice(this.offset, (this.offset += length)) -} - -Connection.prototype.parseCString = function (buffer) { - var start = this.offset - var end = buffer.indexOf(0, start) - this.offset = end + 1 - return buffer.toString(this.encoding, start, end) -} -// end parsing methods module.exports = Connection diff --git a/packages/pg/test/unit/connection/outbound-sending-tests.js b/packages/pg/test/unit/connection/outbound-sending-tests.js deleted file mode 100644 index 8b21de4ce..000000000 --- a/packages/pg/test/unit/connection/outbound-sending-tests.js +++ /dev/null @@ -1,205 +0,0 @@ -'use strict' -require(__dirname + '/test-helper') -var Connection = require(__dirname + '/../../../lib/connection') -var stream = new MemoryStream() -var con = new Connection({ - stream: stream, -}) -con._connecting = true - -assert.received = function (stream, buffer) { - assert.lengthIs(stream.packets, 1) - var packet = stream.packets.pop() - assert.equalBuffers(packet, buffer) -} - -test('sends startup message', function () { - con.startup({ - user: 'brian', - database: 'bang', - }) - assert.received( - stream, - new BufferList() - .addInt16(3) - .addInt16(0) - .addCString('user') - .addCString('brian') - .addCString('database') - .addCString('bang') - .addCString('client_encoding') - .addCString("'utf-8'") - .addCString('') - .join(true) - ) -}) - -test('sends password message', function () { - con.password('!') - assert.received(stream, new BufferList().addCString('!').join(true, 'p')) -}) - -test('sends SASLInitialResponseMessage message', function () { - con.sendSASLInitialResponseMessage('mech', 'data') - assert.received(stream, new BufferList().addCString('mech').addInt32(4).addString('data').join(true, 'p')) -}) - -test('sends SCRAMClientFinalMessage message', function () { - con.sendSCRAMClientFinalMessage('data') - assert.received(stream, new BufferList().addString('data').join(true, 'p')) -}) - -test('sends query message', function () { - var txt = 'select * from boom' - con.query(txt) - assert.received(stream, new BufferList().addCString(txt).join(true, 'Q')) -}) - -test('sends parse message', function () { - con.parse({ text: '!' }) - var expected = new BufferList().addCString('').addCString('!').addInt16(0).join(true, 'P') - assert.received(stream, expected) -}) - -test('sends parse message with named query', function () { - con.parse({ - name: 'boom', - text: 'select * from boom', - types: [], - }) - var expected = new BufferList().addCString('boom').addCString('select * from boom').addInt16(0).join(true, 'P') - assert.received(stream, expected) - - test('with multiple parameters', function () { - con.parse({ - name: 'force', - text: 'select * from bang where name = $1', - types: [1, 2, 3, 4], - }) - var expected = new BufferList() - .addCString('force') - .addCString('select * from bang where name = $1') - .addInt16(4) - .addInt32(1) - .addInt32(2) - .addInt32(3) - .addInt32(4) - .join(true, 'P') - assert.received(stream, expected) - }) -}) - -test('bind messages', function () { - test('with no values', function () { - con.bind() - - var expectedBuffer = new BufferList() - .addCString('') - .addCString('') - .addInt16(0) - .addInt16(0) - .addInt16(0) - .join(true, 'B') - assert.received(stream, expectedBuffer) - }) - - test('with named statement, portal, and values', function () { - con.bind({ - portal: 'bang', - statement: 'woo', - values: ['1', 'hi', null, 'zing'], - }) - var expectedBuffer = new BufferList() - .addCString('bang') // portal name - .addCString('woo') // statement name - .addInt16(0) - .addInt16(4) - .addInt32(1) - .add(Buffer.from('1')) - .addInt32(2) - .add(Buffer.from('hi')) - .addInt32(-1) - .addInt32(4) - .add(Buffer.from('zing')) - .addInt16(0) - .join(true, 'B') - assert.received(stream, expectedBuffer) - }) -}) - -test('with named statement, portal, and buffer value', function () { - con.bind({ - portal: 'bang', - statement: 'woo', - values: ['1', 'hi', null, Buffer.from('zing', 'utf8')], - }) - var expectedBuffer = new BufferList() - .addCString('bang') // portal name - .addCString('woo') // statement name - .addInt16(4) // value count - .addInt16(0) // string - .addInt16(0) // string - .addInt16(0) // string - .addInt16(1) // binary - .addInt16(4) - .addInt32(1) - .add(Buffer.from('1')) - .addInt32(2) - .add(Buffer.from('hi')) - .addInt32(-1) - .addInt32(4) - .add(Buffer.from('zing', 'UTF-8')) - .addInt16(0) - .join(true, 'B') - assert.received(stream, expectedBuffer) -}) - -test('sends execute message', function () { - test('for unamed portal with no row limit', function () { - con.execute() - var expectedBuffer = new BufferList().addCString('').addInt32(0).join(true, 'E') - assert.received(stream, expectedBuffer) - }) - - test('for named portal with row limit', function () { - con.execute({ - portal: 'my favorite portal', - rows: 100, - }) - var expectedBuffer = new BufferList().addCString('my favorite portal').addInt32(100).join(true, 'E') - assert.received(stream, expectedBuffer) - }) -}) - -test('sends flush command', function () { - con.flush() - var expected = new BufferList().join(true, 'H') - assert.received(stream, expected) -}) - -test('sends sync command', function () { - con.sync() - var expected = new BufferList().join(true, 'S') - assert.received(stream, expected) -}) - -test('sends end command', function () { - con.end() - var expected = Buffer.from([0x58, 0, 0, 0, 4]) - assert.received(stream, expected) - assert.equal(stream.closed, true) -}) - -test('sends describe command', function () { - test('describe statement', function () { - con.describe({ type: 'S', name: 'bang' }) - var expected = new BufferList().addChar('S').addCString('bang').join(true, 'D') - assert.received(stream, expected) - }) - - test('describe unnamed portal', function () { - con.describe({ type: 'P' }) - var expected = new BufferList().addChar('P').addCString('').join(true, 'D') - assert.received(stream, expected) - }) -}) From 08afb12dccacad265e6fc164ee0421285a5c9369 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 12 May 2020 16:32:40 -0500 Subject: [PATCH 0651/1037] Set noDelay to true --- packages/pg/lib/connection.js | 1 + .../unit/client/stream-and-query-error-interaction-tests.js | 1 + packages/pg/test/unit/test-helper.js | 2 ++ 3 files changed, 4 insertions(+) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index bce183484..98b6b5a5f 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -39,6 +39,7 @@ Connection.prototype.connect = function (port, host) { var self = this this._connecting = true + this.stream.setNoDelay(true) this.stream.connect(port, host) this.stream.once('connect', function () { diff --git a/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js index 041af010d..3f84ae4a5 100644 --- a/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js +++ b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js @@ -5,6 +5,7 @@ var Client = require(__dirname + '/../../../lib/client') test('emits end when not in query', function () { var stream = new (require('events').EventEmitter)() + stream.setNoDelay = () => {} stream.connect = function () { // NOOP } diff --git a/packages/pg/test/unit/test-helper.js b/packages/pg/test/unit/test-helper.js index 918b14187..407dbf247 100644 --- a/packages/pg/test/unit/test-helper.js +++ b/packages/pg/test/unit/test-helper.js @@ -17,6 +17,8 @@ p.connect = function () { // NOOP } +p.setNoDelay = () => {} + p.write = function (packet, cb) { this.packets.push(packet) if (cb) { From 72b5f6d669d4602319e15a0707464ce5e22fb460 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 12 May 2020 17:20:17 -0500 Subject: [PATCH 0652/1037] Add test & fix packed packet parsing error for SASL authentication messages --- packages/pg-protocol/src/inbound-parser.test.ts | 13 +++++++++++++ packages/pg-protocol/src/parser.ts | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packages/pg-protocol/src/inbound-parser.test.ts b/packages/pg-protocol/src/inbound-parser.test.ts index 8a8785a5c..3fcbe410a 100644 --- a/packages/pg-protocol/src/inbound-parser.test.ts +++ b/packages/pg-protocol/src/inbound-parser.test.ts @@ -210,8 +210,21 @@ describe('PgPacketStream', function () { testForMessage(md5PasswordBuffer, expectedMD5PasswordMessage) testForMessage(SASLBuffer, expectedSASLMessage) testForMessage(SASLContinueBuffer, expectedSASLContinueMessage) + + // this exercises a found bug in the parser: + // https://github.com/brianc/node-postgres/pull/2210#issuecomment-627626084 + // and adds a test which is deterministic, rather than relying on network packet chunking + const extendedSASLContinueBuffer = Buffer.concat([SASLContinueBuffer, Buffer.from([1, 2, 3, 4])]) + testForMessage(extendedSASLContinueBuffer, expectedSASLContinueMessage) + testForMessage(SASLFinalBuffer, expectedSASLFinalMessage) + // this exercises a found bug in the parser: + // https://github.com/brianc/node-postgres/pull/2210#issuecomment-627626084 + // and adds a test which is deterministic, rather than relying on network packet chunking + const extendedSASLFinalBuffer = Buffer.concat([SASLFinalBuffer, Buffer.from([1, 2, 4, 5])]) + testForMessage(extendedSASLFinalBuffer, expectedSASLFinalMessage) + testForMessage(paramStatusBuffer, expectedParameterStatusMessage) testForMessage(backendKeyDataBuffer, expectedBackendKeyDataMessage) testForMessage(readyForQueryBuffer, expectedReadyForQueryMessage) diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 1531f3c0d..4044dae1c 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -296,11 +296,11 @@ export class Parser { break case 11: // AuthenticationSASLContinue message.name = MessageName.authenticationSASLContinue - message.data = this.reader.string(length - 4) + message.data = this.reader.string(length - 8) break case 12: // AuthenticationSASLFinal message.name = MessageName.authenticationSASLFinal - message.data = this.reader.string(length - 4) + message.data = this.reader.string(length - 8) break default: throw new Error('Unknown authenticationOk message type ' + code) From 9e55a7073b46da9f2ab274f1dd356087e2a7d982 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 13 May 2020 09:10:34 -0500 Subject: [PATCH 0653/1037] Publish - pg-cursor@2.2.0 - pg-protocol@1.2.3 - pg-query-stream@3.1.0 - pg@8.2.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 14af348ea..4309caf92 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.1.11", + "version": "2.2.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -17,6 +17,6 @@ "license": "MIT", "devDependencies": { "mocha": "^6.2.2", - "pg": "^8.1.0" + "pg": "^8.2.0" } } diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 60bc2027d..f35664385 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.2.2", + "version": "1.2.3", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index d6c8e96b4..775e65c1f 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.0.8", + "version": "3.1.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -26,12 +26,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^6.2.2", - "pg": "^8.1.0", + "pg": "^8.2.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.1.11" + "pg-cursor": "^2.2.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 1fda0daeb..81ef42479 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.1.0", + "version": "8.2.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "packet-reader": "1.0.0", "pg-connection-string": "^2.2.2", "pg-pool": "^3.2.0", - "pg-protocol": "^1.2.2", + "pg-protocol": "^1.2.3", "pg-types": "^2.1.0", "pgpass": "1.x", "semver": "4.3.2" From 70c8e5f45175bb7ddedf9a34035c5dafbd6c8d50 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 13 May 2020 09:17:08 -0500 Subject: [PATCH 0654/1037] Update changelog --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e92a7b0a..274c7487e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### pg@8.2.0 + +- Switch internal protocol parser & serializer to [pg-protocol](https://github.com/brianc/node-postgres/tree/master/packages/pg-protocol). The change is backwards compatible but results in a significant performance improvement across the board, with some queries as much as 50% faster. This is the first work to land in an on-going performance improvment initiative I'm working on. Stay tuned as things are set to get much faster still! :rocket: + +### pg-cursor@2.2.0 + +- Switch internal protocol parser & serializer to [pg-protocol](https://github.com/brianc/node-postgres/tree/master/packages/pg-protocol). The change is backwards compatible but results in a significant performance improvement across the board, with some queries as much as 50% faster. + +### pg-query-stream@3.1.0 + +- Switch internal protocol parser & serializer to [pg-protocol](https://github.com/brianc/node-postgres/tree/master/packages/pg-protocol). The change is backwards compatible but results in a significant performance improvement across the board, with some queries as much as 50% faster. + ### pg@8.1.0 - Switch to using [monorepo](https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string) version of `pg-connection-string`. This includes better support for SSL argument parsing from connection strings and ensures continuity of support. From 84044342794414969005bd9e091875367e77b8ec Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 13 May 2020 11:49:37 -0500 Subject: [PATCH 0655/1037] Upgrade mocha --- packages/pg-connection-string/package.json | 2 +- packages/pg-cursor/package.json | 2 +- packages/pg-pool/package.json | 2 +- packages/pg-pool/test/mocha.opts | 3 - packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 2 +- packages/pg-query-stream/test/mocha.opts | 1 - yarn.lock | 347 +++++++++------------ 8 files changed, 147 insertions(+), 214 deletions(-) delete mode 100644 packages/pg-pool/test/mocha.opts delete mode 100644 packages/pg-query-stream/test/mocha.opts diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index cdbbf527a..a2081e5e2 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -29,7 +29,7 @@ "chai": "^4.1.1", "coveralls": "^3.0.4", "istanbul": "^0.4.5", - "mocha": "^3.5.0" + "mocha": "^7.1.2" }, "files": [ "index.js", diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 4309caf92..ac580c30f 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -16,7 +16,7 @@ "author": "Brian M. Carlson", "license": "MIT", "devDependencies": { - "mocha": "^6.2.2", + "mocha": "^7.1.2", "pg": "^8.2.0" } } diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 176a3e41c..0c4c93a8f 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -30,7 +30,7 @@ "co": "4.6.0", "expect.js": "0.3.1", "lodash": "^4.17.11", - "mocha": "^5.2.0", + "mocha": "^7.1.2", "pg-cursor": "^1.3.0" }, "peerDependencies": { diff --git a/packages/pg-pool/test/mocha.opts b/packages/pg-pool/test/mocha.opts deleted file mode 100644 index eb0ba600d..000000000 --- a/packages/pg-pool/test/mocha.opts +++ /dev/null @@ -1,3 +0,0 @@ ---require test/setup.js ---bail ---timeout 10000 diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index f35664385..30cfe4095 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -11,7 +11,7 @@ "@types/node": "^12.12.21", "chai": "^4.2.0", "chunky": "^0.0.0", - "mocha": "^6.2.2", + "mocha": "^7.1.2", "ts-node": "^8.5.4", "typescript": "^3.7.3" }, diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 775e65c1f..0d454b1b6 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -25,7 +25,7 @@ "JSONStream": "~0.7.1", "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", - "mocha": "^6.2.2", + "mocha": "^7.1.2", "pg": "^8.2.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", diff --git a/packages/pg-query-stream/test/mocha.opts b/packages/pg-query-stream/test/mocha.opts deleted file mode 100644 index 8640eeef9..000000000 --- a/packages/pg-query-stream/test/mocha.opts +++ /dev/null @@ -1 +0,0 @@ ---bail diff --git a/yarn.lock b/yarn.lock index a1f07fa34..7bfd5878e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1048,6 +1048,14 @@ any-promise@^1.0.0: resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" integrity sha1-q8av7tzqUugJzcA3au0845Y10X8= +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + aproba@^1.0.3, aproba@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -1241,6 +1249,11 @@ before-after-hook@^2.0.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635" integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A== +binary-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" + integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== + bluebird@3.4.1: version "3.4.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.1.tgz#b731ddf48e2dd3bedac2e75e1215a11bcb91fa07" @@ -1288,10 +1301,12 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - integrity sha1-81HTKWnTL6XXpVZxVCY9korjvR8= +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" browser-stdout@1.3.1: version "1.3.1" @@ -1442,7 +1457,7 @@ chai@^4.1.1, chai@^4.2.0: pathval "^1.1.0" type-detect "^4.0.5" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1461,6 +1476,21 @@ check-error@^1.0.2: resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= +chokidar@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.0.tgz#12c0714668c55800f659e262d4962a97faf554a6" + integrity sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.2.0" + optionalDependencies: + fsevents "~2.1.1" + chownr@^1.1.1, chownr@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" @@ -1573,18 +1603,6 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@2.15.1: - version "2.15.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f" - integrity sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag== - -commander@2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4" - integrity sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q= - dependencies: - graceful-readlink ">= 1.0.0" - commander@~2.20.3: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -1821,13 +1839,6 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -debug@2.6.8: - version "2.6.8" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.8.tgz#e731531ca2ede27d188222427da17821d68ff4fc" - integrity sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw= - dependencies: - ms "2.0.0" - debug@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -1960,11 +1971,6 @@ dezalgo@^1.0.0: asap "^2.0.0" wrappy "1" -diff@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.2.0.tgz#c9ce393a4b7cbd0b058a725c93df299027868ff9" - integrity sha1-yc45Okt8vQsFinJck98pkCeGj/k= - diff@3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -2436,6 +2442,13 @@ fill-range@^4.0.0: repeat-string "^1.6.1" to-regex-range "^2.1.0" +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + find-up@3.0.0, find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" @@ -2561,6 +2574,11 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= +fsevents@~2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -2709,35 +2727,18 @@ glob-parent@^5.0.0: dependencies: is-glob "^4.0.1" +glob-parent@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + glob-to-regexp@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= -glob@7.1.1: - version "7.1.1" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.1.tgz#805211df04faaf1c63a3600306cdf5ade50b2ec8" - integrity sha1-gFIR3wT6rxxjo2ADBs31reULLsg= - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.2" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - integrity sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - glob@7.1.3: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" @@ -2799,21 +2800,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= - growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== -growl@1.9.2: - version "1.9.2" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" - integrity sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8= - handlebars@^4.0.1: version "4.7.6" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e" @@ -2908,11 +2899,6 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - integrity sha1-k0EP0hsAlzUVH4howvJx80J+I/0= - he@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -3129,6 +3115,13 @@ is-arrayish@^0.2.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" @@ -3241,7 +3234,7 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0, is-glob@^4.0.1: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== @@ -3255,6 +3248,11 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + is-obj@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" @@ -3427,11 +3425,6 @@ json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= -json3@3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.2.tgz#3c0434743df93e2f5c42aee7b19bcb483575f4e1" - integrity sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE= - jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -3567,34 +3560,6 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" -lodash._baseassign@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz#8c38a099500f215ad09e59f1722fd0c52bfe0a4e" - integrity sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4= - dependencies: - lodash._basecopy "^3.0.0" - lodash.keys "^3.0.0" - -lodash._basecopy@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz#8da0e6a876cf344c0ad8a54882111dd3c5c7ca36" - integrity sha1-jaDmqHbPNEwK2KVIghEd08XHyjY= - -lodash._basecreate@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz#1bc661614daa7fc311b7d03bf16806a0213cf821" - integrity sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE= - -lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - -lodash._isiterateecall@^3.0.0: - version "3.0.9" - resolved "https://registry.yarnpkg.com/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz#5203ad7ba425fae842460e696db9cf3e6aac057c" - integrity sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw= - lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -3605,44 +3570,16 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8= -lodash.create@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lodash.create/-/lodash.create-3.1.1.tgz#d7f2849f0dbda7e04682bb8cd72ab022461debe7" - integrity sha1-1/KEnw29p+BGgruM1yqwIkYd6+c= - dependencies: - lodash._baseassign "^3.0.0" - lodash._basecreate "^3.0.0" - lodash._isiterateecall "^3.0.0" - lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= -lodash.isarguments@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz#2f573d85c6a24289ff00663b491c1d338ff3458a" - integrity sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo= - -lodash.isarray@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-3.0.4.tgz#79e4eb88c36a8122af86f844aa9bcd851b5fbb55" - integrity sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U= - lodash.ismatch@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz#756cb5150ca3ba6f11085a78849645f188f85f37" integrity sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc= -lodash.keys@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-3.1.2.tgz#4dbc0472b156be50a0b286855d1bd0b0c656098a" - integrity sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo= - dependencies: - lodash._getnative "^3.0.0" - lodash.isarguments "^3.0.0" - lodash.isarray "^3.0.0" - lodash.set@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" @@ -3683,12 +3620,12 @@ log-driver@^1.2.7: resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== -log-symbols@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== +log-symbols@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-3.0.0.tgz#f3a08516a5dea893336a7dee14d18a1cfdab77c4" + integrity sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ== dependencies: - chalk "^2.0.1" + chalk "^2.4.2" loud-rejection@^1.0.0: version "1.6.0" @@ -3866,7 +3803,7 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.2, minimatch@^3.0.4: +"minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== @@ -3947,62 +3884,28 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@0.5.1, mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@*, mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" -mkdirp@0.5.x: +mkdirp@0.5.5, mkdirp@0.5.x: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== dependencies: minimist "^1.2.5" -mocha@^3.5.0: - version "3.5.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-3.5.3.tgz#1e0480fe36d2da5858d1eb6acc38418b26eaa20d" - integrity sha512-/6na001MJWEtYxHOV1WLfsmR4YIynkUEhBwzsb+fk2qmQ3iqsi258l/Q2MWHJMImAcNpZ8DEdYAK72NHoIQ9Eg== - dependencies: - browser-stdout "1.3.0" - commander "2.9.0" - debug "2.6.8" - diff "3.2.0" - escape-string-regexp "1.0.5" - glob "7.1.1" - growl "1.9.2" - he "1.1.1" - json3 "3.3.2" - lodash.create "3.1.1" - mkdirp "0.5.1" - supports-color "3.1.2" - -mocha@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-5.2.0.tgz#6d8ae508f59167f940f2b5b3c4a612ae50c90ae6" - integrity sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ== - dependencies: - browser-stdout "1.3.1" - commander "2.15.1" - debug "3.1.0" - diff "3.5.0" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.5" - he "1.1.1" - minimatch "3.0.4" - mkdirp "0.5.1" - supports-color "5.4.0" - -mocha@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.2.tgz#5d8987e28940caf8957a7d7664b910dc5b2fea20" - integrity sha512-FgDS9Re79yU1xz5d+C4rv1G7QagNGHZ+iXF81hO8zY35YZZcLEsJVfFolfsqKFWunATEvNzMK0r/CwWd/szO9A== +mocha@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.1.2.tgz#8e40d198acf91a52ace122cd7599c9ab857b29e6" + integrity sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA== dependencies: ansi-colors "3.2.3" browser-stdout "1.3.1" + chokidar "3.3.0" debug "3.2.6" diff "3.5.0" escape-string-regexp "1.0.5" @@ -4011,18 +3914,18 @@ mocha@^6.2.2: growl "1.10.5" he "1.2.0" js-yaml "3.13.1" - log-symbols "2.2.0" + log-symbols "3.0.0" minimatch "3.0.4" - mkdirp "0.5.1" + mkdirp "0.5.5" ms "2.1.1" - node-environment-flags "1.0.5" + node-environment-flags "1.0.6" object.assign "4.1.0" strip-json-comments "2.0.1" supports-color "6.0.0" which "1.3.1" wide-align "1.1.3" - yargs "13.3.0" - yargs-parser "13.1.1" + yargs "13.3.2" + yargs-parser "13.1.2" yargs-unparser "1.6.0" modify-values@^1.0.0: @@ -4118,10 +4021,10 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== -node-environment-flags@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" - integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== +node-environment-flags@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" + integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== dependencies: object.getownpropertydescriptors "^2.0.3" semver "^5.7.0" @@ -4182,6 +4085,11 @@ normalize-package-data@^2.0.0, normalize-package-data@^2.3.0, normalize-package- semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + normalize-url@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" @@ -4629,6 +4537,11 @@ pgpass@1.x: dependencies: split "^1.0.0" +picomatch@^2.0.4: + version "2.2.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -4915,6 +4828,13 @@ readdir-scoped-modules@^1.0.0: graceful-fs "^4.1.2" once "^1.3.0" +readdirp@~3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.2.0.tgz#c30c33352b12c96dfb4b895421a49fd5a9593839" + integrity sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ== + dependencies: + picomatch "^2.0.4" + redent@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-1.0.0.tgz#cf916ab1fd5f1f16dfb20822dd6ec7f730c2afde" @@ -5576,20 +5496,6 @@ strong-log-transformer@^2.0.0: minimist "^1.2.0" through "^2.3.4" -supports-color@3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" - integrity sha1-cqJiiU2dQIuVbKBf83su2KbiotU= - dependencies: - has-flag "^1.0.0" - -supports-color@5.4.0: - version "5.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.4.0.tgz#1c6b337402c2137605efe19f10fec390f6faab54" - integrity sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w== - dependencies: - has-flag "^3.0.0" - supports-color@6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" @@ -5722,6 +5628,13 @@ to-regex-range@^2.1.0: is-number "^3.0.0" repeat-string "^1.6.1" +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" @@ -6125,10 +6038,10 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yargs-parser@13.1.1, yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== +yargs-parser@13.1.2, yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -6140,6 +6053,14 @@ yargs-parser@^10.0.0: dependencies: camelcase "^4.1.0" +yargs-parser@^13.1.1: + version "13.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" + integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^15.0.0: version "15.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.0.tgz#cdd7a97490ec836195f59f3f4dbe5ea9e8f75f08" @@ -6157,7 +6078,23 @@ yargs-unparser@1.6.0: lodash "^4.17.15" yargs "^13.3.0" -yargs@13.3.0, yargs@^13.3.0: +yargs@13.3.2: + version "13.3.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" + +yargs@^13.3.0: version "13.3.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== From bf40f0378872481d238af4893ea5385ee59e6eea Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Wed, 22 Apr 2020 15:55:03 -0700 Subject: [PATCH 0656/1037] Send the `client_encoding` startup parameter value with more typical formatting All non-alphanumerics are ignored, but `'utf-8'` is weird. `UTF8` is the canonical name, and is what libpq sends. --- packages/pg-protocol/src/serializer.ts | 2 +- packages/pg/lib/connection.js | 2 +- packages/pg/test/unit/connection/outbound-sending-tests.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/pg-protocol/src/serializer.ts b/packages/pg-protocol/src/serializer.ts index 00e43fffe..bff2fd332 100644 --- a/packages/pg-protocol/src/serializer.ts +++ b/packages/pg-protocol/src/serializer.ts @@ -25,7 +25,7 @@ const startup = (opts: Record): Buffer => { writer.addCString(key).addCString(opts[key]) } - writer.addCString('client_encoding').addCString("'utf-8'") + writer.addCString('client_encoding').addCString('UTF8') var bodyBuffer = writer.addCString('').flush() // this message is sent without a code diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index c3f30aa0f..761250137 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -144,7 +144,7 @@ Connection.prototype.startup = function (config) { writer.addCString(key).addCString(val) }) - writer.addCString('client_encoding').addCString("'utf-8'") + writer.addCString('client_encoding').addCString('UTF8') var bodyBuffer = writer.addCString('').flush() // this message is sent without a code diff --git a/packages/pg/test/unit/connection/outbound-sending-tests.js b/packages/pg/test/unit/connection/outbound-sending-tests.js index 8b21de4ce..d6b03964f 100644 --- a/packages/pg/test/unit/connection/outbound-sending-tests.js +++ b/packages/pg/test/unit/connection/outbound-sending-tests.js @@ -28,7 +28,7 @@ test('sends startup message', function () { .addCString('database') .addCString('bang') .addCString('client_encoding') - .addCString("'utf-8'") + .addCString('UTF8') .addCString('') .join(true) ) From 06cdf3e9f0a32b84a61e5c8268bce20098a7d1f2 Mon Sep 17 00:00:00 2001 From: Rafi Shamim Date: Wed, 13 May 2020 14:44:47 -0400 Subject: [PATCH 0657/1037] Support options connection parameter This supports the connection parameter documented here: https://www.postgresql.org/docs/9.1/libpq-connect.html#LIBPQ-CONNECT-OPTIONS --- packages/pg-connection-string/index.d.ts | 1 + packages/pg-connection-string/test/parse.js | 6 +++--- packages/pg/lib/client.js | 3 +++ packages/pg/lib/connection-parameters.js | 2 ++ packages/pg/lib/defaults.js | 2 ++ .../pg/test/unit/connection-parameters/creation-tests.js | 6 +++++- 6 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/pg-connection-string/index.d.ts b/packages/pg-connection-string/index.d.ts index b1b7abd9c..3081270e2 100644 --- a/packages/pg-connection-string/index.d.ts +++ b/packages/pg-connection-string/index.d.ts @@ -11,4 +11,5 @@ export interface ConnectionOptions { application_name?: string fallback_application_name?: string + options?: string } diff --git a/packages/pg-connection-string/test/parse.js b/packages/pg-connection-string/test/parse.js index 957f06441..035b025d1 100644 --- a/packages/pg-connection-string/test/parse.js +++ b/packages/pg-connection-string/test/parse.js @@ -188,10 +188,10 @@ describe('parse', function () { subject.fallback_application_name.should.equal('TheAppFallback') }) - it('configuration parameter fallback_application_name', function () { - var connectionString = 'pg:///?fallback_application_name=TheAppFallback' + it('configuration parameter options', function () { + var connectionString = 'pg:///?options=-c geqo=off' var subject = parse(connectionString) - subject.fallback_application_name.should.equal('TheAppFallback') + subject.options.should.equal('-c geqo=off') }) it('configuration parameter ssl=true', function () { diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 2c12f2cce..93dfc6c9c 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -391,6 +391,9 @@ Client.prototype.getStartupConf = function () { if (params.idle_in_transaction_session_timeout) { data.idle_in_transaction_session_timeout = String(parseInt(params.idle_in_transaction_session_timeout, 10)) } + if (params.options) { + data.options = params.options + } return data } diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index e1d838929..546682521 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -70,6 +70,7 @@ var ConnectionParameters = function (config) { }) this.binary = val('binary', config) + this.options = val('options', config) this.ssl = typeof config.ssl === 'undefined' ? readSSLConfigFromEnvironment() : config.ssl @@ -126,6 +127,7 @@ ConnectionParameters.prototype.getLibpqConnectionString = function (cb) { add(params, this, 'application_name') add(params, this, 'fallback_application_name') add(params, this, 'connect_timeout') + add(params, this, 'options') var ssl = typeof this.ssl === 'object' ? this.ssl : this.ssl ? { sslmode: this.ssl } : {} add(params, ssl, 'sslmode') diff --git a/packages/pg/lib/defaults.js b/packages/pg/lib/defaults.js index 394216680..e28794dba 100644 --- a/packages/pg/lib/defaults.js +++ b/packages/pg/lib/defaults.js @@ -53,6 +53,8 @@ module.exports = { fallback_application_name: undefined, + options: undefined, + parseInputDatesAsUTC: false, // max milliseconds any query using this connection will execute for before timing out in error. diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index 820b320a5..fb01b1118 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -25,6 +25,7 @@ var compare = function (actual, expected, type) { assert.equal(actual.password, expected.password, type + ' password') assert.equal(actual.binary, expected.binary, type + ' binary') assert.equal(actual.statement_timeout, expected.statement_timeout, type + ' statement_timeout') + assert.equal(actual.options, expected.options, type + ' options') assert.equal( actual.idle_in_transaction_session_timeout, expected.idle_in_transaction_session_timeout, @@ -48,12 +49,14 @@ test('ConnectionParameters initializing from defaults with connectionString set' binary: defaults.binary, statement_timeout: false, idle_in_transaction_session_timeout: false, + options: '-c geqo=off', } var original_value = defaults.connectionString // Just changing this here doesn't actually work because it's no longer in scope when viewed inside of // of ConnectionParameters() so we have to pass in the defaults explicitly to test it - defaults.connectionString = 'postgres://brians-are-the-best:mypassword@foo.bar.net:7777/scoobysnacks' + defaults.connectionString = + 'postgres://brians-are-the-best:mypassword@foo.bar.net:7777/scoobysnacks?options=-c geqo=off' var subject = new ConnectionParameters(defaults) defaults.connectionString = original_value compare(subject, config, 'defaults-connectionString') @@ -73,6 +76,7 @@ test('ConnectionParameters initializing from config', function () { }, statement_timeout: 15000, idle_in_transaction_session_timeout: 15000, + options: '-c geqo=off', } var subject = new ConnectionParameters(config) compare(subject, config, 'config') From a79c8e7992269a796a477c20d9c775b7685991c0 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 15 May 2020 17:51:09 -0500 Subject: [PATCH 0658/1037] Send sync after flush --- packages/pg/lib/connection.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 98b6b5a5f..65867026d 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -172,8 +172,8 @@ Connection.prototype.flush = function () { const syncBuffer = serialize.sync() Connection.prototype.sync = function () { this._ending = true - this._send(syncBuffer) this._send(flushBuffer) + this._send(syncBuffer) } const endBuffer = serialize.end() From f3136a7d5d5498280924b3e06f47f8ce80dbe4e6 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 15 May 2020 18:33:34 -0500 Subject: [PATCH 0659/1037] Publish - pg-connection-string@2.2.3 - pg-cursor@2.2.1 - pg-pool@3.2.1 - pg-protocol@1.2.4 - pg-query-stream@3.1.1 - pg@8.2.1 --- packages/pg-connection-string/package.json | 2 +- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 8 ++++---- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index a2081e5e2..2c2407250 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "2.2.2", + "version": "2.2.3", "description": "Functions for dealing with a PostgresSQL connection string", "main": "./index.js", "types": "./index.d.ts", diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index ac580c30f..92b227ec0 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.2.0", + "version": "2.2.1", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -17,6 +17,6 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.2.0" + "pg": "^8.2.1" } } diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 0c4c93a8f..3acac307e 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.2.0", + "version": "3.2.1", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 30cfe4095..6e32eb26c 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.2.3", + "version": "1.2.4", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 0d454b1b6..f36fe55f5 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.1.0", + "version": "3.1.1", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -26,12 +26,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.2.0", + "pg": "^8.2.1", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.2.0" + "pg-cursor": "^2.2.1" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 81ef42479..32ce3e181 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.2.0", + "version": "8.2.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -21,9 +21,9 @@ "dependencies": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-connection-string": "^2.2.2", - "pg-pool": "^3.2.0", - "pg-protocol": "^1.2.3", + "pg-connection-string": "^2.2.3", + "pg-pool": "^3.2.1", + "pg-protocol": "^1.2.4", "pg-types": "^2.1.0", "pgpass": "1.x", "semver": "4.3.2" From eeb62ba40da27941dad144635ee84b283950d411 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Tue, 12 May 2020 16:41:12 -0400 Subject: [PATCH 0660/1037] test: Replace __dirname concatenations in require(...) with relative paths Replaces __dirname concatentation in pg test scripts so that editors like VS Code can automatically generate typings and support code navigation (F12). --- packages/pg/test/cli.js | 2 +- packages/pg/test/integration/client/api-tests.js | 2 +- packages/pg/test/integration/client/appname-tests.js | 2 +- packages/pg/test/integration/client/array-tests.js | 2 +- .../pg/test/integration/client/query-as-promise-tests.js | 2 +- .../pg/test/integration/client/query-column-names-tests.js | 2 +- packages/pg/test/integration/client/ssl-tests.js | 4 ++-- packages/pg/test/integration/client/type-coercion-tests.js | 2 +- .../pg/test/integration/connection/bound-command-tests.js | 2 +- packages/pg/test/integration/connection/copy-tests.js | 2 +- .../pg/test/integration/connection/notification-tests.js | 2 +- packages/pg/test/integration/connection/query-tests.js | 2 +- packages/pg/test/integration/connection/test-helper.js | 6 +++--- packages/pg/test/integration/gh-issues/130-tests.js | 2 +- packages/pg/test/integration/gh-issues/507-tests.js | 2 +- packages/pg/test/native/stress-tests.js | 4 ++-- packages/pg/test/test-buffers.js | 2 +- packages/pg/test/unit/client/configuration-tests.js | 2 +- packages/pg/test/unit/client/escape-tests.js | 2 +- packages/pg/test/unit/client/notification-tests.js | 2 +- packages/pg/test/unit/client/query-queue-tests.js | 4 ++-- packages/pg/test/unit/client/result-metadata-tests.js | 2 +- packages/pg/test/unit/client/simple-query-tests.js | 2 +- .../unit/client/stream-and-query-error-interaction-tests.js | 6 +++--- .../pg/test/unit/connection-parameters/creation-tests.js | 6 +++--- .../connection-parameters/environment-variable-tests.js | 6 +++--- packages/pg/test/unit/connection/error-tests.js | 4 ++-- packages/pg/test/unit/connection/inbound-parser-tests.js | 6 +++--- packages/pg/test/unit/connection/startup-tests.js | 4 ++-- packages/pg/test/unit/connection/test-helper.js | 2 +- 30 files changed, 45 insertions(+), 45 deletions(-) diff --git a/packages/pg/test/cli.js b/packages/pg/test/cli.js index 2b40976c6..03699b9ba 100644 --- a/packages/pg/test/cli.js +++ b/packages/pg/test/cli.js @@ -1,5 +1,5 @@ 'use strict' -var ConnectionParameters = require(__dirname + '/../lib/connection-parameters') +var ConnectionParameters = require('../lib/connection-parameters') var config = new ConnectionParameters(process.argv[2]) for (var i = 0; i < process.argv.length; i++) { diff --git a/packages/pg/test/integration/client/api-tests.js b/packages/pg/test/integration/client/api-tests.js index a957c32ae..abaab69fb 100644 --- a/packages/pg/test/integration/client/api-tests.js +++ b/packages/pg/test/integration/client/api-tests.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/../test-helper') +var helper = require('../test-helper') var pg = helper.pg var suite = new helper.Suite() diff --git a/packages/pg/test/integration/client/appname-tests.js b/packages/pg/test/integration/client/appname-tests.js index dd8de6b39..ab7202a9b 100644 --- a/packages/pg/test/integration/client/appname-tests.js +++ b/packages/pg/test/integration/client/appname-tests.js @@ -71,7 +71,7 @@ suite.test('application_name has precedence over fallback_application_name', fun suite.test('application_name from connection string', function (done) { var appName = 'my app' - var conParams = require(__dirname + '/../../../lib/connection-parameters') + var conParams = require('../../../lib/connection-parameters') var conf if (process.argv[2]) { conf = new conParams(process.argv[2] + '?application_name=' + appName) diff --git a/packages/pg/test/integration/client/array-tests.js b/packages/pg/test/integration/client/array-tests.js index f5e62b032..a32139646 100644 --- a/packages/pg/test/integration/client/array-tests.js +++ b/packages/pg/test/integration/client/array-tests.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') var pg = helper.pg var suite = new helper.Suite() diff --git a/packages/pg/test/integration/client/query-as-promise-tests.js b/packages/pg/test/integration/client/query-as-promise-tests.js index 46365c6c0..30c106f0b 100644 --- a/packages/pg/test/integration/client/query-as-promise-tests.js +++ b/packages/pg/test/integration/client/query-as-promise-tests.js @@ -1,6 +1,6 @@ 'use strict' var bluebird = require('bluebird') -var helper = require(__dirname + '/../test-helper') +var helper = require('../test-helper') var pg = helper.pg process.on('unhandledRejection', function (e) { diff --git a/packages/pg/test/integration/client/query-column-names-tests.js b/packages/pg/test/integration/client/query-column-names-tests.js index 6b32881e5..a109209b1 100644 --- a/packages/pg/test/integration/client/query-column-names-tests.js +++ b/packages/pg/test/integration/client/query-column-names-tests.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/../test-helper') +var helper = require('../test-helper') var pg = helper.pg new helper.Suite().test('support for complex column names', function () { diff --git a/packages/pg/test/integration/client/ssl-tests.js b/packages/pg/test/integration/client/ssl-tests.js index 1d3c5015b..97aa59492 100644 --- a/packages/pg/test/integration/client/ssl-tests.js +++ b/packages/pg/test/integration/client/ssl-tests.js @@ -1,6 +1,6 @@ 'use strict' -var pg = require(__dirname + '/../../../lib') -var config = require(__dirname + '/test-helper').config +var pg = require('../../../lib') +var config = require('./test-helper').config test('can connect with ssl', function () { return false config.ssl = { diff --git a/packages/pg/test/integration/client/type-coercion-tests.js b/packages/pg/test/integration/client/type-coercion-tests.js index 96f57b08c..33249a9b2 100644 --- a/packages/pg/test/integration/client/type-coercion-tests.js +++ b/packages/pg/test/integration/client/type-coercion-tests.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') var pg = helper.pg var sink const suite = new helper.Suite() diff --git a/packages/pg/test/integration/connection/bound-command-tests.js b/packages/pg/test/integration/connection/bound-command-tests.js index a707bc4b1..15f4f791e 100644 --- a/packages/pg/test/integration/connection/bound-command-tests.js +++ b/packages/pg/test/integration/connection/bound-command-tests.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY test('flushing once', function () { diff --git a/packages/pg/test/integration/connection/copy-tests.js b/packages/pg/test/integration/connection/copy-tests.js index 1b7d06ed1..177009d00 100644 --- a/packages/pg/test/integration/connection/copy-tests.js +++ b/packages/pg/test/integration/connection/copy-tests.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') var assert = require('assert') test('COPY FROM events check', function () { diff --git a/packages/pg/test/integration/connection/notification-tests.js b/packages/pg/test/integration/connection/notification-tests.js index 347b7ee89..534106d4b 100644 --- a/packages/pg/test/integration/connection/notification-tests.js +++ b/packages/pg/test/integration/connection/notification-tests.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') // http://www.postgresql.org/docs/8.3/static/libpq-notify.html test('recieves notification from same connection with no payload', function () { helper.connect(function (con) { diff --git a/packages/pg/test/integration/connection/query-tests.js b/packages/pg/test/integration/connection/query-tests.js index 70c39c322..4105bb719 100644 --- a/packages/pg/test/integration/connection/query-tests.js +++ b/packages/pg/test/integration/connection/query-tests.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') var assert = require('assert') var rows = [] diff --git a/packages/pg/test/integration/connection/test-helper.js b/packages/pg/test/integration/connection/test-helper.js index ca978af4f..a94c64be5 100644 --- a/packages/pg/test/integration/connection/test-helper.js +++ b/packages/pg/test/integration/connection/test-helper.js @@ -1,8 +1,8 @@ 'use strict' var net = require('net') -var helper = require(__dirname + '/../test-helper') -var Connection = require(__dirname + '/../../../lib/connection') -var utils = require(__dirname + '/../../../lib/utils') +var helper = require('../test-helper') +var Connection = require('../../../lib/connection') +var utils = require('../../../lib/utils') var connect = function (callback) { var username = helper.args.user var database = helper.args.database diff --git a/packages/pg/test/integration/gh-issues/130-tests.js b/packages/pg/test/integration/gh-issues/130-tests.js index 8b097b99b..fb86b5ba3 100644 --- a/packages/pg/test/integration/gh-issues/130-tests.js +++ b/packages/pg/test/integration/gh-issues/130-tests.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/../test-helper') +var helper = require('../test-helper') var exec = require('child_process').exec helper.pg.defaults.poolIdleTimeout = 1000 diff --git a/packages/pg/test/integration/gh-issues/507-tests.js b/packages/pg/test/integration/gh-issues/507-tests.js index 9c3409199..f77d1f842 100644 --- a/packages/pg/test/integration/gh-issues/507-tests.js +++ b/packages/pg/test/integration/gh-issues/507-tests.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/../test-helper') +var helper = require('../test-helper') var pg = helper.pg new helper.Suite().test('parsing array results', function (cb) { diff --git a/packages/pg/test/native/stress-tests.js b/packages/pg/test/native/stress-tests.js index 49904b12a..9d1287750 100644 --- a/packages/pg/test/native/stress-tests.js +++ b/packages/pg/test/native/stress-tests.js @@ -1,6 +1,6 @@ 'use strict' -var helper = require(__dirname + '/../test-helper') -var Client = require(__dirname + '/../../lib/native') +var helper = require('../test-helper') +var Client = require('../../lib/native') var Query = Client.Query test('many rows', function () { diff --git a/packages/pg/test/test-buffers.js b/packages/pg/test/test-buffers.js index 9fdd889d4..64fefb6c4 100644 --- a/packages/pg/test/test-buffers.js +++ b/packages/pg/test/test-buffers.js @@ -1,5 +1,5 @@ 'use strict' -require(__dirname + '/test-helper') +require('./test-helper') // http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html var buffers = {} diff --git a/packages/pg/test/unit/client/configuration-tests.js b/packages/pg/test/unit/client/configuration-tests.js index e604513bf..19a1da800 100644 --- a/packages/pg/test/unit/client/configuration-tests.js +++ b/packages/pg/test/unit/client/configuration-tests.js @@ -1,5 +1,5 @@ 'use strict' -require(__dirname + '/test-helper') +require('./test-helper') var assert = require('assert') var pguser = process.env['PGUSER'] || process.env.USER diff --git a/packages/pg/test/unit/client/escape-tests.js b/packages/pg/test/unit/client/escape-tests.js index 7f96a832d..721b04b49 100644 --- a/packages/pg/test/unit/client/escape-tests.js +++ b/packages/pg/test/unit/client/escape-tests.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') function createClient(callback) { var client = new Client(helper.config) diff --git a/packages/pg/test/unit/client/notification-tests.js b/packages/pg/test/unit/client/notification-tests.js index 5ca9df226..7143acaba 100644 --- a/packages/pg/test/unit/client/notification-tests.js +++ b/packages/pg/test/unit/client/notification-tests.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') test('passes connection notification', function () { var client = helper.client() diff --git a/packages/pg/test/unit/client/query-queue-tests.js b/packages/pg/test/unit/client/query-queue-tests.js index 9364ce822..0b5eaa564 100644 --- a/packages/pg/test/unit/client/query-queue-tests.js +++ b/packages/pg/test/unit/client/query-queue-tests.js @@ -1,6 +1,6 @@ 'use strict' -var helper = require(__dirname + '/test-helper') -var Connection = require(__dirname + '/../../../lib/connection') +var helper = require('./test-helper') +var Connection = require('../../../lib/connection') test('drain', function () { var con = new Connection({ stream: 'NO' }) diff --git a/packages/pg/test/unit/client/result-metadata-tests.js b/packages/pg/test/unit/client/result-metadata-tests.js index f3e005949..a5e6542c8 100644 --- a/packages/pg/test/unit/client/result-metadata-tests.js +++ b/packages/pg/test/unit/client/result-metadata-tests.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') var testForTag = function (tagText, callback) { test('includes command tag data for tag ' + tagText, function () { diff --git a/packages/pg/test/unit/client/simple-query-tests.js b/packages/pg/test/unit/client/simple-query-tests.js index b0d5b8674..2c3ea5e4e 100644 --- a/packages/pg/test/unit/client/simple-query-tests.js +++ b/packages/pg/test/unit/client/simple-query-tests.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/test-helper') +var helper = require('./test-helper') var Query = require('../../../lib/query') test('executing query', function () { diff --git a/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js index 3f84ae4a5..892d2e87a 100644 --- a/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js +++ b/packages/pg/test/unit/client/stream-and-query-error-interaction-tests.js @@ -1,7 +1,7 @@ 'use strict' -var helper = require(__dirname + '/test-helper') -var Connection = require(__dirname + '/../../../lib/connection') -var Client = require(__dirname + '/../../../lib/client') +var helper = require('./test-helper') +var Connection = require('../../../lib/connection') +var Client = require('../../../lib/client') test('emits end when not in query', function () { var stream = new (require('events').EventEmitter)() diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index 820b320a5..5e7625736 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -1,8 +1,8 @@ 'use strict' -var helper = require(__dirname + '/../test-helper') +var helper = require('../test-helper') var assert = require('assert') -var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters') -var defaults = require(__dirname + '/../../../lib').defaults +var ConnectionParameters = require('../../../lib/connection-parameters') +var defaults = require('../../../lib').defaults // clear process.env for (var key in process.env) { diff --git a/packages/pg/test/unit/connection-parameters/environment-variable-tests.js b/packages/pg/test/unit/connection-parameters/environment-variable-tests.js index c64edee87..b20a7934b 100644 --- a/packages/pg/test/unit/connection-parameters/environment-variable-tests.js +++ b/packages/pg/test/unit/connection-parameters/environment-variable-tests.js @@ -1,10 +1,10 @@ 'use strict' -var helper = require(__dirname + '/../test-helper') +var helper = require('../test-helper') const Suite = require('../../suite') var assert = require('assert') -var ConnectionParameters = require(__dirname + '/../../../lib/connection-parameters') -var defaults = require(__dirname + '/../../../lib').defaults +var ConnectionParameters = require('../../../lib/connection-parameters') +var defaults = require('../../../lib').defaults // clear process.env var realEnv = {} diff --git a/packages/pg/test/unit/connection/error-tests.js b/packages/pg/test/unit/connection/error-tests.js index 5075c770d..b9ccd8197 100644 --- a/packages/pg/test/unit/connection/error-tests.js +++ b/packages/pg/test/unit/connection/error-tests.js @@ -1,6 +1,6 @@ 'use strict' -var helper = require(__dirname + '/test-helper') -var Connection = require(__dirname + '/../../../lib/connection') +var helper = require('./test-helper') +var Connection = require('../../../lib/connection') var net = require('net') const suite = new helper.Suite() diff --git a/packages/pg/test/unit/connection/inbound-parser-tests.js b/packages/pg/test/unit/connection/inbound-parser-tests.js index f3690cc63..0e3c34cfa 100644 --- a/packages/pg/test/unit/connection/inbound-parser-tests.js +++ b/packages/pg/test/unit/connection/inbound-parser-tests.js @@ -1,7 +1,7 @@ 'use strict' -require(__dirname + '/test-helper') -var Connection = require(__dirname + '/../../../lib/connection') -var buffers = require(__dirname + '/../../test-buffers') +require('./test-helper') +var Connection = require('../../../lib/connection') +var buffers = require('../../test-buffers') var PARSE = function (buffer) { return new Parser(buffer).parse() } diff --git a/packages/pg/test/unit/connection/startup-tests.js b/packages/pg/test/unit/connection/startup-tests.js index 6e317d70f..e2eb6ee99 100644 --- a/packages/pg/test/unit/connection/startup-tests.js +++ b/packages/pg/test/unit/connection/startup-tests.js @@ -1,6 +1,6 @@ 'use strict' -require(__dirname + '/test-helper') -var Connection = require(__dirname + '/../../../lib/connection') +require('./test-helper') +var Connection = require('../../../lib/connection') test('connection can take existing stream', function () { var stream = new MemoryStream() var con = new Connection({ stream: stream }) diff --git a/packages/pg/test/unit/connection/test-helper.js b/packages/pg/test/unit/connection/test-helper.js index 53c4b0c9b..0cc83dca2 100644 --- a/packages/pg/test/unit/connection/test-helper.js +++ b/packages/pg/test/unit/connection/test-helper.js @@ -1,2 +1,2 @@ 'use strict' -module.exports = require(__dirname + '/../test-helper') +module.exports = require('../test-helper') From bd28c0f15cff48956378cc577a87bba3c4a7ee8a Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Sat, 16 May 2020 07:42:25 -0400 Subject: [PATCH 0661/1037] test: Remove unused getMode() function --- packages/pg/test/test-helper.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/pg/test/test-helper.js b/packages/pg/test/test-helper.js index 8159e387c..2d93756e6 100644 --- a/packages/pg/test/test-helper.js +++ b/packages/pg/test/test-helper.js @@ -171,12 +171,6 @@ assert.isNull = function (item, message) { assert.ok(item === null, message) } -const getMode = () => { - if (args.native) return 'native' - if (args.binary) return 'binary' - return '' -} - global.test = function (name, action) { test.testCount++ test[name] = action From 87559bdbfa9beca18e73bb589acffc502180b889 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Sat, 16 May 2020 07:43:57 -0400 Subject: [PATCH 0662/1037] test: Remove unused count variable Removes unused count var. Sink function below it shadows the variable within its add(...) function so file level count variable is never used. --- packages/pg/test/test-helper.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/pg/test/test-helper.js b/packages/pg/test/test-helper.js index 2d93756e6..ee3625003 100644 --- a/packages/pg/test/test-helper.js +++ b/packages/pg/test/test-helper.js @@ -197,8 +197,6 @@ process.on('uncaughtException', function (err) { process.exit(255) }) -var count = 0 - var Sink = function (expected, timeout, callback) { var defaultTimeout = 5000 if (typeof timeout === 'function') { From 02c4fc5b95d6bfd497975ae280798c923daace2a Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Sat, 16 May 2020 07:45:55 -0400 Subject: [PATCH 0663/1037] test: Remove unused imports in test-helpers --- packages/pg/test/test-helper.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/pg/test/test-helper.js b/packages/pg/test/test-helper.js index ee3625003..8156b39f1 100644 --- a/packages/pg/test/test-helper.js +++ b/packages/pg/test/test-helper.js @@ -1,15 +1,12 @@ 'use strict' // make assert a global... global.assert = require('assert') -var EventEmitter = require('events').EventEmitter var sys = require('util') var BufferList = require('./buffer-list') const Suite = require('./suite') const args = require('./cli') -var Connection = require('./../lib/connection') - global.Client = require('./../lib').Client process.on('uncaughtException', function (d) { From 96e2f20a1d8da9871fbd085dd97fd3fab705bf2d Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Sat, 16 May 2020 07:58:57 -0400 Subject: [PATCH 0664/1037] test: Replace global BufferList with local require Removes assigning BufferList to a global in top level test-helper and adds explicit require in the tests that need to access it. --- packages/pg/test/buffer-list.js | 3 ++- packages/pg/test/test-buffers.js | 1 + packages/pg/test/test-helper.js | 1 - packages/pg/test/unit/client/md5-password-tests.js | 1 + packages/pg/test/unit/connection/inbound-parser-tests.js | 1 + 5 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/pg/test/buffer-list.js b/packages/pg/test/buffer-list.js index aea529c10..ec48b6ad6 100644 --- a/packages/pg/test/buffer-list.js +++ b/packages/pg/test/buffer-list.js @@ -1,5 +1,6 @@ 'use strict' -global.BufferList = function () { + +const BufferList = function () { this.buffers = [] } var p = BufferList.prototype diff --git a/packages/pg/test/test-buffers.js b/packages/pg/test/test-buffers.js index 64fefb6c4..2989434d4 100644 --- a/packages/pg/test/test-buffers.js +++ b/packages/pg/test/test-buffers.js @@ -1,5 +1,6 @@ 'use strict' require('./test-helper') +const BufferList = require('./buffer-list') // http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html var buffers = {} diff --git a/packages/pg/test/test-helper.js b/packages/pg/test/test-helper.js index 8156b39f1..4ca9da1b3 100644 --- a/packages/pg/test/test-helper.js +++ b/packages/pg/test/test-helper.js @@ -3,7 +3,6 @@ global.assert = require('assert') var sys = require('util') -var BufferList = require('./buffer-list') const Suite = require('./suite') const args = require('./cli') diff --git a/packages/pg/test/unit/client/md5-password-tests.js b/packages/pg/test/unit/client/md5-password-tests.js index a55e955bc..71f502087 100644 --- a/packages/pg/test/unit/client/md5-password-tests.js +++ b/packages/pg/test/unit/client/md5-password-tests.js @@ -1,5 +1,6 @@ 'use strict' var helper = require('./test-helper') +const BufferList = require('../../buffer-list') var utils = require('../../../lib/utils') test('md5 authentication', function () { diff --git a/packages/pg/test/unit/connection/inbound-parser-tests.js b/packages/pg/test/unit/connection/inbound-parser-tests.js index 0e3c34cfa..af9385c40 100644 --- a/packages/pg/test/unit/connection/inbound-parser-tests.js +++ b/packages/pg/test/unit/connection/inbound-parser-tests.js @@ -1,5 +1,6 @@ 'use strict' require('./test-helper') +const BufferList = require('../../buffer-list') var Connection = require('../../../lib/connection') var buffers = require('../../test-buffers') var PARSE = function (buffer) { From ea6ac2ad2313af57159b10a0292c0c178e8e0923 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Mon, 18 May 2020 18:30:21 -0700 Subject: [PATCH 0665/1037] Remove the last `__dirname`s in `require`s Follow-up to eeb62ba40da27941dad144635ee84b283950d411. --- packages/pg/script/create-test-tables.js | 4 ++-- packages/pg/script/dump-db-types.js | 4 ++-- packages/pg/script/list-db-types.js | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/pg/script/create-test-tables.js b/packages/pg/script/create-test-tables.js index 6db5fea7c..c7b2ff9e0 100644 --- a/packages/pg/script/create-test-tables.js +++ b/packages/pg/script/create-test-tables.js @@ -1,6 +1,6 @@ 'use strict' -var args = require(__dirname + '/../test/cli') -var pg = require(__dirname + '/../lib') +var args = require('../test/cli') +var pg = require('../lib') var people = [ { name: 'Aaron', age: 10 }, diff --git a/packages/pg/script/dump-db-types.js b/packages/pg/script/dump-db-types.js index 08fe4dc98..f76249483 100644 --- a/packages/pg/script/dump-db-types.js +++ b/packages/pg/script/dump-db-types.js @@ -1,6 +1,6 @@ 'use strict' -var pg = require(__dirname + '/../lib') -var args = require(__dirname + '/../test/cli') +var pg = require('../lib') +var args = require('../test/cli') var queries = ['select CURRENT_TIMESTAMP', "select interval '1 day' + interval '1 hour'", "select TIMESTAMP 'today'"] diff --git a/packages/pg/script/list-db-types.js b/packages/pg/script/list-db-types.js index c3e75c1ae..df179afaf 100644 --- a/packages/pg/script/list-db-types.js +++ b/packages/pg/script/list-db-types.js @@ -1,5 +1,5 @@ 'use strict' -var helper = require(__dirname + '/../test/integration/test-helper') +var helper = require('../test/integration/test-helper') var pg = helper.pg pg.connect( helper.config, From 0455504e22639e9c475447034b93f5161c1327b4 Mon Sep 17 00:00:00 2001 From: regevbr Date: Thu, 18 Jun 2020 14:49:50 +0300 Subject: [PATCH 0666/1037] fix: major performance issues with bytea performance #2240 --- packages/pg-protocol/src/parser.ts | 44 ++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 4044dae1c..61f765fa8 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -75,6 +75,8 @@ export type MessageCallback = (msg: BackendMessage) => void export class Parser { private remainingBuffer: Buffer = emptyBuffer + private remainingBufferLength: number = 0 + private remainingBufferOffset: number = 0 private reader = new BufferReader() private mode: Mode @@ -87,13 +89,33 @@ export class Parser { public parse(buffer: Buffer, callback: MessageCallback) { let combinedBuffer = buffer - if (this.remainingBuffer.byteLength) { - combinedBuffer = Buffer.allocUnsafe(this.remainingBuffer.byteLength + buffer.byteLength) - this.remainingBuffer.copy(combinedBuffer) - buffer.copy(combinedBuffer, this.remainingBuffer.byteLength) + let combinedBufferOffset = 0 + let combinedBufferLength = buffer.byteLength + const newRealLength = this.remainingBufferLength + combinedBufferLength + if (this.remainingBufferLength) { + const newLength = newRealLength + this.remainingBufferOffset + if (newLength > this.remainingBuffer.byteLength) { + let newBufferLength = this.remainingBufferLength * 2 + while (newRealLength >= newBufferLength) { + newBufferLength *= 2 + } + const newBuffer = Buffer.allocUnsafe(newBufferLength) + this.remainingBuffer.copy( + newBuffer, + 0, + this.remainingBufferOffset, + this.remainingBufferOffset + this.remainingBufferLength + ) + this.remainingBuffer = newBuffer + this.remainingBufferOffset = 0 + } + buffer.copy(this.remainingBuffer, this.remainingBufferOffset + this.remainingBufferLength) + combinedBuffer = this.remainingBuffer + combinedBufferLength = newRealLength + combinedBufferOffset = this.remainingBufferOffset } - let offset = 0 - while (offset + HEADER_LENGTH <= combinedBuffer.byteLength) { + let offset = combinedBufferOffset + while (offset + HEADER_LENGTH <= combinedBufferLength) { // code is 1 byte long - it identifies the message type const code = combinedBuffer[offset] @@ -102,7 +124,7 @@ export class Parser { const fullMessageLength = CODE_LENGTH + length - if (fullMessageLength + offset <= combinedBuffer.byteLength) { + if (fullMessageLength + offset <= combinedBufferLength) { const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer) callback(message) offset += fullMessageLength @@ -111,10 +133,14 @@ export class Parser { } } - if (offset === combinedBuffer.byteLength) { + if (offset === combinedBufferLength) { this.remainingBuffer = emptyBuffer + this.remainingBufferLength = 0 + this.remainingBufferOffset = 0 } else { - this.remainingBuffer = combinedBuffer.slice(offset) + this.remainingBuffer = combinedBuffer + this.remainingBufferLength = combinedBufferLength - offset + this.remainingBufferOffset += offset } } From c31205f4373f9820697f06d8f8875e31c7c0877f Mon Sep 17 00:00:00 2001 From: regevbr Date: Fri, 19 Jun 2020 02:32:00 +0300 Subject: [PATCH 0667/1037] fix: major performance issues with bytea performance #2240 --- packages/pg-protocol/src/parser.ts | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 61f765fa8..657514dde 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -91,11 +91,12 @@ export class Parser { let combinedBuffer = buffer let combinedBufferOffset = 0 let combinedBufferLength = buffer.byteLength - const newRealLength = this.remainingBufferLength + combinedBufferLength - if (this.remainingBufferLength) { + let remainingBufferNotEmpty = this.remainingBufferLength > 0 + if (remainingBufferNotEmpty) { + const newRealLength = this.remainingBufferLength + combinedBufferLength const newLength = newRealLength + this.remainingBufferOffset if (newLength > this.remainingBuffer.byteLength) { - let newBufferLength = this.remainingBufferLength * 2 + let newBufferLength = this.remainingBuffer.byteLength * 2 while (newRealLength >= newBufferLength) { newBufferLength *= 2 } @@ -111,11 +112,12 @@ export class Parser { } buffer.copy(this.remainingBuffer, this.remainingBufferOffset + this.remainingBufferLength) combinedBuffer = this.remainingBuffer - combinedBufferLength = newRealLength + combinedBufferLength = this.remainingBufferLength = newRealLength combinedBufferOffset = this.remainingBufferOffset } + const realLength = combinedBufferOffset + combinedBufferLength let offset = combinedBufferOffset - while (offset + HEADER_LENGTH <= combinedBufferLength) { + while (offset + HEADER_LENGTH <= realLength) { // code is 1 byte long - it identifies the message type const code = combinedBuffer[offset] @@ -124,7 +126,7 @@ export class Parser { const fullMessageLength = CODE_LENGTH + length - if (fullMessageLength + offset <= combinedBufferLength) { + if (fullMessageLength + offset <= realLength) { const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer) callback(message) offset += fullMessageLength @@ -133,12 +135,12 @@ export class Parser { } } - if (offset === combinedBufferLength) { + if (offset === realLength) { this.remainingBuffer = emptyBuffer this.remainingBufferLength = 0 this.remainingBufferOffset = 0 } else { - this.remainingBuffer = combinedBuffer + this.remainingBuffer = remainingBufferNotEmpty ? combinedBuffer : combinedBuffer.slice() this.remainingBufferLength = combinedBufferLength - offset this.remainingBufferOffset += offset } From 13ff0e11ed0c93eebe40a55296660247866e7b94 Mon Sep 17 00:00:00 2001 From: regevbr Date: Fri, 19 Jun 2020 02:53:17 +0300 Subject: [PATCH 0668/1037] fix: major performance issues with bytea performance #2240 --- packages/pg-protocol/src/parser.ts | 35 +++++++++++++++++------------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 657514dde..63303ac83 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -89,15 +89,15 @@ export class Parser { public parse(buffer: Buffer, callback: MessageCallback) { let combinedBuffer = buffer - let combinedBufferOffset = 0 let combinedBufferLength = buffer.byteLength - let remainingBufferNotEmpty = this.remainingBufferLength > 0 - if (remainingBufferNotEmpty) { - const newRealLength = this.remainingBufferLength + combinedBufferLength - const newLength = newRealLength + this.remainingBufferOffset - if (newLength > this.remainingBuffer.byteLength) { + let combinedBufferOffset = 0 + let reuseRemainingBuffer = this.remainingBufferLength > 0 + if (reuseRemainingBuffer) { + const newLength = this.remainingBufferLength + combinedBufferLength + const newFullLength = newLength + this.remainingBufferOffset + if (newFullLength > this.remainingBuffer.byteLength) { let newBufferLength = this.remainingBuffer.byteLength * 2 - while (newRealLength >= newBufferLength) { + while (newLength >= newBufferLength) { newBufferLength *= 2 } const newBuffer = Buffer.allocUnsafe(newBufferLength) @@ -112,12 +112,12 @@ export class Parser { } buffer.copy(this.remainingBuffer, this.remainingBufferOffset + this.remainingBufferLength) combinedBuffer = this.remainingBuffer - combinedBufferLength = this.remainingBufferLength = newRealLength + combinedBufferLength = this.remainingBufferLength = newLength combinedBufferOffset = this.remainingBufferOffset } - const realLength = combinedBufferOffset + combinedBufferLength + const fullLength = combinedBufferOffset + combinedBufferLength let offset = combinedBufferOffset - while (offset + HEADER_LENGTH <= realLength) { + while (offset + HEADER_LENGTH <= fullLength) { // code is 1 byte long - it identifies the message type const code = combinedBuffer[offset] @@ -126,7 +126,7 @@ export class Parser { const fullMessageLength = CODE_LENGTH + length - if (fullMessageLength + offset <= realLength) { + if (fullMessageLength + offset <= fullLength) { const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer) callback(message) offset += fullMessageLength @@ -135,14 +135,19 @@ export class Parser { } } - if (offset === realLength) { + if (offset === fullLength) { this.remainingBuffer = emptyBuffer this.remainingBufferLength = 0 this.remainingBufferOffset = 0 } else { - this.remainingBuffer = remainingBufferNotEmpty ? combinedBuffer : combinedBuffer.slice() - this.remainingBufferLength = combinedBufferLength - offset - this.remainingBufferOffset += offset + if (reuseRemainingBuffer) { + this.remainingBufferLength = combinedBufferLength - offset + this.remainingBufferOffset += offset + } else { + this.remainingBuffer = combinedBuffer.slice(offset) + this.remainingBufferLength = this.remainingBuffer.byteLength + this.remainingBufferOffset = 0 + } } } From 316b119e63f50b60f540f1390d36f341317ae01a Mon Sep 17 00:00:00 2001 From: regevbr Date: Fri, 19 Jun 2020 03:27:39 +0300 Subject: [PATCH 0669/1037] fix: major performance issues with bytea performance #2240 --- packages/pg-protocol/src/parser.ts | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 63303ac83..eabb1e3d7 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -96,11 +96,20 @@ export class Parser { const newLength = this.remainingBufferLength + combinedBufferLength const newFullLength = newLength + this.remainingBufferOffset if (newFullLength > this.remainingBuffer.byteLength) { - let newBufferLength = this.remainingBuffer.byteLength * 2 - while (newLength >= newBufferLength) { - newBufferLength *= 2 + // We can't concat the new buffer with the remaining one + let newBuffer: Buffer + if (newLength <= this.remainingBuffer.byteLength && this.remainingBufferOffset >= this.remainingBufferLength) { + // We can move the relevant part to the beginning of the buffer instead of allocating a new buffer + newBuffer = this.remainingBuffer + } else { + // Allocate a new larger buffer + let newBufferLength = this.remainingBuffer.byteLength * 2 + while (newLength >= newBufferLength) { + newBufferLength *= 2 + } + newBuffer = Buffer.allocUnsafe(newBufferLength) } - const newBuffer = Buffer.allocUnsafe(newBufferLength) + // Move the remaining buffer to the new one this.remainingBuffer.copy( newBuffer, 0, @@ -110,6 +119,7 @@ export class Parser { this.remainingBuffer = newBuffer this.remainingBufferOffset = 0 } + // Concat the new buffer with the remaining one buffer.copy(this.remainingBuffer, this.remainingBufferOffset + this.remainingBufferLength) combinedBuffer = this.remainingBuffer combinedBufferLength = this.remainingBufferLength = newLength @@ -134,16 +144,18 @@ export class Parser { break } } - if (offset === fullLength) { + // No more use for the buffer this.remainingBuffer = emptyBuffer this.remainingBufferLength = 0 this.remainingBufferOffset = 0 } else { if (reuseRemainingBuffer) { + // Adjust the cursors of remainingBuffer this.remainingBufferLength = combinedBufferLength - offset this.remainingBufferOffset += offset } else { + // To avoid side effects, copy the remaining part of the new buffer to remainingBuffer this.remainingBuffer = combinedBuffer.slice(offset) this.remainingBufferLength = this.remainingBuffer.byteLength this.remainingBufferOffset = 0 From 89758cee2f7306d1a3471fe9f64d86f5c25aa8b4 Mon Sep 17 00:00:00 2001 From: regevbr Date: Fri, 19 Jun 2020 03:39:06 +0300 Subject: [PATCH 0670/1037] fix: major performance issues with bytea performance #2240 --- packages/pg-protocol/src/parser.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index eabb1e3d7..56670fd75 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -150,14 +150,14 @@ export class Parser { this.remainingBufferLength = 0 this.remainingBufferOffset = 0 } else { + this.remainingBufferLength = fullLength - offset if (reuseRemainingBuffer) { // Adjust the cursors of remainingBuffer - this.remainingBufferLength = combinedBufferLength - offset - this.remainingBufferOffset += offset + this.remainingBufferOffset = offset } else { - // To avoid side effects, copy the remaining part of the new buffer to remainingBuffer - this.remainingBuffer = combinedBuffer.slice(offset) - this.remainingBufferLength = this.remainingBuffer.byteLength + // To avoid side effects, copy the remaining part of the new buffer to remainingBuffer with extra space for next buffer + this.remainingBuffer = Buffer.allocUnsafe(combinedBufferLength * 2) + combinedBuffer.copy(this.remainingBuffer, 0, offset) this.remainingBufferOffset = 0 } } From 5e0d684446e044d3c3d979fd09bb3247acbc006f Mon Sep 17 00:00:00 2001 From: regevbr Date: Sat, 20 Jun 2020 10:44:28 +0300 Subject: [PATCH 0671/1037] fix: major performance issues with bytea performance #2240 --- packages/pg-protocol/src/parser.ts | 85 ++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 22 deletions(-) diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 56670fd75..1827c3d1f 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -73,6 +73,14 @@ const enum MessageCodes { export type MessageCallback = (msg: BackendMessage) => void +interface CombinedBuffer { + combinedBuffer: Buffer + combinedBufferOffset: number + combinedBufferLength: number + combinedBufferFullLength: number + reuseRemainingBuffer: boolean +} + export class Parser { private remainingBuffer: Buffer = emptyBuffer private remainingBufferLength: number = 0 @@ -88,6 +96,41 @@ export class Parser { } public parse(buffer: Buffer, callback: MessageCallback) { + const { + combinedBuffer, + combinedBufferOffset, + combinedBufferLength, + reuseRemainingBuffer, + combinedBufferFullLength, + } = this.mergeBuffer(buffer) + let offset = combinedBufferOffset + while (offset + HEADER_LENGTH <= combinedBufferFullLength) { + // code is 1 byte long - it identifies the message type + const code = combinedBuffer[offset] + + // length is 1 Uint32BE - it is the length of the message EXCLUDING the code + const length = combinedBuffer.readUInt32BE(offset + CODE_LENGTH) + + const fullMessageLength = CODE_LENGTH + length + + if (fullMessageLength + offset <= combinedBufferFullLength) { + const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer) + callback(message) + offset += fullMessageLength + } else { + break + } + } + this.consumeBuffer({ + combinedBuffer, + combinedBufferOffset: offset, + combinedBufferLength, + reuseRemainingBuffer, + combinedBufferFullLength, + }) + } + + private mergeBuffer(buffer: Buffer): CombinedBuffer { let combinedBuffer = buffer let combinedBufferLength = buffer.byteLength let combinedBufferOffset = 0 @@ -125,39 +168,37 @@ export class Parser { combinedBufferLength = this.remainingBufferLength = newLength combinedBufferOffset = this.remainingBufferOffset } - const fullLength = combinedBufferOffset + combinedBufferLength - let offset = combinedBufferOffset - while (offset + HEADER_LENGTH <= fullLength) { - // code is 1 byte long - it identifies the message type - const code = combinedBuffer[offset] - - // length is 1 Uint32BE - it is the length of the message EXCLUDING the code - const length = combinedBuffer.readUInt32BE(offset + CODE_LENGTH) - - const fullMessageLength = CODE_LENGTH + length - - if (fullMessageLength + offset <= fullLength) { - const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer) - callback(message) - offset += fullMessageLength - } else { - break - } + const combinedBufferFullLength = combinedBufferOffset + combinedBufferLength + return { + combinedBuffer, + combinedBufferOffset, + combinedBufferLength, + reuseRemainingBuffer, + combinedBufferFullLength, } - if (offset === fullLength) { + } + + private consumeBuffer({ + combinedBufferOffset, + combinedBufferFullLength, + reuseRemainingBuffer, + combinedBuffer, + combinedBufferLength, + }: CombinedBuffer) { + if (combinedBufferOffset === combinedBufferFullLength) { // No more use for the buffer this.remainingBuffer = emptyBuffer this.remainingBufferLength = 0 this.remainingBufferOffset = 0 } else { - this.remainingBufferLength = fullLength - offset + this.remainingBufferLength = combinedBufferFullLength - combinedBufferOffset if (reuseRemainingBuffer) { // Adjust the cursors of remainingBuffer - this.remainingBufferOffset = offset + this.remainingBufferOffset = combinedBufferOffset } else { // To avoid side effects, copy the remaining part of the new buffer to remainingBuffer with extra space for next buffer this.remainingBuffer = Buffer.allocUnsafe(combinedBufferLength * 2) - combinedBuffer.copy(this.remainingBuffer, 0, offset) + combinedBuffer.copy(this.remainingBuffer, 0, combinedBufferOffset) this.remainingBufferOffset = 0 } } From 27029ba7c750d8b4543789899d5c8fe0263dbc38 Mon Sep 17 00:00:00 2001 From: Matt Riedemann Date: Wed, 24 Jun 2020 11:31:35 -0500 Subject: [PATCH 0672/1037] Fix rejectUnauthorize typo in CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 274c7487e..f9220322a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ We do not include break-fix version release in this file. ### pg@8.1.0 - Switch to using [monorepo](https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string) version of `pg-connection-string`. This includes better support for SSL argument parsing from connection strings and ensures continuity of support. -- Add `&ssl=no-verify` option to connection string and `PGSSLMODE=no-verify` environment variable support for the pure JS driver. This is equivalent of passing `{ ssl: { rejectUnauthorize: false } }` to the client/pool constructor. The advantage of having support in connection strings and environment variables is it can be "externally" configured via environment variables and CLI arguments much more easily, and should remove the need to directly edit any application code for [the SSL default changes in 8.0](https://node-postgres.com/announcements#2020-02-25). This should make using `pg@8.x` significantly less difficult on environments like Heroku for example. +- Add `&ssl=no-verify` option to connection string and `PGSSLMODE=no-verify` environment variable support for the pure JS driver. This is equivalent of passing `{ ssl: { rejectUnauthorized: false } }` to the client/pool constructor. The advantage of having support in connection strings and environment variables is it can be "externally" configured via environment variables and CLI arguments much more easily, and should remove the need to directly edit any application code for [the SSL default changes in 8.0](https://node-postgres.com/announcements#2020-02-25). This should make using `pg@8.x` significantly less difficult on environments like Heroku for example. ### pg-pool@3.2.0 From f49db313c1a75a7679c467b9f1740ea70047a509 Mon Sep 17 00:00:00 2001 From: Liam Aharon Date: Tue, 30 Jun 2020 17:13:41 +1000 Subject: [PATCH 0673/1037] Fix typo in README.md --- packages/pg-pool/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg-pool/README.md b/packages/pg-pool/README.md index f1c81ae52..c6d7e9287 100644 --- a/packages/pg-pool/README.md +++ b/packages/pg-pool/README.md @@ -69,7 +69,7 @@ const config = { const pool = new Pool(config); /* - Transforms, 'progres://DBuser:secret@DBHost:#####/myDB', into + Transforms, 'postgres://DBuser:secret@DBHost:#####/myDB', into config = { user: 'DBuser', password: 'secret', From 64c78b0b0ef41d8da966c20a3b97eab74c1c3c60 Mon Sep 17 00:00:00 2001 From: regevbr Date: Fri, 3 Jul 2020 17:52:26 +0300 Subject: [PATCH 0674/1037] fix: major performance issues with bytea performance #2240 --- package.json | 2 +- packages/pg-protocol/src/parser.ts | 128 +++++++++-------------------- packages/pg/bench.js | 20 ++++- 3 files changed, 55 insertions(+), 95 deletions(-) diff --git a/package.json b/package.json index 282ca9376..6ab9fa918 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "packages/*" ], "scripts": { - "test": "yarn lint && yarn lerna exec yarn test", + "test": "export PGDATABASE=data && export PGUSER=user && export PGPASSWORD=pass && yarn lint && yarn lerna exec yarn test", "build": "yarn lerna exec --scope pg-protocol yarn build", "pretest": "yarn build", "lint": "if [ -x ./node_modules/.bin/prettier ]; then eslint '*/**/*.{js,ts,tsx}'; fi;" diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 1827c3d1f..a00dabec9 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -73,18 +73,10 @@ const enum MessageCodes { export type MessageCallback = (msg: BackendMessage) => void -interface CombinedBuffer { - combinedBuffer: Buffer - combinedBufferOffset: number - combinedBufferLength: number - combinedBufferFullLength: number - reuseRemainingBuffer: boolean -} - export class Parser { - private remainingBuffer: Buffer = emptyBuffer - private remainingBufferLength: number = 0 - private remainingBufferOffset: number = 0 + private buffer: Buffer = emptyBuffer + private bufferLength: number = 0 + private bufferOffset: number = 0 private reader = new BufferReader() private mode: Mode @@ -96,111 +88,65 @@ export class Parser { } public parse(buffer: Buffer, callback: MessageCallback) { - const { - combinedBuffer, - combinedBufferOffset, - combinedBufferLength, - reuseRemainingBuffer, - combinedBufferFullLength, - } = this.mergeBuffer(buffer) - let offset = combinedBufferOffset - while (offset + HEADER_LENGTH <= combinedBufferFullLength) { + this.mergeBuffer(buffer) + const bufferFullLength = this.bufferOffset + this.bufferLength + let offset = this.bufferOffset + while (offset + HEADER_LENGTH <= bufferFullLength) { // code is 1 byte long - it identifies the message type - const code = combinedBuffer[offset] - + const code = this.buffer[offset] // length is 1 Uint32BE - it is the length of the message EXCLUDING the code - const length = combinedBuffer.readUInt32BE(offset + CODE_LENGTH) - + const length = this.buffer.readUInt32BE(offset + CODE_LENGTH) const fullMessageLength = CODE_LENGTH + length - - if (fullMessageLength + offset <= combinedBufferFullLength) { - const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer) + if (fullMessageLength + offset <= bufferFullLength) { + const message = this.handlePacket(offset + HEADER_LENGTH, code, length, this.buffer) callback(message) offset += fullMessageLength } else { break } } - this.consumeBuffer({ - combinedBuffer, - combinedBufferOffset: offset, - combinedBufferLength, - reuseRemainingBuffer, - combinedBufferFullLength, - }) + if (offset === bufferFullLength) { + // No more use for the buffer + this.buffer = emptyBuffer + this.bufferLength = 0 + this.bufferOffset = 0 + } else { + // Adjust the cursors of remainingBuffer + this.bufferLength = bufferFullLength - offset + this.bufferOffset = offset + } } - private mergeBuffer(buffer: Buffer): CombinedBuffer { - let combinedBuffer = buffer - let combinedBufferLength = buffer.byteLength - let combinedBufferOffset = 0 - let reuseRemainingBuffer = this.remainingBufferLength > 0 - if (reuseRemainingBuffer) { - const newLength = this.remainingBufferLength + combinedBufferLength - const newFullLength = newLength + this.remainingBufferOffset - if (newFullLength > this.remainingBuffer.byteLength) { + private mergeBuffer(buffer: Buffer): void { + if (this.bufferLength > 0) { + const newLength = this.bufferLength + buffer.byteLength + const newFullLength = newLength + this.bufferOffset + if (newFullLength > this.buffer.byteLength) { // We can't concat the new buffer with the remaining one let newBuffer: Buffer - if (newLength <= this.remainingBuffer.byteLength && this.remainingBufferOffset >= this.remainingBufferLength) { + if (newLength <= this.buffer.byteLength && this.bufferOffset >= this.bufferLength) { // We can move the relevant part to the beginning of the buffer instead of allocating a new buffer - newBuffer = this.remainingBuffer + newBuffer = this.buffer } else { // Allocate a new larger buffer - let newBufferLength = this.remainingBuffer.byteLength * 2 + let newBufferLength = this.buffer.byteLength * 2 while (newLength >= newBufferLength) { newBufferLength *= 2 } newBuffer = Buffer.allocUnsafe(newBufferLength) } // Move the remaining buffer to the new one - this.remainingBuffer.copy( - newBuffer, - 0, - this.remainingBufferOffset, - this.remainingBufferOffset + this.remainingBufferLength - ) - this.remainingBuffer = newBuffer - this.remainingBufferOffset = 0 + this.buffer.copy(newBuffer, 0, this.bufferOffset, this.bufferOffset + this.bufferLength) + this.buffer = newBuffer + this.bufferOffset = 0 } // Concat the new buffer with the remaining one - buffer.copy(this.remainingBuffer, this.remainingBufferOffset + this.remainingBufferLength) - combinedBuffer = this.remainingBuffer - combinedBufferLength = this.remainingBufferLength = newLength - combinedBufferOffset = this.remainingBufferOffset - } - const combinedBufferFullLength = combinedBufferOffset + combinedBufferLength - return { - combinedBuffer, - combinedBufferOffset, - combinedBufferLength, - reuseRemainingBuffer, - combinedBufferFullLength, - } - } - - private consumeBuffer({ - combinedBufferOffset, - combinedBufferFullLength, - reuseRemainingBuffer, - combinedBuffer, - combinedBufferLength, - }: CombinedBuffer) { - if (combinedBufferOffset === combinedBufferFullLength) { - // No more use for the buffer - this.remainingBuffer = emptyBuffer - this.remainingBufferLength = 0 - this.remainingBufferOffset = 0 + buffer.copy(this.buffer, this.bufferOffset + this.bufferLength) + this.bufferLength = newLength } else { - this.remainingBufferLength = combinedBufferFullLength - combinedBufferOffset - if (reuseRemainingBuffer) { - // Adjust the cursors of remainingBuffer - this.remainingBufferOffset = combinedBufferOffset - } else { - // To avoid side effects, copy the remaining part of the new buffer to remainingBuffer with extra space for next buffer - this.remainingBuffer = Buffer.allocUnsafe(combinedBufferLength * 2) - combinedBuffer.copy(this.remainingBuffer, 0, combinedBufferOffset) - this.remainingBufferOffset = 0 - } + this.buffer = buffer + this.bufferOffset = 0 + this.bufferLength = buffer.byteLength } } diff --git a/packages/pg/bench.js b/packages/pg/bench.js index 80c07dc19..c861c3ae6 100644 --- a/packages/pg/bench.js +++ b/packages/pg/bench.js @@ -1,5 +1,4 @@ const pg = require('./lib') -const pool = new pg.Pool() const params = { text: @@ -17,7 +16,7 @@ const seq = { } const exec = async (client, q) => { - const result = await client.query({ + await client.query({ text: q.text, values: q.values, rowMode: 'array', @@ -40,6 +39,7 @@ const run = async () => { const client = new pg.Client() await client.connect() await client.query('CREATE TEMP TABLE foobar(name TEXT, age NUMERIC)') + await client.query('CREATE TEMP TABLE buf(name TEXT, data BYTEA)') await bench(client, params, 1000) console.log('warmup done') const seconds = 5 @@ -61,7 +61,21 @@ const run = async () => { console.log('insert queries:', queries) console.log('qps', queries / seconds) console.log('on my laptop best so far seen 5799 qps') - console.log() + + console.log('') + console.log('Warming up bytea test') + await client.query({ + text: 'INSERT INTO buf(name, data) VALUES ($1, $2)', + values: ['test', Buffer.allocUnsafe(104857600)], + }) + console.log('bytea warmup done') + const start = Date.now() + const results = await client.query('SELECT * FROM buf') + const time = Date.now() - start + console.log('bytea time:', time, 'ms') + console.log('bytea length:', results.rows[0].data.byteLength, 'bytes') + console.log('on my laptop best so far seen 1107ms and 104857600 bytes') + await client.end() await client.end() } From bf53552a15d1f09dbbd119b13711a13adf60b0b9 Mon Sep 17 00:00:00 2001 From: regevbr Date: Fri, 3 Jul 2020 17:53:22 +0300 Subject: [PATCH 0675/1037] fix: major performance issues with bytea performance #2240 --- packages/pg-protocol/src/parser.ts | 128 ++++++++++++++++++++--------- packages/pg/bench.js | 20 +---- 2 files changed, 94 insertions(+), 54 deletions(-) diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index a00dabec9..1827c3d1f 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -73,10 +73,18 @@ const enum MessageCodes { export type MessageCallback = (msg: BackendMessage) => void +interface CombinedBuffer { + combinedBuffer: Buffer + combinedBufferOffset: number + combinedBufferLength: number + combinedBufferFullLength: number + reuseRemainingBuffer: boolean +} + export class Parser { - private buffer: Buffer = emptyBuffer - private bufferLength: number = 0 - private bufferOffset: number = 0 + private remainingBuffer: Buffer = emptyBuffer + private remainingBufferLength: number = 0 + private remainingBufferOffset: number = 0 private reader = new BufferReader() private mode: Mode @@ -88,65 +96,111 @@ export class Parser { } public parse(buffer: Buffer, callback: MessageCallback) { - this.mergeBuffer(buffer) - const bufferFullLength = this.bufferOffset + this.bufferLength - let offset = this.bufferOffset - while (offset + HEADER_LENGTH <= bufferFullLength) { + const { + combinedBuffer, + combinedBufferOffset, + combinedBufferLength, + reuseRemainingBuffer, + combinedBufferFullLength, + } = this.mergeBuffer(buffer) + let offset = combinedBufferOffset + while (offset + HEADER_LENGTH <= combinedBufferFullLength) { // code is 1 byte long - it identifies the message type - const code = this.buffer[offset] + const code = combinedBuffer[offset] + // length is 1 Uint32BE - it is the length of the message EXCLUDING the code - const length = this.buffer.readUInt32BE(offset + CODE_LENGTH) + const length = combinedBuffer.readUInt32BE(offset + CODE_LENGTH) + const fullMessageLength = CODE_LENGTH + length - if (fullMessageLength + offset <= bufferFullLength) { - const message = this.handlePacket(offset + HEADER_LENGTH, code, length, this.buffer) + + if (fullMessageLength + offset <= combinedBufferFullLength) { + const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer) callback(message) offset += fullMessageLength } else { break } } - if (offset === bufferFullLength) { - // No more use for the buffer - this.buffer = emptyBuffer - this.bufferLength = 0 - this.bufferOffset = 0 - } else { - // Adjust the cursors of remainingBuffer - this.bufferLength = bufferFullLength - offset - this.bufferOffset = offset - } + this.consumeBuffer({ + combinedBuffer, + combinedBufferOffset: offset, + combinedBufferLength, + reuseRemainingBuffer, + combinedBufferFullLength, + }) } - private mergeBuffer(buffer: Buffer): void { - if (this.bufferLength > 0) { - const newLength = this.bufferLength + buffer.byteLength - const newFullLength = newLength + this.bufferOffset - if (newFullLength > this.buffer.byteLength) { + private mergeBuffer(buffer: Buffer): CombinedBuffer { + let combinedBuffer = buffer + let combinedBufferLength = buffer.byteLength + let combinedBufferOffset = 0 + let reuseRemainingBuffer = this.remainingBufferLength > 0 + if (reuseRemainingBuffer) { + const newLength = this.remainingBufferLength + combinedBufferLength + const newFullLength = newLength + this.remainingBufferOffset + if (newFullLength > this.remainingBuffer.byteLength) { // We can't concat the new buffer with the remaining one let newBuffer: Buffer - if (newLength <= this.buffer.byteLength && this.bufferOffset >= this.bufferLength) { + if (newLength <= this.remainingBuffer.byteLength && this.remainingBufferOffset >= this.remainingBufferLength) { // We can move the relevant part to the beginning of the buffer instead of allocating a new buffer - newBuffer = this.buffer + newBuffer = this.remainingBuffer } else { // Allocate a new larger buffer - let newBufferLength = this.buffer.byteLength * 2 + let newBufferLength = this.remainingBuffer.byteLength * 2 while (newLength >= newBufferLength) { newBufferLength *= 2 } newBuffer = Buffer.allocUnsafe(newBufferLength) } // Move the remaining buffer to the new one - this.buffer.copy(newBuffer, 0, this.bufferOffset, this.bufferOffset + this.bufferLength) - this.buffer = newBuffer - this.bufferOffset = 0 + this.remainingBuffer.copy( + newBuffer, + 0, + this.remainingBufferOffset, + this.remainingBufferOffset + this.remainingBufferLength + ) + this.remainingBuffer = newBuffer + this.remainingBufferOffset = 0 } // Concat the new buffer with the remaining one - buffer.copy(this.buffer, this.bufferOffset + this.bufferLength) - this.bufferLength = newLength + buffer.copy(this.remainingBuffer, this.remainingBufferOffset + this.remainingBufferLength) + combinedBuffer = this.remainingBuffer + combinedBufferLength = this.remainingBufferLength = newLength + combinedBufferOffset = this.remainingBufferOffset + } + const combinedBufferFullLength = combinedBufferOffset + combinedBufferLength + return { + combinedBuffer, + combinedBufferOffset, + combinedBufferLength, + reuseRemainingBuffer, + combinedBufferFullLength, + } + } + + private consumeBuffer({ + combinedBufferOffset, + combinedBufferFullLength, + reuseRemainingBuffer, + combinedBuffer, + combinedBufferLength, + }: CombinedBuffer) { + if (combinedBufferOffset === combinedBufferFullLength) { + // No more use for the buffer + this.remainingBuffer = emptyBuffer + this.remainingBufferLength = 0 + this.remainingBufferOffset = 0 } else { - this.buffer = buffer - this.bufferOffset = 0 - this.bufferLength = buffer.byteLength + this.remainingBufferLength = combinedBufferFullLength - combinedBufferOffset + if (reuseRemainingBuffer) { + // Adjust the cursors of remainingBuffer + this.remainingBufferOffset = combinedBufferOffset + } else { + // To avoid side effects, copy the remaining part of the new buffer to remainingBuffer with extra space for next buffer + this.remainingBuffer = Buffer.allocUnsafe(combinedBufferLength * 2) + combinedBuffer.copy(this.remainingBuffer, 0, combinedBufferOffset) + this.remainingBufferOffset = 0 + } } } diff --git a/packages/pg/bench.js b/packages/pg/bench.js index c861c3ae6..80c07dc19 100644 --- a/packages/pg/bench.js +++ b/packages/pg/bench.js @@ -1,4 +1,5 @@ const pg = require('./lib') +const pool = new pg.Pool() const params = { text: @@ -16,7 +17,7 @@ const seq = { } const exec = async (client, q) => { - await client.query({ + const result = await client.query({ text: q.text, values: q.values, rowMode: 'array', @@ -39,7 +40,6 @@ const run = async () => { const client = new pg.Client() await client.connect() await client.query('CREATE TEMP TABLE foobar(name TEXT, age NUMERIC)') - await client.query('CREATE TEMP TABLE buf(name TEXT, data BYTEA)') await bench(client, params, 1000) console.log('warmup done') const seconds = 5 @@ -61,21 +61,7 @@ const run = async () => { console.log('insert queries:', queries) console.log('qps', queries / seconds) console.log('on my laptop best so far seen 5799 qps') - - console.log('') - console.log('Warming up bytea test') - await client.query({ - text: 'INSERT INTO buf(name, data) VALUES ($1, $2)', - values: ['test', Buffer.allocUnsafe(104857600)], - }) - console.log('bytea warmup done') - const start = Date.now() - const results = await client.query('SELECT * FROM buf') - const time = Date.now() - start - console.log('bytea time:', time, 'ms') - console.log('bytea length:', results.rows[0].data.byteLength, 'bytes') - console.log('on my laptop best so far seen 1107ms and 104857600 bytes') - + console.log() await client.end() await client.end() } From 410a6ab2486446129bced11aaf942a53e3bf30cb Mon Sep 17 00:00:00 2001 From: regevbr Date: Fri, 3 Jul 2020 17:54:29 +0300 Subject: [PATCH 0676/1037] fix: major performance issues with bytea performance #2240 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6ab9fa918..282ca9376 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "packages/*" ], "scripts": { - "test": "export PGDATABASE=data && export PGUSER=user && export PGPASSWORD=pass && yarn lint && yarn lerna exec yarn test", + "test": "yarn lint && yarn lerna exec yarn test", "build": "yarn lerna exec --scope pg-protocol yarn build", "pretest": "yarn build", "lint": "if [ -x ./node_modules/.bin/prettier ]; then eslint '*/**/*.{js,ts,tsx}'; fi;" From 69af2672ed3ece1872f60d4b4398676901971a8f Mon Sep 17 00:00:00 2001 From: regevbr Date: Fri, 3 Jul 2020 17:56:13 +0300 Subject: [PATCH 0677/1037] fix: major performance issues with bytea performance #2240 --- packages/pg/bench.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/pg/bench.js b/packages/pg/bench.js index 80c07dc19..1c1aa641d 100644 --- a/packages/pg/bench.js +++ b/packages/pg/bench.js @@ -1,5 +1,4 @@ const pg = require('./lib') -const pool = new pg.Pool() const params = { text: @@ -17,7 +16,7 @@ const seq = { } const exec = async (client, q) => { - const result = await client.query({ + await client.query({ text: q.text, values: q.values, rowMode: 'array', @@ -39,7 +38,9 @@ const bench = async (client, q, time) => { const run = async () => { const client = new pg.Client() await client.connect() + console.log('start') await client.query('CREATE TEMP TABLE foobar(name TEXT, age NUMERIC)') + await client.query('CREATE TEMP TABLE buf(name TEXT, data BYTEA)') await bench(client, params, 1000) console.log('warmup done') const seconds = 5 @@ -61,7 +62,21 @@ const run = async () => { console.log('insert queries:', queries) console.log('qps', queries / seconds) console.log('on my laptop best so far seen 5799 qps') - console.log() + + console.log('') + console.log('Warming up bytea test') + await client.query({ + text: 'INSERT INTO buf(name, data) VALUES ($1, $2)', + values: ['test', Buffer.allocUnsafe(104857600)], + }) + console.log('bytea warmup done') + const start = Date.now() + const results = await client.query('SELECT * FROM buf') + const time = Date.now() - start + console.log('bytea time:', time, 'ms') + console.log('bytea length:', results.rows[0].data.byteLength, 'bytes') + console.log('on my laptop best so far seen 1107ms and 104857600 bytes') + await client.end() await client.end() } From 1d3f155d4ffa5ac4200cfcc8ceb4d338790e5556 Mon Sep 17 00:00:00 2001 From: regevbr Date: Fri, 3 Jul 2020 17:57:07 +0300 Subject: [PATCH 0678/1037] fix: major performance issues with bytea performance #2240 --- packages/pg-protocol/src/parser.ts | 128 +++++++++-------------------- 1 file changed, 37 insertions(+), 91 deletions(-) diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 1827c3d1f..a00dabec9 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -73,18 +73,10 @@ const enum MessageCodes { export type MessageCallback = (msg: BackendMessage) => void -interface CombinedBuffer { - combinedBuffer: Buffer - combinedBufferOffset: number - combinedBufferLength: number - combinedBufferFullLength: number - reuseRemainingBuffer: boolean -} - export class Parser { - private remainingBuffer: Buffer = emptyBuffer - private remainingBufferLength: number = 0 - private remainingBufferOffset: number = 0 + private buffer: Buffer = emptyBuffer + private bufferLength: number = 0 + private bufferOffset: number = 0 private reader = new BufferReader() private mode: Mode @@ -96,111 +88,65 @@ export class Parser { } public parse(buffer: Buffer, callback: MessageCallback) { - const { - combinedBuffer, - combinedBufferOffset, - combinedBufferLength, - reuseRemainingBuffer, - combinedBufferFullLength, - } = this.mergeBuffer(buffer) - let offset = combinedBufferOffset - while (offset + HEADER_LENGTH <= combinedBufferFullLength) { + this.mergeBuffer(buffer) + const bufferFullLength = this.bufferOffset + this.bufferLength + let offset = this.bufferOffset + while (offset + HEADER_LENGTH <= bufferFullLength) { // code is 1 byte long - it identifies the message type - const code = combinedBuffer[offset] - + const code = this.buffer[offset] // length is 1 Uint32BE - it is the length of the message EXCLUDING the code - const length = combinedBuffer.readUInt32BE(offset + CODE_LENGTH) - + const length = this.buffer.readUInt32BE(offset + CODE_LENGTH) const fullMessageLength = CODE_LENGTH + length - - if (fullMessageLength + offset <= combinedBufferFullLength) { - const message = this.handlePacket(offset + HEADER_LENGTH, code, length, combinedBuffer) + if (fullMessageLength + offset <= bufferFullLength) { + const message = this.handlePacket(offset + HEADER_LENGTH, code, length, this.buffer) callback(message) offset += fullMessageLength } else { break } } - this.consumeBuffer({ - combinedBuffer, - combinedBufferOffset: offset, - combinedBufferLength, - reuseRemainingBuffer, - combinedBufferFullLength, - }) + if (offset === bufferFullLength) { + // No more use for the buffer + this.buffer = emptyBuffer + this.bufferLength = 0 + this.bufferOffset = 0 + } else { + // Adjust the cursors of remainingBuffer + this.bufferLength = bufferFullLength - offset + this.bufferOffset = offset + } } - private mergeBuffer(buffer: Buffer): CombinedBuffer { - let combinedBuffer = buffer - let combinedBufferLength = buffer.byteLength - let combinedBufferOffset = 0 - let reuseRemainingBuffer = this.remainingBufferLength > 0 - if (reuseRemainingBuffer) { - const newLength = this.remainingBufferLength + combinedBufferLength - const newFullLength = newLength + this.remainingBufferOffset - if (newFullLength > this.remainingBuffer.byteLength) { + private mergeBuffer(buffer: Buffer): void { + if (this.bufferLength > 0) { + const newLength = this.bufferLength + buffer.byteLength + const newFullLength = newLength + this.bufferOffset + if (newFullLength > this.buffer.byteLength) { // We can't concat the new buffer with the remaining one let newBuffer: Buffer - if (newLength <= this.remainingBuffer.byteLength && this.remainingBufferOffset >= this.remainingBufferLength) { + if (newLength <= this.buffer.byteLength && this.bufferOffset >= this.bufferLength) { // We can move the relevant part to the beginning of the buffer instead of allocating a new buffer - newBuffer = this.remainingBuffer + newBuffer = this.buffer } else { // Allocate a new larger buffer - let newBufferLength = this.remainingBuffer.byteLength * 2 + let newBufferLength = this.buffer.byteLength * 2 while (newLength >= newBufferLength) { newBufferLength *= 2 } newBuffer = Buffer.allocUnsafe(newBufferLength) } // Move the remaining buffer to the new one - this.remainingBuffer.copy( - newBuffer, - 0, - this.remainingBufferOffset, - this.remainingBufferOffset + this.remainingBufferLength - ) - this.remainingBuffer = newBuffer - this.remainingBufferOffset = 0 + this.buffer.copy(newBuffer, 0, this.bufferOffset, this.bufferOffset + this.bufferLength) + this.buffer = newBuffer + this.bufferOffset = 0 } // Concat the new buffer with the remaining one - buffer.copy(this.remainingBuffer, this.remainingBufferOffset + this.remainingBufferLength) - combinedBuffer = this.remainingBuffer - combinedBufferLength = this.remainingBufferLength = newLength - combinedBufferOffset = this.remainingBufferOffset - } - const combinedBufferFullLength = combinedBufferOffset + combinedBufferLength - return { - combinedBuffer, - combinedBufferOffset, - combinedBufferLength, - reuseRemainingBuffer, - combinedBufferFullLength, - } - } - - private consumeBuffer({ - combinedBufferOffset, - combinedBufferFullLength, - reuseRemainingBuffer, - combinedBuffer, - combinedBufferLength, - }: CombinedBuffer) { - if (combinedBufferOffset === combinedBufferFullLength) { - // No more use for the buffer - this.remainingBuffer = emptyBuffer - this.remainingBufferLength = 0 - this.remainingBufferOffset = 0 + buffer.copy(this.buffer, this.bufferOffset + this.bufferLength) + this.bufferLength = newLength } else { - this.remainingBufferLength = combinedBufferFullLength - combinedBufferOffset - if (reuseRemainingBuffer) { - // Adjust the cursors of remainingBuffer - this.remainingBufferOffset = combinedBufferOffset - } else { - // To avoid side effects, copy the remaining part of the new buffer to remainingBuffer with extra space for next buffer - this.remainingBuffer = Buffer.allocUnsafe(combinedBufferLength * 2) - combinedBuffer.copy(this.remainingBuffer, 0, combinedBufferOffset) - this.remainingBufferOffset = 0 - } + this.buffer = buffer + this.bufferOffset = 0 + this.bufferLength = buffer.byteLength } } From dec892ed015af8844f1aa6a9475832c88693b464 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 7 Jul 2020 08:58:57 -0500 Subject: [PATCH 0679/1037] Publish - pg-cursor@2.2.2 - pg-protocol@1.2.5 - pg-query-stream@3.1.2 - pg@8.2.2 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 92b227ec0..130d788ac 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.2.1", + "version": "2.2.2", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -17,6 +17,6 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.2.1" + "pg": "^8.2.2" } } diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 6e32eb26c..0a65e77d9 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.2.4", + "version": "1.2.5", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index f36fe55f5..e0db5b11a 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.1.1", + "version": "3.1.2", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -26,12 +26,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.2.1", + "pg": "^8.2.2", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.2.1" + "pg-cursor": "^2.2.2" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 32ce3e181..c3950f6be 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.2.1", + "version": "8.2.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "packet-reader": "1.0.0", "pg-connection-string": "^2.2.3", "pg-pool": "^3.2.1", - "pg-protocol": "^1.2.4", + "pg-protocol": "^1.2.5", "pg-types": "^2.1.0", "pgpass": "1.x", "semver": "4.3.2" From 3360697bbdcbc256a86e728dc6c0d05ed5497059 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 8 Jul 2020 12:17:20 -0500 Subject: [PATCH 0680/1037] Add integration test for #2216 --- .../client/connection-parameter-tests.js | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 packages/pg/test/integration/client/connection-parameter-tests.js diff --git a/packages/pg/test/integration/client/connection-parameter-tests.js b/packages/pg/test/integration/client/connection-parameter-tests.js new file mode 100644 index 000000000..b3bf74c36 --- /dev/null +++ b/packages/pg/test/integration/client/connection-parameter-tests.js @@ -0,0 +1,13 @@ +const helper = require('../test-helper') +const suite = new helper.Suite() +const { Client } = helper.pg + +suite.test('it sends options', async () => { + const client = new Client({ + options: '--default_transaction_isolation=serializable', + }) + await client.connect() + const { rows } = await client.query('SHOW default_transaction_isolation') + console.log(rows) + await client.end() +}) From cf203431d62486a52c656618b3fbcd2ab7af8ae9 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 9 Jul 2020 10:35:06 -0500 Subject: [PATCH 0681/1037] Publish - pg-connection-string@2.3.0 - pg-cursor@2.3.0 - pg-query-stream@3.2.0 - pg@8.3.0 --- packages/pg-connection-string/package.json | 2 +- packages/pg-cursor/package.json | 4 ++-- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index 2c2407250..9bf951d16 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "2.2.3", + "version": "2.3.0", "description": "Functions for dealing with a PostgresSQL connection string", "main": "./index.js", "types": "./index.d.ts", diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 130d788ac..00fbcaaa2 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.2.2", + "version": "2.3.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -17,6 +17,6 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.2.2" + "pg": "^8.3.0" } } diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index e0db5b11a..34009afca 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.1.2", + "version": "3.2.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -26,12 +26,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.2.2", + "pg": "^8.3.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.2.2" + "pg-cursor": "^2.3.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index c3950f6be..d60e9e4b1 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.2.2", + "version": "8.3.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -21,7 +21,7 @@ "dependencies": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-connection-string": "^2.2.3", + "pg-connection-string": "^2.3.0", "pg-pool": "^3.2.1", "pg-protocol": "^1.2.5", "pg-types": "^2.1.0", From f0bf3cda7b05be77e84c067a231bbb9db7c96c39 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 9 Jul 2020 10:37:32 -0500 Subject: [PATCH 0682/1037] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9220322a..7dabeb479 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### pg@8.3.0 + +- Support passing a [string of command line options flags](https://github.com/brianc/node-postgres/pull/2216) via the `{ options: string }` field on client/pool config. + ### pg@8.2.0 - Switch internal protocol parser & serializer to [pg-protocol](https://github.com/brianc/node-postgres/tree/master/packages/pg-protocol). The change is backwards compatible but results in a significant performance improvement across the board, with some queries as much as 50% faster. This is the first work to land in an on-going performance improvment initiative I'm working on. Stay tuned as things are set to get much faster still! :rocket: From 54048235c590e3aee322e88d56093ad7f42ae4a4 Mon Sep 17 00:00:00 2001 From: Aravindan Ve Date: Fri, 10 Jul 2020 11:43:32 +0530 Subject: [PATCH 0683/1037] fix: use types configured on pg client in pg-query-stream --- packages/pg-query-stream/index.js | 3 +++ .../pg-query-stream/test/client-options.js | 27 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 packages/pg-query-stream/test/client-options.js diff --git a/packages/pg-query-stream/index.js b/packages/pg-query-stream/index.js index 914a7e32b..3806e60aa 100644 --- a/packages/pg-query-stream/index.js +++ b/packages/pg-query-stream/index.js @@ -16,6 +16,9 @@ class PgQueryStream extends Readable { this.handleReadyForQuery = this.cursor.handleReadyForQuery.bind(this.cursor) this.handleError = this.cursor.handleError.bind(this.cursor) this.handleEmptyQuery = this.cursor.handleEmptyQuery.bind(this.cursor) + + // pg client sets types via _result property + this._result = this.cursor._result } submit(connection) { diff --git a/packages/pg-query-stream/test/client-options.js b/packages/pg-query-stream/test/client-options.js new file mode 100644 index 000000000..3820d96b2 --- /dev/null +++ b/packages/pg-query-stream/test/client-options.js @@ -0,0 +1,27 @@ +var pg = require('pg') +var assert = require('assert') +var QueryStream = require('../') + +describe('client options', function () { + it('uses custom types from client config', function (done) { + const types = { + getTypeParser: () => (string) => string, + } + var client = new pg.Client({ types }) + client.connect() + var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num') + var query = client.query(stream) + var result = [] + query.on('data', (datum) => { + result.push(datum) + }) + query.on('end', () => { + const expected = new Array(11).fill(0).map((_, i) => ({ + num: i.toString(), + })) + assert.deepEqual(result, expected) + client.end() + done() + }) + }) +}) From d7b22b390d355798d8204787f6b122d15c30995b Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Fri, 10 Jul 2020 08:55:31 -0700 Subject: [PATCH 0684/1037] Fix dependency badges for monorepo --- README.md | 2 +- packages/pg/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 34aceea3b..1fe69fa5f 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # node-postgres [![Build Status](https://secure.travis-ci.org/brianc/node-postgres.svg?branch=master)](http://travis-ci.org/brianc/node-postgres) -[![Dependency Status](https://david-dm.org/brianc/node-postgres.svg)](https://david-dm.org/brianc/node-postgres) +[![Dependency Status](https://david-dm.org/brianc/node-postgres.svg?path=packages/pg)](https://david-dm.org/brianc/node-postgres?path=packages/pg) NPM version NPM downloads diff --git a/packages/pg/README.md b/packages/pg/README.md index 0d471dd42..ed4d7a626 100644 --- a/packages/pg/README.md +++ b/packages/pg/README.md @@ -1,7 +1,7 @@ # node-postgres [![Build Status](https://secure.travis-ci.org/brianc/node-postgres.svg?branch=master)](http://travis-ci.org/brianc/node-postgres) -[![Dependency Status](https://david-dm.org/brianc/node-postgres.svg)](https://david-dm.org/brianc/node-postgres) +[![Dependency Status](https://david-dm.org/brianc/node-postgres.svg?path=packages/pg)](https://david-dm.org/brianc/node-postgres?path=packages/pg) NPM version NPM downloads From 80d07c489f661711586e5345700a85f72d734992 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 15 Jul 2020 10:01:26 -0500 Subject: [PATCH 0685/1037] Remove out of date unneeded copyright / license comments --- packages/pg/lib/client.js | 7 ------- packages/pg/lib/connection-parameters.js | 7 ------- packages/pg/lib/connection.js | 7 ------- packages/pg/lib/defaults.js | 7 ------- packages/pg/lib/index.js | 7 ------- packages/pg/lib/native/client.js | 7 ------- packages/pg/lib/native/query.js | 7 ------- packages/pg/lib/query.js | 7 ------- packages/pg/lib/result.js | 7 ------- packages/pg/lib/type-overrides.js | 7 ------- packages/pg/lib/utils.js | 7 ------- 11 files changed, 77 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 93dfc6c9c..e80c86145 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -1,11 +1,4 @@ 'use strict' -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ var EventEmitter = require('events').EventEmitter var util = require('util') diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index 546682521..96f1fef84 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -1,11 +1,4 @@ 'use strict' -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ var dns = require('dns') diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 65867026d..b046de403 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -1,11 +1,4 @@ 'use strict' -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ var net = require('net') var EventEmitter = require('events').EventEmitter diff --git a/packages/pg/lib/defaults.js b/packages/pg/lib/defaults.js index e28794dba..9384e01cb 100644 --- a/packages/pg/lib/defaults.js +++ b/packages/pg/lib/defaults.js @@ -1,11 +1,4 @@ 'use strict' -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ module.exports = { // database host. defaults to localhost diff --git a/packages/pg/lib/index.js b/packages/pg/lib/index.js index 975175cd4..fa6580559 100644 --- a/packages/pg/lib/index.js +++ b/packages/pg/lib/index.js @@ -1,11 +1,4 @@ 'use strict' -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ var Client = require('./client') var defaults = require('./defaults') diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index f45546151..b2cc43479 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -1,11 +1,4 @@ 'use strict' -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ // eslint-disable-next-line var Native = require('pg-native') diff --git a/packages/pg/lib/native/query.js b/packages/pg/lib/native/query.js index de443489a..d06db43ca 100644 --- a/packages/pg/lib/native/query.js +++ b/packages/pg/lib/native/query.js @@ -1,11 +1,4 @@ 'use strict' -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ var EventEmitter = require('events').EventEmitter var util = require('util') diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index 2392b710e..d43795bbe 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -1,11 +1,4 @@ 'use strict' -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ const { EventEmitter } = require('events') diff --git a/packages/pg/lib/result.js b/packages/pg/lib/result.js index 233455b06..55b7df58d 100644 --- a/packages/pg/lib/result.js +++ b/packages/pg/lib/result.js @@ -1,11 +1,4 @@ 'use strict' -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ var types = require('pg-types') diff --git a/packages/pg/lib/type-overrides.js b/packages/pg/lib/type-overrides.js index 63bfc83e1..66693482b 100644 --- a/packages/pg/lib/type-overrides.js +++ b/packages/pg/lib/type-overrides.js @@ -1,11 +1,4 @@ 'use strict' -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ var types = require('pg-types') diff --git a/packages/pg/lib/utils.js b/packages/pg/lib/utils.js index f6da81f47..b3b4ff4c1 100644 --- a/packages/pg/lib/utils.js +++ b/packages/pg/lib/utils.js @@ -1,11 +1,4 @@ 'use strict' -/** - * Copyright (c) 2010-2017 Brian Carlson (brian.m.carlson@gmail.com) - * All rights reserved. - * - * This source code is licensed under the MIT license found in the - * README.md file in the root directory of this source tree. - */ const crypto = require('crypto') From 04e5297d2ea5b45b32e01edaff97a7bd29ba6229 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 15 Jul 2020 10:33:33 -0500 Subject: [PATCH 0686/1037] Convert more things to ES6 classes --- packages/pg/lib/client.js | 939 ++++++++++++----------- packages/pg/lib/connection-parameters.js | 206 ++--- packages/pg/lib/result.js | 215 ++++-- 3 files changed, 720 insertions(+), 640 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 93dfc6c9c..fd9ecad19 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -19,576 +19,579 @@ var Query = require('./query') var defaults = require('./defaults') var Connection = require('./connection') -var Client = function (config) { - EventEmitter.call(this) - - this.connectionParameters = new ConnectionParameters(config) - this.user = this.connectionParameters.user - this.database = this.connectionParameters.database - this.port = this.connectionParameters.port - this.host = this.connectionParameters.host - - // "hiding" the password so it doesn't show up in stack traces - // or if the client is console.logged - Object.defineProperty(this, 'password', { - configurable: true, - enumerable: false, - writable: true, - value: this.connectionParameters.password, - }) - - this.replication = this.connectionParameters.replication - - var c = config || {} - - this._Promise = c.Promise || global.Promise - this._types = new TypeOverrides(c.types) - this._ending = false - this._connecting = false - this._connected = false - this._connectionError = false - this._queryable = true - - this.connection = - c.connection || - new Connection({ - stream: c.stream, - ssl: this.connectionParameters.ssl, - keepAlive: c.keepAlive || false, - keepAliveInitialDelayMillis: c.keepAliveInitialDelayMillis || 0, - encoding: this.connectionParameters.client_encoding || 'utf8', +class Client extends EventEmitter { + constructor(config) { + super() + + this.connectionParameters = new ConnectionParameters(config) + this.user = this.connectionParameters.user + this.database = this.connectionParameters.database + this.port = this.connectionParameters.port + this.host = this.connectionParameters.host + + // "hiding" the password so it doesn't show up in stack traces + // or if the client is console.logged + Object.defineProperty(this, 'password', { + configurable: true, + enumerable: false, + writable: true, + value: this.connectionParameters.password, }) - this.queryQueue = [] - this.binary = c.binary || defaults.binary - this.processID = null - this.secretKey = null - this.ssl = this.connectionParameters.ssl || false - this._connectionTimeoutMillis = c.connectionTimeoutMillis || 0 -} - -util.inherits(Client, EventEmitter) -Client.prototype._errorAllQueries = function (err) { - const enqueueError = (query) => { - process.nextTick(() => { - query.handleError(err, this.connection) - }) + this.replication = this.connectionParameters.replication + + var c = config || {} + + this._Promise = c.Promise || global.Promise + this._types = new TypeOverrides(c.types) + this._ending = false + this._connecting = false + this._connected = false + this._connectionError = false + this._queryable = true + + this.connection = + c.connection || + new Connection({ + stream: c.stream, + ssl: this.connectionParameters.ssl, + keepAlive: c.keepAlive || false, + keepAliveInitialDelayMillis: c.keepAliveInitialDelayMillis || 0, + encoding: this.connectionParameters.client_encoding || 'utf8', + }) + this.queryQueue = [] + this.binary = c.binary || defaults.binary + this.processID = null + this.secretKey = null + this.ssl = this.connectionParameters.ssl || false + this._connectionTimeoutMillis = c.connectionTimeoutMillis || 0 } - if (this.activeQuery) { - enqueueError(this.activeQuery) - this.activeQuery = null - } + _errorAllQueries(err) { + const enqueueError = (query) => { + process.nextTick(() => { + query.handleError(err, this.connection) + }) + } - this.queryQueue.forEach(enqueueError) - this.queryQueue.length = 0 -} + if (this.activeQuery) { + enqueueError(this.activeQuery) + this.activeQuery = null + } -Client.prototype._connect = function (callback) { - var self = this - var con = this.connection - if (this._connecting || this._connected) { - const err = new Error('Client has already been connected. You cannot reuse a client.') - process.nextTick(() => { - callback(err) - }) - return - } - this._connecting = true - - var connectionTimeoutHandle - if (this._connectionTimeoutMillis > 0) { - connectionTimeoutHandle = setTimeout(() => { - con._ending = true - con.stream.destroy(new Error('timeout expired')) - }, this._connectionTimeoutMillis) + this.queryQueue.forEach(enqueueError) + this.queryQueue.length = 0 } - if (this.host && this.host.indexOf('/') === 0) { - con.connect(this.host + '/.s.PGSQL.' + this.port) - } else { - con.connect(this.port, this.host) - } + _connect(callback) { + var self = this + var con = this.connection + if (this._connecting || this._connected) { + const err = new Error('Client has already been connected. You cannot reuse a client.') + process.nextTick(() => { + callback(err) + }) + return + } + this._connecting = true + + var connectionTimeoutHandle + if (this._connectionTimeoutMillis > 0) { + connectionTimeoutHandle = setTimeout(() => { + con._ending = true + con.stream.destroy(new Error('timeout expired')) + }, this._connectionTimeoutMillis) + } - // once connection is established send startup message - con.on('connect', function () { - if (self.ssl) { - con.requestSsl() + if (this.host && this.host.indexOf('/') === 0) { + con.connect(this.host + '/.s.PGSQL.' + this.port) } else { - con.startup(self.getStartupConf()) + con.connect(this.port, this.host) } - }) - - con.on('sslconnect', function () { - con.startup(self.getStartupConf()) - }) - - function checkPgPass(cb) { - return function (msg) { - if (typeof self.password === 'function') { - self._Promise - .resolve() - .then(() => self.password()) - .then((pass) => { - if (pass !== undefined) { - if (typeof pass !== 'string') { - con.emit('error', new TypeError('Password must be a string')) - return + + // once connection is established send startup message + con.on('connect', function () { + if (self.ssl) { + con.requestSsl() + } else { + con.startup(self.getStartupConf()) + } + }) + + con.on('sslconnect', function () { + con.startup(self.getStartupConf()) + }) + + function checkPgPass(cb) { + return function (msg) { + if (typeof self.password === 'function') { + self._Promise + .resolve() + .then(() => self.password()) + .then((pass) => { + if (pass !== undefined) { + if (typeof pass !== 'string') { + con.emit('error', new TypeError('Password must be a string')) + return + } + self.connectionParameters.password = self.password = pass + } else { + self.connectionParameters.password = self.password = null } + cb(msg) + }) + .catch((err) => { + con.emit('error', err) + }) + } else if (self.password !== null) { + cb(msg) + } else { + pgPass(self.connectionParameters, function (pass) { + if (undefined !== pass) { self.connectionParameters.password = self.password = pass - } else { - self.connectionParameters.password = self.password = null } cb(msg) }) - .catch((err) => { - con.emit('error', err) - }) - } else if (self.password !== null) { - cb(msg) - } else { - pgPass(self.connectionParameters, function (pass) { - if (undefined !== pass) { - self.connectionParameters.password = self.password = pass - } - cb(msg) - }) + } } } - } - // password request handling - con.on( - 'authenticationCleartextPassword', - checkPgPass(function () { - con.password(self.password) - }) - ) + // password request handling + con.on( + 'authenticationCleartextPassword', + checkPgPass(function () { + con.password(self.password) + }) + ) - // password request handling - con.on( - 'authenticationMD5Password', - checkPgPass(function (msg) { - con.password(utils.postgresMd5PasswordHash(self.user, self.password, msg.salt)) - }) - ) + // password request handling + con.on( + 'authenticationMD5Password', + checkPgPass(function (msg) { + con.password(utils.postgresMd5PasswordHash(self.user, self.password, msg.salt)) + }) + ) - // password request handling (SASL) - var saslSession - con.on( - 'authenticationSASL', - checkPgPass(function (msg) { - saslSession = sasl.startSession(msg.mechanisms) + // password request handling (SASL) + var saslSession + con.on( + 'authenticationSASL', + checkPgPass(function (msg) { + saslSession = sasl.startSession(msg.mechanisms) - con.sendSASLInitialResponseMessage(saslSession.mechanism, saslSession.response) - }) - ) + con.sendSASLInitialResponseMessage(saslSession.mechanism, saslSession.response) + }) + ) - // password request handling (SASL) - con.on('authenticationSASLContinue', function (msg) { - sasl.continueSession(saslSession, self.password, msg.data) + // password request handling (SASL) + con.on('authenticationSASLContinue', function (msg) { + sasl.continueSession(saslSession, self.password, msg.data) - con.sendSCRAMClientFinalMessage(saslSession.response) - }) + con.sendSCRAMClientFinalMessage(saslSession.response) + }) - // password request handling (SASL) - con.on('authenticationSASLFinal', function (msg) { - sasl.finalizeSession(saslSession, msg.data) + // password request handling (SASL) + con.on('authenticationSASLFinal', function (msg) { + sasl.finalizeSession(saslSession, msg.data) - saslSession = null - }) + saslSession = null + }) - con.once('backendKeyData', function (msg) { - self.processID = msg.processID - self.secretKey = msg.secretKey - }) + con.once('backendKeyData', function (msg) { + self.processID = msg.processID + self.secretKey = msg.secretKey + }) - const connectingErrorHandler = (err) => { - if (this._connectionError) { - return + const connectingErrorHandler = (err) => { + if (this._connectionError) { + return + } + this._connectionError = true + clearTimeout(connectionTimeoutHandle) + if (callback) { + return callback(err) + } + this.emit('error', err) } - this._connectionError = true - clearTimeout(connectionTimeoutHandle) - if (callback) { - return callback(err) + + const connectedErrorHandler = (err) => { + this._queryable = false + this._errorAllQueries(err) + this.emit('error', err) } - this.emit('error', err) - } - const connectedErrorHandler = (err) => { - this._queryable = false - this._errorAllQueries(err) - this.emit('error', err) - } + const connectedErrorMessageHandler = (msg) => { + const activeQuery = this.activeQuery - const connectedErrorMessageHandler = (msg) => { - const activeQuery = this.activeQuery + if (!activeQuery) { + connectedErrorHandler(msg) + return + } - if (!activeQuery) { - connectedErrorHandler(msg) - return + this.activeQuery = null + activeQuery.handleError(msg, con) } - this.activeQuery = null - activeQuery.handleError(msg, con) - } + con.on('error', connectingErrorHandler) + con.on('errorMessage', connectingErrorHandler) + + // hook up query handling events to connection + // after the connection initially becomes ready for queries + con.once('readyForQuery', function () { + self._connecting = false + self._connected = true + self._attachListeners(con) + con.removeListener('error', connectingErrorHandler) + con.removeListener('errorMessage', connectingErrorHandler) + con.on('error', connectedErrorHandler) + con.on('errorMessage', connectedErrorMessageHandler) + clearTimeout(connectionTimeoutHandle) + + // process possible callback argument to Client#connect + if (callback) { + callback(null, self) + // remove callback for proper error handling + // after the connect event + callback = null + } + self.emit('connect') + }) - con.on('error', connectingErrorHandler) - con.on('errorMessage', connectingErrorHandler) - - // hook up query handling events to connection - // after the connection initially becomes ready for queries - con.once('readyForQuery', function () { - self._connecting = false - self._connected = true - self._attachListeners(con) - con.removeListener('error', connectingErrorHandler) - con.removeListener('errorMessage', connectingErrorHandler) - con.on('error', connectedErrorHandler) - con.on('errorMessage', connectedErrorMessageHandler) - clearTimeout(connectionTimeoutHandle) - - // process possible callback argument to Client#connect - if (callback) { - callback(null, self) - // remove callback for proper error handling - // after the connect event - callback = null - } - self.emit('connect') - }) - - con.on('readyForQuery', function () { - var activeQuery = self.activeQuery - self.activeQuery = null - self.readyForQuery = true - if (activeQuery) { - activeQuery.handleReadyForQuery(con) - } - self._pulseQueryQueue() - }) - - con.once('end', () => { - const error = this._ending ? new Error('Connection terminated') : new Error('Connection terminated unexpectedly') - - clearTimeout(connectionTimeoutHandle) - this._errorAllQueries(error) - - if (!this._ending) { - // if the connection is ended without us calling .end() - // on this client then we have an unexpected disconnection - // treat this as an error unless we've already emitted an error - // during connection. - if (this._connecting && !this._connectionError) { - if (callback) { - callback(error) - } else { + con.on('readyForQuery', function () { + var activeQuery = self.activeQuery + self.activeQuery = null + self.readyForQuery = true + if (activeQuery) { + activeQuery.handleReadyForQuery(con) + } + self._pulseQueryQueue() + }) + + con.once('end', () => { + const error = this._ending ? new Error('Connection terminated') : new Error('Connection terminated unexpectedly') + + clearTimeout(connectionTimeoutHandle) + this._errorAllQueries(error) + + if (!this._ending) { + // if the connection is ended without us calling .end() + // on this client then we have an unexpected disconnection + // treat this as an error unless we've already emitted an error + // during connection. + if (this._connecting && !this._connectionError) { + if (callback) { + callback(error) + } else { + connectedErrorHandler(error) + } + } else if (!this._connectionError) { connectedErrorHandler(error) } - } else if (!this._connectionError) { - connectedErrorHandler(error) } - } - process.nextTick(() => { - this.emit('end') + process.nextTick(() => { + this.emit('end') + }) }) - }) - con.on('notice', function (msg) { - self.emit('notice', msg) - }) -} + con.on('notice', function (msg) { + self.emit('notice', msg) + }) + } -Client.prototype.connect = function (callback) { - if (callback) { - this._connect(callback) - return + connect(callback) { + if (callback) { + this._connect(callback) + return + } + + return new this._Promise((resolve, reject) => { + this._connect((error) => { + if (error) { + reject(error) + } else { + resolve() + } + }) + }) } - return new this._Promise((resolve, reject) => { - this._connect((error) => { - if (error) { - reject(error) - } else { - resolve() - } + _attachListeners(con) { + const self = this + // delegate rowDescription to active query + con.on('rowDescription', function (msg) { + self.activeQuery.handleRowDescription(msg) }) - }) -} -Client.prototype._attachListeners = function (con) { - const self = this - // delegate rowDescription to active query - con.on('rowDescription', function (msg) { - self.activeQuery.handleRowDescription(msg) - }) - - // delegate dataRow to active query - con.on('dataRow', function (msg) { - self.activeQuery.handleDataRow(msg) - }) - - // delegate portalSuspended to active query - // eslint-disable-next-line no-unused-vars - con.on('portalSuspended', function (msg) { - self.activeQuery.handlePortalSuspended(con) - }) - - // delegate emptyQuery to active query - // eslint-disable-next-line no-unused-vars - con.on('emptyQuery', function (msg) { - self.activeQuery.handleEmptyQuery(con) - }) - - // delegate commandComplete to active query - con.on('commandComplete', function (msg) { - self.activeQuery.handleCommandComplete(msg, con) - }) - - // if a prepared statement has a name and properly parses - // we track that its already been executed so we don't parse - // it again on the same client - // eslint-disable-next-line no-unused-vars - con.on('parseComplete', function (msg) { - if (self.activeQuery.name) { - con.parsedStatements[self.activeQuery.name] = self.activeQuery.text - } - }) + // delegate dataRow to active query + con.on('dataRow', function (msg) { + self.activeQuery.handleDataRow(msg) + }) - // eslint-disable-next-line no-unused-vars - con.on('copyInResponse', function (msg) { - self.activeQuery.handleCopyInResponse(self.connection) - }) + // delegate portalSuspended to active query + // eslint-disable-next-line no-unused-vars + con.on('portalSuspended', function (msg) { + self.activeQuery.handlePortalSuspended(con) + }) - con.on('copyData', function (msg) { - self.activeQuery.handleCopyData(msg, self.connection) - }) + // delegate emptyQuery to active query + // eslint-disable-next-line no-unused-vars + con.on('emptyQuery', function (msg) { + self.activeQuery.handleEmptyQuery(con) + }) - con.on('notification', function (msg) { - self.emit('notification', msg) - }) -} + // delegate commandComplete to active query + con.on('commandComplete', function (msg) { + self.activeQuery.handleCommandComplete(msg, con) + }) -Client.prototype.getStartupConf = function () { - var params = this.connectionParameters + // if a prepared statement has a name and properly parses + // we track that its already been executed so we don't parse + // it again on the same client + // eslint-disable-next-line no-unused-vars + con.on('parseComplete', function (msg) { + if (self.activeQuery.name) { + con.parsedStatements[self.activeQuery.name] = self.activeQuery.text + } + }) - var data = { - user: params.user, - database: params.database, + con.on('copyInResponse', this.handleCopyInResponse.bind(this)) + con.on('copyData', this.handleCopyData.bind(this)) + con.on('notification', this.handleNotification.bind(this)) } - var appName = params.application_name || params.fallback_application_name - if (appName) { - data.application_name = appName + handleCopyInResponse(msg) { + this.activeQuery.handleCopyInResponse(this.connection) } - if (params.replication) { - data.replication = '' + params.replication - } - if (params.statement_timeout) { - data.statement_timeout = String(parseInt(params.statement_timeout, 10)) - } - if (params.idle_in_transaction_session_timeout) { - data.idle_in_transaction_session_timeout = String(parseInt(params.idle_in_transaction_session_timeout, 10)) + + handleCopyData(msg) { + this.activeQuery.handleCopyData(msg, this.connection) } - if (params.options) { - data.options = params.options + + handleNotification(msg) { + this.emit('notification', msg) } - return data -} + getStartupConf() { + var params = this.connectionParameters -Client.prototype.cancel = function (client, query) { - if (client.activeQuery === query) { - var con = this.connection + var data = { + user: params.user, + database: params.database, + } - if (this.host && this.host.indexOf('/') === 0) { - con.connect(this.host + '/.s.PGSQL.' + this.port) - } else { - con.connect(this.port, this.host) + var appName = params.application_name || params.fallback_application_name + if (appName) { + data.application_name = appName + } + if (params.replication) { + data.replication = '' + params.replication + } + if (params.statement_timeout) { + data.statement_timeout = String(parseInt(params.statement_timeout, 10)) + } + if (params.idle_in_transaction_session_timeout) { + data.idle_in_transaction_session_timeout = String(parseInt(params.idle_in_transaction_session_timeout, 10)) + } + if (params.options) { + data.options = params.options } - // once connection is established send cancel message - con.on('connect', function () { - con.cancel(client.processID, client.secretKey) - }) - } else if (client.queryQueue.indexOf(query) !== -1) { - client.queryQueue.splice(client.queryQueue.indexOf(query), 1) + return data } -} - -Client.prototype.setTypeParser = function (oid, format, parseFn) { - return this._types.setTypeParser(oid, format, parseFn) -} -Client.prototype.getTypeParser = function (oid, format) { - return this._types.getTypeParser(oid, format) -} + cancel(client, query) { + if (client.activeQuery === query) { + var con = this.connection -// Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c -Client.prototype.escapeIdentifier = function (str) { - return '"' + str.replace(/"/g, '""') + '"' -} + if (this.host && this.host.indexOf('/') === 0) { + con.connect(this.host + '/.s.PGSQL.' + this.port) + } else { + con.connect(this.port, this.host) + } -// Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c -Client.prototype.escapeLiteral = function (str) { - var hasBackslash = false - var escaped = "'" - - for (var i = 0; i < str.length; i++) { - var c = str[i] - if (c === "'") { - escaped += c + c - } else if (c === '\\') { - escaped += c + c - hasBackslash = true - } else { - escaped += c + // once connection is established send cancel message + con.on('connect', function () { + con.cancel(client.processID, client.secretKey) + }) + } else if (client.queryQueue.indexOf(query) !== -1) { + client.queryQueue.splice(client.queryQueue.indexOf(query), 1) } } - escaped += "'" - - if (hasBackslash === true) { - escaped = ' E' + escaped + setTypeParser(oid, format, parseFn) { + return this._types.setTypeParser(oid, format, parseFn) } - return escaped -} + getTypeParser(oid, format) { + return this._types.getTypeParser(oid, format) + } -Client.prototype._pulseQueryQueue = function () { - if (this.readyForQuery === true) { - this.activeQuery = this.queryQueue.shift() - if (this.activeQuery) { - this.readyForQuery = false - this.hasExecuted = true + // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c + escapeIdentifier(str) { + return '"' + str.replace(/"/g, '""') + '"' + } - const queryError = this.activeQuery.submit(this.connection) - if (queryError) { - process.nextTick(() => { - this.activeQuery.handleError(queryError, this.connection) - this.readyForQuery = true - this._pulseQueryQueue() - }) + // Ported from PostgreSQL 9.2.4 source code in src/interfaces/libpq/fe-exec.c + escapeLiteral(str) { + var hasBackslash = false + var escaped = "'" + + for (var i = 0; i < str.length; i++) { + var c = str[i] + if (c === "'") { + escaped += c + c + } else if (c === '\\') { + escaped += c + c + hasBackslash = true + } else { + escaped += c } - } else if (this.hasExecuted) { - this.activeQuery = null - this.emit('drain') } - } -} -Client.prototype.query = function (config, values, callback) { - // can take in strings, config object or query object - var query - var result - var readTimeout - var readTimeoutTimer - var queryCallback - - if (config === null || config === undefined) { - throw new TypeError('Client was passed a null or undefined query') - } else if (typeof config.submit === 'function') { - readTimeout = config.query_timeout || this.connectionParameters.query_timeout - result = query = config - if (typeof values === 'function') { - query.callback = query.callback || values + escaped += "'" + + if (hasBackslash === true) { + escaped = ' E' + escaped } - } else { - readTimeout = this.connectionParameters.query_timeout - query = new Query(config, values, callback) - if (!query.callback) { - result = new this._Promise((resolve, reject) => { - query.callback = (err, res) => (err ? reject(err) : resolve(res)) - }) + + return escaped + } + + _pulseQueryQueue() { + if (this.readyForQuery === true) { + this.activeQuery = this.queryQueue.shift() + if (this.activeQuery) { + this.readyForQuery = false + this.hasExecuted = true + + const queryError = this.activeQuery.submit(this.connection) + if (queryError) { + process.nextTick(() => { + this.activeQuery.handleError(queryError, this.connection) + this.readyForQuery = true + this._pulseQueryQueue() + }) + } + } else if (this.hasExecuted) { + this.activeQuery = null + this.emit('drain') + } } } - if (readTimeout) { - queryCallback = query.callback + query(config, values, callback) { + // can take in strings, config object or query object + var query + var result + var readTimeout + var readTimeoutTimer + var queryCallback + + if (config === null || config === undefined) { + throw new TypeError('Client was passed a null or undefined query') + } else if (typeof config.submit === 'function') { + readTimeout = config.query_timeout || this.connectionParameters.query_timeout + result = query = config + if (typeof values === 'function') { + query.callback = query.callback || values + } + } else { + readTimeout = this.connectionParameters.query_timeout + query = new Query(config, values, callback) + if (!query.callback) { + result = new this._Promise((resolve, reject) => { + query.callback = (err, res) => (err ? reject(err) : resolve(res)) + }) + } + } - readTimeoutTimer = setTimeout(() => { - var error = new Error('Query read timeout') + if (readTimeout) { + queryCallback = query.callback - process.nextTick(() => { - query.handleError(error, this.connection) - }) + readTimeoutTimer = setTimeout(() => { + var error = new Error('Query read timeout') - queryCallback(error) + process.nextTick(() => { + query.handleError(error, this.connection) + }) + + queryCallback(error) + + // we already returned an error, + // just do nothing if query completes + query.callback = () => {} + + // Remove from queue + var index = this.queryQueue.indexOf(query) + if (index > -1) { + this.queryQueue.splice(index, 1) + } - // we already returned an error, - // just do nothing if query completes - query.callback = () => {} + this._pulseQueryQueue() + }, readTimeout) - // Remove from queue - var index = this.queryQueue.indexOf(query) - if (index > -1) { - this.queryQueue.splice(index, 1) + query.callback = (err, res) => { + clearTimeout(readTimeoutTimer) + queryCallback(err, res) } + } - this._pulseQueryQueue() - }, readTimeout) + if (this.binary && !query.binary) { + query.binary = true + } - query.callback = (err, res) => { - clearTimeout(readTimeoutTimer) - queryCallback(err, res) + if (query._result && !query._result._types) { + query._result._types = this._types } - } - if (this.binary && !query.binary) { - query.binary = true - } + if (!this._queryable) { + process.nextTick(() => { + query.handleError(new Error('Client has encountered a connection error and is not queryable'), this.connection) + }) + return result + } - if (query._result && !query._result._types) { - query._result._types = this._types - } + if (this._ending) { + process.nextTick(() => { + query.handleError(new Error('Client was closed and is not queryable'), this.connection) + }) + return result + } - if (!this._queryable) { - process.nextTick(() => { - query.handleError(new Error('Client has encountered a connection error and is not queryable'), this.connection) - }) + this.queryQueue.push(query) + this._pulseQueryQueue() return result } - if (this._ending) { - process.nextTick(() => { - query.handleError(new Error('Client was closed and is not queryable'), this.connection) - }) - return result - } + end(cb) { + this._ending = true - this.queryQueue.push(query) - this._pulseQueryQueue() - return result -} + // if we have never connected, then end is a noop, callback immediately + if (!this.connection._connecting) { + if (cb) { + cb() + } else { + return this._Promise.resolve() + } + } -Client.prototype.end = function (cb) { - this._ending = true + if (this.activeQuery || !this._queryable) { + // if we have an active query we need to force a disconnect + // on the socket - otherwise a hung query could block end forever + this.connection.stream.destroy() + } else { + this.connection.end() + } - // if we have never connected, then end is a noop, callback immediately - if (!this.connection._connecting) { if (cb) { - cb() + this.connection.once('end', cb) } else { - return this._Promise.resolve() + return new this._Promise((resolve) => { + this.connection.once('end', resolve) + }) } } - - if (this.activeQuery || !this._queryable) { - // if we have an active query we need to force a disconnect - // on the socket - otherwise a hung query could block end forever - this.connection.stream.destroy() - } else { - this.connection.end() - } - - if (cb) { - this.connection.once('end', cb) - } else { - return new this._Promise((resolve) => { - this.connection.once('end', resolve) - }) - } } // expose a Query constructor diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index 546682521..eae798d50 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -40,73 +40,6 @@ var readSSLConfigFromEnvironment = function () { return defaults.ssl } -var ConnectionParameters = function (config) { - // if a string is passed, it is a raw connection string so we parse it into a config - config = typeof config === 'string' ? parse(config) : config || {} - - // if the config has a connectionString defined, parse IT into the config we use - // this will override other default values with what is stored in connectionString - if (config.connectionString) { - config = Object.assign({}, config, parse(config.connectionString)) - } - - this.user = val('user', config) - this.database = val('database', config) - - if (this.database === undefined) { - this.database = this.user - } - - this.port = parseInt(val('port', config), 10) - this.host = val('host', config) - - // "hiding" the password so it doesn't show up in stack traces - // or if the client is console.logged - Object.defineProperty(this, 'password', { - configurable: true, - enumerable: false, - writable: true, - value: val('password', config), - }) - - this.binary = val('binary', config) - this.options = val('options', config) - - this.ssl = typeof config.ssl === 'undefined' ? readSSLConfigFromEnvironment() : config.ssl - - // support passing in ssl=no-verify via connection string - if (this.ssl === 'no-verify') { - this.ssl = { rejectUnauthorized: false } - } - - this.client_encoding = val('client_encoding', config) - this.replication = val('replication', config) - // a domain socket begins with '/' - this.isDomainSocket = !(this.host || '').indexOf('/') - - this.application_name = val('application_name', config, 'PGAPPNAME') - this.fallback_application_name = val('fallback_application_name', config, false) - this.statement_timeout = val('statement_timeout', config, false) - this.idle_in_transaction_session_timeout = val('idle_in_transaction_session_timeout', config, false) - this.query_timeout = val('query_timeout', config, false) - - if (config.connectionTimeoutMillis === undefined) { - this.connect_timeout = process.env.PGCONNECT_TIMEOUT || 0 - } else { - this.connect_timeout = Math.floor(config.connectionTimeoutMillis / 1000) - } - - if (config.keepAlive === false) { - this.keepalives = 0 - } else if (config.keepAlive === true) { - this.keepalives = 1 - } - - if (typeof config.keepAliveInitialDelayMillis === 'number') { - this.keepalives_idle = Math.floor(config.keepAliveInitialDelayMillis / 1000) - } -} - // Convert arg to a string, surround in single quotes, and escape single quotes and backslashes var quoteParamValue = function (value) { return "'" + ('' + value).replace(/\\/g, '\\\\').replace(/'/g, "\\'") + "'" @@ -119,43 +52,112 @@ var add = function (params, config, paramName) { } } -ConnectionParameters.prototype.getLibpqConnectionString = function (cb) { - var params = [] - add(params, this, 'user') - add(params, this, 'password') - add(params, this, 'port') - add(params, this, 'application_name') - add(params, this, 'fallback_application_name') - add(params, this, 'connect_timeout') - add(params, this, 'options') - - var ssl = typeof this.ssl === 'object' ? this.ssl : this.ssl ? { sslmode: this.ssl } : {} - add(params, ssl, 'sslmode') - add(params, ssl, 'sslca') - add(params, ssl, 'sslkey') - add(params, ssl, 'sslcert') - add(params, ssl, 'sslrootcert') - - if (this.database) { - params.push('dbname=' + quoteParamValue(this.database)) - } - if (this.replication) { - params.push('replication=' + quoteParamValue(this.replication)) +class ConnectionParameters { + constructor(config) { + // if a string is passed, it is a raw connection string so we parse it into a config + config = typeof config === 'string' ? parse(config) : config || {} + + // if the config has a connectionString defined, parse IT into the config we use + // this will override other default values with what is stored in connectionString + if (config.connectionString) { + config = Object.assign({}, config, parse(config.connectionString)) + } + + this.user = val('user', config) + this.database = val('database', config) + + if (this.database === undefined) { + this.database = this.user + } + + this.port = parseInt(val('port', config), 10) + this.host = val('host', config) + + // "hiding" the password so it doesn't show up in stack traces + // or if the client is console.logged + Object.defineProperty(this, 'password', { + configurable: true, + enumerable: false, + writable: true, + value: val('password', config), + }) + + this.binary = val('binary', config) + this.options = val('options', config) + + this.ssl = typeof config.ssl === 'undefined' ? readSSLConfigFromEnvironment() : config.ssl + + // support passing in ssl=no-verify via connection string + if (this.ssl === 'no-verify') { + this.ssl = { rejectUnauthorized: false } + } + + this.client_encoding = val('client_encoding', config) + this.replication = val('replication', config) + // a domain socket begins with '/' + this.isDomainSocket = !(this.host || '').indexOf('/') + + this.application_name = val('application_name', config, 'PGAPPNAME') + this.fallback_application_name = val('fallback_application_name', config, false) + this.statement_timeout = val('statement_timeout', config, false) + this.idle_in_transaction_session_timeout = val('idle_in_transaction_session_timeout', config, false) + this.query_timeout = val('query_timeout', config, false) + + if (config.connectionTimeoutMillis === undefined) { + this.connect_timeout = process.env.PGCONNECT_TIMEOUT || 0 + } else { + this.connect_timeout = Math.floor(config.connectionTimeoutMillis / 1000) + } + + if (config.keepAlive === false) { + this.keepalives = 0 + } else if (config.keepAlive === true) { + this.keepalives = 1 + } + + if (typeof config.keepAliveInitialDelayMillis === 'number') { + this.keepalives_idle = Math.floor(config.keepAliveInitialDelayMillis / 1000) + } } - if (this.host) { - params.push('host=' + quoteParamValue(this.host)) - } - if (this.isDomainSocket) { - return cb(null, params.join(' ')) - } - if (this.client_encoding) { - params.push('client_encoding=' + quoteParamValue(this.client_encoding)) + + getLibpqConnectionString(cb) { + var params = [] + add(params, this, 'user') + add(params, this, 'password') + add(params, this, 'port') + add(params, this, 'application_name') + add(params, this, 'fallback_application_name') + add(params, this, 'connect_timeout') + add(params, this, 'options') + + var ssl = typeof this.ssl === 'object' ? this.ssl : this.ssl ? { sslmode: this.ssl } : {} + add(params, ssl, 'sslmode') + add(params, ssl, 'sslca') + add(params, ssl, 'sslkey') + add(params, ssl, 'sslcert') + add(params, ssl, 'sslrootcert') + + if (this.database) { + params.push('dbname=' + quoteParamValue(this.database)) + } + if (this.replication) { + params.push('replication=' + quoteParamValue(this.replication)) + } + if (this.host) { + params.push('host=' + quoteParamValue(this.host)) + } + if (this.isDomainSocket) { + return cb(null, params.join(' ')) + } + if (this.client_encoding) { + params.push('client_encoding=' + quoteParamValue(this.client_encoding)) + } + dns.lookup(this.host, function (err, address) { + if (err) return cb(err, null) + params.push('hostaddr=' + quoteParamValue(address)) + return cb(null, params.join(' ')) + }) } - dns.lookup(this.host, function (err, address) { - if (err) return cb(err, null) - params.push('hostaddr=' + quoteParamValue(address)) - return cb(null, params.join(' ')) - }) } module.exports = ConnectionParameters diff --git a/packages/pg/lib/result.js b/packages/pg/lib/result.js index 233455b06..5e895736b 100644 --- a/packages/pg/lib/result.js +++ b/packages/pg/lib/result.js @@ -9,95 +9,170 @@ var types = require('pg-types') +var matchRegexp = /^([A-Za-z]+)(?: (\d+))?(?: (\d+))?/ + // result object returned from query // in the 'end' event and also // passed as second argument to provided callback -var Result = function (rowMode, types) { - this.command = null - this.rowCount = null - this.oid = null - this.rows = [] - this.fields = [] - this._parsers = undefined - this._types = types - this.RowCtor = null - this.rowAsArray = rowMode === 'array' - if (this.rowAsArray) { - this.parseRow = this._parseRowAsArray +class Result { + constructor(rowMode, types) { + this.command = null + this.rowCount = null + this.oid = null + this.rows = [] + this.fields = [] + this._parsers = undefined + this._types = types + this.RowCtor = null + this.rowAsArray = rowMode === 'array' + if (this.rowAsArray) { + this.parseRow = this._parseRowAsArray + } } -} -var matchRegexp = /^([A-Za-z]+)(?: (\d+))?(?: (\d+))?/ + // adds a command complete message + addCommandComplete(msg) { + var match + if (msg.text) { + // pure javascript + match = matchRegexp.exec(msg.text) + } else { + // native bindings + match = matchRegexp.exec(msg.command) + } + if (match) { + this.command = match[1] + if (match[3]) { + // COMMMAND OID ROWS + this.oid = parseInt(match[2], 10) + this.rowCount = parseInt(match[3], 10) + } else if (match[2]) { + // COMMAND ROWS + this.rowCount = parseInt(match[2], 10) + } + } + } -// adds a command complete message -Result.prototype.addCommandComplete = function (msg) { - var match - if (msg.text) { - // pure javascript - match = matchRegexp.exec(msg.text) - } else { - // native bindings - match = matchRegexp.exec(msg.command) + _parseRowAsArray(rowData) { + var row = new Array(rowData.length) + for (var i = 0, len = rowData.length; i < len; i++) { + var rawValue = rowData[i] + if (rawValue !== null) { + row[i] = this._parsers[i](rawValue) + } else { + row[i] = null + } + } + return row } - if (match) { - this.command = match[1] - if (match[3]) { - // COMMMAND OID ROWS - this.oid = parseInt(match[2], 10) - this.rowCount = parseInt(match[3], 10) - } else if (match[2]) { - // COMMAND ROWS - this.rowCount = parseInt(match[2], 10) + + parseRow(rowData) { + var row = {} + for (var i = 0, len = rowData.length; i < len; i++) { + var rawValue = rowData[i] + var field = this.fields[i].name + if (rawValue !== null) { + row[field] = this._parsers[i](rawValue) + } else { + row[field] = null + } } + return row } -} -Result.prototype._parseRowAsArray = function (rowData) { - var row = new Array(rowData.length) - for (var i = 0, len = rowData.length; i < len; i++) { - var rawValue = rowData[i] - if (rawValue !== null) { - row[i] = this._parsers[i](rawValue) - } else { - row[i] = null + addRow(row) { + this.rows.push(row) + } + + addFields(fieldDescriptions) { + // clears field definitions + // multiple query statements in 1 action can result in multiple sets + // of rowDescriptions...eg: 'select NOW(); select 1::int;' + // you need to reset the fields + this.fields = fieldDescriptions + if (this.fields.length) { + this._parsers = new Array(fieldDescriptions.length) + } + for (var i = 0; i < fieldDescriptions.length; i++) { + var desc = fieldDescriptions[i] + if (this._types) { + this._parsers[i] = this._types.getTypeParser(desc.dataTypeID, desc.format || 'text') + } else { + this._parsers[i] = types.getTypeParser(desc.dataTypeID, desc.format || 'text') + } } } - return row -} -Result.prototype.parseRow = function (rowData) { - var row = {} - for (var i = 0, len = rowData.length; i < len; i++) { - var rawValue = rowData[i] - var field = this.fields[i].name - if (rawValue !== null) { - row[field] = this._parsers[i](rawValue) + // adds a command complete message + addCommandComplete(msg) { + var match + if (msg.text) { + // pure javascript + match = matchRegexp.exec(msg.text) } else { - row[field] = null + // native bindings + match = matchRegexp.exec(msg.command) + } + if (match) { + this.command = match[1] + if (match[3]) { + // COMMMAND OID ROWS + this.oid = parseInt(match[2], 10) + this.rowCount = parseInt(match[3], 10) + } else if (match[2]) { + // COMMAND ROWS + this.rowCount = parseInt(match[2], 10) + } } } - return row -} -Result.prototype.addRow = function (row) { - this.rows.push(row) -} + _parseRowAsArray(rowData) { + var row = new Array(rowData.length) + for (var i = 0, len = rowData.length; i < len; i++) { + var rawValue = rowData[i] + if (rawValue !== null) { + row[i] = this._parsers[i](rawValue) + } else { + row[i] = null + } + } + return row + } -Result.prototype.addFields = function (fieldDescriptions) { - // clears field definitions - // multiple query statements in 1 action can result in multiple sets - // of rowDescriptions...eg: 'select NOW(); select 1::int;' - // you need to reset the fields - this.fields = fieldDescriptions - if (this.fields.length) { - this._parsers = new Array(fieldDescriptions.length) + parseRow(rowData) { + var row = {} + for (var i = 0, len = rowData.length; i < len; i++) { + var rawValue = rowData[i] + var field = this.fields[i].name + if (rawValue !== null) { + row[field] = this._parsers[i](rawValue) + } else { + row[field] = null + } + } + return row } - for (var i = 0; i < fieldDescriptions.length; i++) { - var desc = fieldDescriptions[i] - if (this._types) { - this._parsers[i] = this._types.getTypeParser(desc.dataTypeID, desc.format || 'text') - } else { - this._parsers[i] = types.getTypeParser(desc.dataTypeID, desc.format || 'text') + + addRow(row) { + this.rows.push(row) + } + + addFields(fieldDescriptions) { + // clears field definitions + // multiple query statements in 1 action can result in multiple sets + // of rowDescriptions...eg: 'select NOW(); select 1::int;' + // you need to reset the fields + this.fields = fieldDescriptions + if (this.fields.length) { + this._parsers = new Array(fieldDescriptions.length) + } + for (var i = 0; i < fieldDescriptions.length; i++) { + var desc = fieldDescriptions[i] + if (this._types) { + this._parsers[i] = this._types.getTypeParser(desc.dataTypeID, desc.format || 'text') + } else { + this._parsers[i] = types.getTypeParser(desc.dataTypeID, desc.format || 'text') + } } } } From 66e1e76c9bdc110d9bc42baf71ee6beefd067983 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 15 Jul 2020 11:05:31 -0500 Subject: [PATCH 0687/1037] More refactoring --- packages/pg/bench.js | 2 +- packages/pg/lib/client.js | 261 ++++++++++++++++++++------------------ 2 files changed, 136 insertions(+), 127 deletions(-) diff --git a/packages/pg/bench.js b/packages/pg/bench.js index 1c1aa641d..a668aa85f 100644 --- a/packages/pg/bench.js +++ b/packages/pg/bench.js @@ -61,7 +61,7 @@ const run = async () => { queries = await bench(client, insert, seconds * 1000) console.log('insert queries:', queries) console.log('qps', queries / seconds) - console.log('on my laptop best so far seen 5799 qps') + console.log('on my laptop best so far seen 6303 qps') console.log('') console.log('Warming up bytea test') diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index fd9ecad19..2dbebe855 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -122,94 +122,25 @@ class Client extends EventEmitter { con.startup(self.getStartupConf()) }) - function checkPgPass(cb) { - return function (msg) { - if (typeof self.password === 'function') { - self._Promise - .resolve() - .then(() => self.password()) - .then((pass) => { - if (pass !== undefined) { - if (typeof pass !== 'string') { - con.emit('error', new TypeError('Password must be a string')) - return - } - self.connectionParameters.password = self.password = pass - } else { - self.connectionParameters.password = self.password = null - } - cb(msg) - }) - .catch((err) => { - con.emit('error', err) - }) - } else if (self.password !== null) { - cb(msg) - } else { - pgPass(self.connectionParameters, function (pass) { - if (undefined !== pass) { - self.connectionParameters.password = self.password = pass - } - cb(msg) - }) - } - } - } - // password request handling - con.on( - 'authenticationCleartextPassword', - checkPgPass(function () { - con.password(self.password) - }) - ) - + con.on('authenticationCleartextPassword', this.handleAuthenticationCleartextPassword.bind(this)) // password request handling - con.on( - 'authenticationMD5Password', - checkPgPass(function (msg) { - con.password(utils.postgresMd5PasswordHash(self.user, self.password, msg.salt)) - }) - ) - - // password request handling (SASL) - var saslSession - con.on( - 'authenticationSASL', - checkPgPass(function (msg) { - saslSession = sasl.startSession(msg.mechanisms) - - con.sendSASLInitialResponseMessage(saslSession.mechanism, saslSession.response) - }) - ) - - // password request handling (SASL) - con.on('authenticationSASLContinue', function (msg) { - sasl.continueSession(saslSession, self.password, msg.data) - - con.sendSCRAMClientFinalMessage(saslSession.response) - }) - + con.on('authenticationMD5Password', this.handleAuthenticationMD5Password.bind(this)) // password request handling (SASL) - con.on('authenticationSASLFinal', function (msg) { - sasl.finalizeSession(saslSession, msg.data) - - saslSession = null - }) - - con.once('backendKeyData', function (msg) { - self.processID = msg.processID - self.secretKey = msg.secretKey - }) + con.on('authenticationSASL', this.handleAuthenticationSASL.bind(this)) + con.on('authenticationSASLContinue', this.handleAuthenticationSASLContinue.bind(this)) + con.on('authenticationSASLFinal', this.handleAuthenticationSASLFinal.bind(this)) + con.once('backendKeyData', this.handleBackendKeyData.bind(this)) + this._connectionCallback = callback const connectingErrorHandler = (err) => { if (this._connectionError) { return } this._connectionError = true clearTimeout(connectionTimeoutHandle) - if (callback) { - return callback(err) + if (this._connectionCallback) { + return this._connectionCallback(err) } this.emit('error', err) } @@ -237,10 +168,9 @@ class Client extends EventEmitter { // hook up query handling events to connection // after the connection initially becomes ready for queries - con.once('readyForQuery', function () { + con.once('readyForQuery', () => { self._connecting = false self._connected = true - self._attachListeners(con) con.removeListener('error', connectingErrorHandler) con.removeListener('errorMessage', connectingErrorHandler) con.on('error', connectedErrorHandler) @@ -248,24 +178,18 @@ class Client extends EventEmitter { clearTimeout(connectionTimeoutHandle) // process possible callback argument to Client#connect - if (callback) { - callback(null, self) + if (this._connectionCallback) { + this._connectionCallback(null, self) // remove callback for proper error handling // after the connect event - callback = null + this._connectionCallback = null } self.emit('connect') }) - con.on('readyForQuery', function () { - var activeQuery = self.activeQuery - self.activeQuery = null - self.readyForQuery = true - if (activeQuery) { - activeQuery.handleReadyForQuery(con) - } - self._pulseQueryQueue() - }) + con.on('readyForQuery', this.handleReadyForQuery.bind(this)) + con.on('notice', this.handleNotice.bind(this)) + self._attachListeners(con) con.once('end', () => { const error = this._ending ? new Error('Connection terminated') : new Error('Connection terminated unexpectedly') @@ -279,8 +203,8 @@ class Client extends EventEmitter { // treat this as an error unless we've already emitted an error // during connection. if (this._connecting && !this._connectionError) { - if (callback) { - callback(error) + if (this._connectionCallback) { + this._connectionCallback(error) } else { connectedErrorHandler(error) } @@ -293,10 +217,6 @@ class Client extends EventEmitter { this.emit('end') }) }) - - con.on('notice', function (msg) { - self.emit('notice', msg) - }) } connect(callback) { @@ -317,47 +237,132 @@ class Client extends EventEmitter { } _attachListeners(con) { - const self = this - // delegate rowDescription to active query - con.on('rowDescription', function (msg) { - self.activeQuery.handleRowDescription(msg) + con.on('rowDescription', this.handleRowDescription.bind(this)) + con.on('dataRow', this.handleDataRow.bind(this)) + con.on('portalSuspended', this.handlePortalSuspended.bind(this)) + con.on('emptyQuery', this.handleEmptyQuery.bind(this)) + con.on('commandComplete', this.handleCommandComplete.bind(this)) + con.on('parseComplete', this.handleParseComplete.bind(this)) + con.on('copyInResponse', this.handleCopyInResponse.bind(this)) + con.on('copyData', this.handleCopyData.bind(this)) + con.on('notification', this.handleNotification.bind(this)) + } + + // TODO(bmc): deprecate pgpass "built in" integration since this.password can be a function + // it can be supplied by the user if required - this is a breaking change! + _checkPgPass(cb) { + return function (msg) { + if (typeof this.password === 'function') { + this._Promise + .resolve() + .then(() => this.password()) + .then((pass) => { + if (pass !== undefined) { + if (typeof pass !== 'string') { + con.emit('error', new TypeError('Password must be a string')) + return + } + this.connectionParameters.password = this.password = pass + } else { + this.connectionParameters.password = this.password = null + } + cb(msg) + }) + .catch((err) => { + con.emit('error', err) + }) + } else if (this.password !== null) { + cb(msg) + } else { + pgPass(this.connectionParameters, function (pass) { + if (undefined !== pass) { + this.connectionParameters.password = this.password = pass + } + cb(msg) + }) + } + } + } + + handleAuthenticationCleartextPassword(msg) { + this._checkPgPass(() => { + this.connection.password(this.password) }) + } - // delegate dataRow to active query - con.on('dataRow', function (msg) { - self.activeQuery.handleDataRow(msg) + handleAuthenticationMD5Password(msg) { + this._checkPgPass((msg) => { + const hashedPassword = utils.postgresMd5PasswordHash(this.user, this.password, msg.salt) + this.connection.password(hashedPassword) }) + } - // delegate portalSuspended to active query - // eslint-disable-next-line no-unused-vars - con.on('portalSuspended', function (msg) { - self.activeQuery.handlePortalSuspended(con) + handleAuthenticationSASL(msg) { + this._checkPgPass((msg) => { + this.saslSession = sasl.startSession(msg.mechanisms) + const con = this.connection + con.sendSASLInitialResponseMessage(saslSession.mechanism, saslSession.response) }) + } + handleAuthenticationSASLContinue(msg) { + const { saslSession } = this + sasl.continueSession(saslSession, self.password, msg.data) + con.sendSCRAMClientFinalMessage(saslSession.response) + } + + handleAuthenticationSASLFinal(msg) { + sasl.finalizeSession(this.saslSession, msg.data) + this.saslSession = null + } + + handleBackendKeyData(msg) { + this.processID = msg.processID + this.secretKey = msg.secretKey + } + + handleReadyForQuery(msg) { + const { activeQuery } = this + this.activeQuery = null + this.readyForQuery = true + if (activeQuery) { + activeQuery.handleReadyForQuery(this.connection) + } + this._pulseQueryQueue() + } + + handleRowDescription(msg) { + // delegate rowDescription to active query + this.activeQuery.handleRowDescription(msg) + } + + handleDataRow(msg) { + // delegate dataRow to active query + this.activeQuery.handleDataRow(msg) + } + + handlePortalSuspended(msg) { + // delegate portalSuspended to active query + this.activeQuery.handlePortalSuspended(this.connection) + } + + handleEmptyQuery(msg) { // delegate emptyQuery to active query - // eslint-disable-next-line no-unused-vars - con.on('emptyQuery', function (msg) { - self.activeQuery.handleEmptyQuery(con) - }) + this.activeQuery.handleEmptyQuery(this.connection) + } + handleCommandComplete(msg) { // delegate commandComplete to active query - con.on('commandComplete', function (msg) { - self.activeQuery.handleCommandComplete(msg, con) - }) + this.activeQuery.handleCommandComplete(msg, this.connection) + } + handleParseComplete(msg) { // if a prepared statement has a name and properly parses // we track that its already been executed so we don't parse // it again on the same client - // eslint-disable-next-line no-unused-vars - con.on('parseComplete', function (msg) { - if (self.activeQuery.name) { - con.parsedStatements[self.activeQuery.name] = self.activeQuery.text - } - }) - - con.on('copyInResponse', this.handleCopyInResponse.bind(this)) - con.on('copyData', this.handleCopyData.bind(this)) - con.on('notification', this.handleNotification.bind(this)) + if (this.activeQuery.name) { + this.connection.parsedStatements[this.activeQuery.name] = this.activeQuery.text + } } handleCopyInResponse(msg) { @@ -372,6 +377,10 @@ class Client extends EventEmitter { this.emit('notification', msg) } + handleNotice(msg) { + this.emit('notice', msg) + } + getStartupConf() { var params = this.connectionParameters From 0b424cfff18e338e3860496ad957a178fed1892f Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 15 Jul 2020 11:16:46 -0500 Subject: [PATCH 0688/1037] Move more functionality to methods --- packages/pg/lib/client.js | 74 +++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 31 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 2dbebe855..926fa6bba 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -95,9 +95,9 @@ class Client extends EventEmitter { } this._connecting = true - var connectionTimeoutHandle + this.connectionTimeoutHandle if (this._connectionTimeoutMillis > 0) { - connectionTimeoutHandle = setTimeout(() => { + this.connectionTimeoutHandle = setTimeout(() => { con._ending = true con.stream.destroy(new Error('timeout expired')) }, this._connectionTimeoutMillis) @@ -133,35 +133,11 @@ class Client extends EventEmitter { con.once('backendKeyData', this.handleBackendKeyData.bind(this)) this._connectionCallback = callback - const connectingErrorHandler = (err) => { - if (this._connectionError) { - return - } - this._connectionError = true - clearTimeout(connectionTimeoutHandle) - if (this._connectionCallback) { - return this._connectionCallback(err) - } - this.emit('error', err) - } - - const connectedErrorHandler = (err) => { - this._queryable = false - this._errorAllQueries(err) - this.emit('error', err) - } + const connectingErrorHandler = this.handleErrorWhileConnecting.bind(this) - const connectedErrorMessageHandler = (msg) => { - const activeQuery = this.activeQuery + const connectedErrorHandler = this.handleErrorWhileConnected.bind(this) - if (!activeQuery) { - connectedErrorHandler(msg) - return - } - - this.activeQuery = null - activeQuery.handleError(msg, con) - } + const connectedErrorMessageHandler = this.handleErrorMessage.bind(this) con.on('error', connectingErrorHandler) con.on('errorMessage', connectingErrorHandler) @@ -175,7 +151,7 @@ class Client extends EventEmitter { con.removeListener('errorMessage', connectingErrorHandler) con.on('error', connectedErrorHandler) con.on('errorMessage', connectedErrorMessageHandler) - clearTimeout(connectionTimeoutHandle) + clearTimeout(this.connectionTimeoutHandle) // process possible callback argument to Client#connect if (this._connectionCallback) { @@ -194,7 +170,7 @@ class Client extends EventEmitter { con.once('end', () => { const error = this._ending ? new Error('Connection terminated') : new Error('Connection terminated unexpectedly') - clearTimeout(connectionTimeoutHandle) + clearTimeout(this.connectionTimeoutHandle) this._errorAllQueries(error) if (!this._ending) { @@ -331,6 +307,42 @@ class Client extends EventEmitter { this._pulseQueryQueue() } + // if we receieve an error during the connection process we handle it here + handleErrorWhileConnecting(err) { + if (this._connectionError) { + // TODO(bmc): this is swallowing errors - we shouldn't do this + return + } + this._connectionError = true + clearTimeout(this.connectionTimeoutHandle) + if (this._connectionCallback) { + return this._connectionCallback(err) + } + this.emit('error', err) + } + + // if we're connected and we receive an error event from the connection + // this means the socket is dead - do a hard abort of all queries and emit + // the socket error on the client as well + handleErrorWhileConnected(err) { + this._queryable = false + this._errorAllQueries(err) + this.emit('error', err) + } + + // handle error messages from the postgres backend + handleErrorMessage(msg) { + const activeQuery = this.activeQuery + + if (!activeQuery) { + this.handleErrorWhileConnected(msg) + return + } + + this.activeQuery = null + activeQuery.handleError(msg, this.connection) + } + handleRowDescription(msg) { // delegate rowDescription to active query this.activeQuery.handleRowDescription(msg) From 63e15d15fab69fc769995ce6bf45a82175923919 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 15 Jul 2020 11:31:16 -0500 Subject: [PATCH 0689/1037] Refactor --- packages/pg/lib/client.js | 94 ++++++++++++++++++--------------------- 1 file changed, 43 insertions(+), 51 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 926fa6bba..7f1356e98 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -86,6 +86,8 @@ class Client extends EventEmitter { _connect(callback) { var self = this var con = this.connection + this._connectionCallback = callback + if (this._connecting || this._connected) { const err = new Error('Client has already been connected. You cannot reuse a client.') process.nextTick(() => { @@ -122,50 +124,7 @@ class Client extends EventEmitter { con.startup(self.getStartupConf()) }) - // password request handling - con.on('authenticationCleartextPassword', this.handleAuthenticationCleartextPassword.bind(this)) - // password request handling - con.on('authenticationMD5Password', this.handleAuthenticationMD5Password.bind(this)) - // password request handling (SASL) - con.on('authenticationSASL', this.handleAuthenticationSASL.bind(this)) - con.on('authenticationSASLContinue', this.handleAuthenticationSASLContinue.bind(this)) - con.on('authenticationSASLFinal', this.handleAuthenticationSASLFinal.bind(this)) - con.once('backendKeyData', this.handleBackendKeyData.bind(this)) - - this._connectionCallback = callback - const connectingErrorHandler = this.handleErrorWhileConnecting.bind(this) - - const connectedErrorHandler = this.handleErrorWhileConnected.bind(this) - - const connectedErrorMessageHandler = this.handleErrorMessage.bind(this) - - con.on('error', connectingErrorHandler) - con.on('errorMessage', connectingErrorHandler) - - // hook up query handling events to connection - // after the connection initially becomes ready for queries - con.once('readyForQuery', () => { - self._connecting = false - self._connected = true - con.removeListener('error', connectingErrorHandler) - con.removeListener('errorMessage', connectingErrorHandler) - con.on('error', connectedErrorHandler) - con.on('errorMessage', connectedErrorMessageHandler) - clearTimeout(this.connectionTimeoutHandle) - - // process possible callback argument to Client#connect - if (this._connectionCallback) { - this._connectionCallback(null, self) - // remove callback for proper error handling - // after the connect event - this._connectionCallback = null - } - self.emit('connect') - }) - - con.on('readyForQuery', this.handleReadyForQuery.bind(this)) - con.on('notice', this.handleNotice.bind(this)) - self._attachListeners(con) + this._attachListeners(con) con.once('end', () => { const error = this._ending ? new Error('Connection terminated') : new Error('Connection terminated unexpectedly') @@ -182,10 +141,10 @@ class Client extends EventEmitter { if (this._connectionCallback) { this._connectionCallback(error) } else { - connectedErrorHandler(error) + this.handleErrorWhileConnected(error) } } else if (!this._connectionError) { - connectedErrorHandler(error) + this.handleErrorWhileConnected(error) } } @@ -213,6 +172,19 @@ class Client extends EventEmitter { } _attachListeners(con) { + // password request handling + con.on('authenticationCleartextPassword', this.handleAuthenticationCleartextPassword.bind(this)) + // password request handling + con.on('authenticationMD5Password', this.handleAuthenticationMD5Password.bind(this)) + // password request handling (SASL) + con.on('authenticationSASL', this.handleAuthenticationSASL.bind(this)) + con.on('authenticationSASLContinue', this.handleAuthenticationSASLContinue.bind(this)) + con.on('authenticationSASLFinal', this.handleAuthenticationSASLFinal.bind(this)) + con.on('backendKeyData', this.handleBackendKeyData.bind(this)) + con.on('error', this.handleErrorWhileConnecting) + con.on('errorMessage', this.handleErrorMessage) + con.on('readyForQuery', this.handleReadyForQuery.bind(this)) + con.on('notice', this.handleNotice.bind(this)) con.on('rowDescription', this.handleRowDescription.bind(this)) con.on('dataRow', this.handleDataRow.bind(this)) con.on('portalSuspended', this.handlePortalSuspended.bind(this)) @@ -283,7 +255,7 @@ class Client extends EventEmitter { handleAuthenticationSASLContinue(msg) { const { saslSession } = this - sasl.continueSession(saslSession, self.password, msg.data) + sasl.continueSession(saslSession, this.password, msg.data) con.sendSCRAMClientFinalMessage(saslSession.response) } @@ -298,6 +270,23 @@ class Client extends EventEmitter { } handleReadyForQuery(msg) { + if (this._connecting) { + this._connecting = false + this._connected = true + const con = this.connection + con.removeListener('error', this.handleErrorWhileConnecting) + con.on('error', this.handleErrorWhileConnected) + clearTimeout(this.connectionTimeoutHandle) + + // process possible callback argument to Client#connect + if (this._connectionCallback) { + this._connectionCallback(null, this) + // remove callback for proper error handling + // after the connect event + this._connectionCallback = null + } + this.emit('connect') + } const { activeQuery } = this this.activeQuery = null this.readyForQuery = true @@ -307,8 +296,8 @@ class Client extends EventEmitter { this._pulseQueryQueue() } - // if we receieve an error during the connection process we handle it here - handleErrorWhileConnecting(err) { + // if we receieve an error event or error message during the connection process we handle it here + handleErrorWhileConnecting = (err) => { if (this._connectionError) { // TODO(bmc): this is swallowing errors - we shouldn't do this return @@ -324,14 +313,17 @@ class Client extends EventEmitter { // if we're connected and we receive an error event from the connection // this means the socket is dead - do a hard abort of all queries and emit // the socket error on the client as well - handleErrorWhileConnected(err) { + handleErrorWhileConnected = (err) => { this._queryable = false this._errorAllQueries(err) this.emit('error', err) } // handle error messages from the postgres backend - handleErrorMessage(msg) { + handleErrorMessage = (msg) => { + if (this._connecting) { + return this.handleErrorWhileConnecting(msg) + } const activeQuery = this.activeQuery if (!activeQuery) { From 9d1dce9c5ddb654d9ab5bd3a4f4027b9889348d7 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 15 Jul 2020 11:42:33 -0500 Subject: [PATCH 0690/1037] Mark handler methods as 'private' --- packages/pg/lib/client.js | 95 ++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 7f1356e98..1cac61f8b 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -141,10 +141,10 @@ class Client extends EventEmitter { if (this._connectionCallback) { this._connectionCallback(error) } else { - this.handleErrorWhileConnected(error) + this._handleErrorEvent(error) } } else if (!this._connectionError) { - this.handleErrorWhileConnected(error) + this._handleErrorEvent(error) } } @@ -173,27 +173,27 @@ class Client extends EventEmitter { _attachListeners(con) { // password request handling - con.on('authenticationCleartextPassword', this.handleAuthenticationCleartextPassword.bind(this)) + con.on('authenticationCleartextPassword', this._handleAuthCleartextPassword.bind(this)) // password request handling - con.on('authenticationMD5Password', this.handleAuthenticationMD5Password.bind(this)) + con.on('authenticationMD5Password', this._handleAuthMD5Password.bind(this)) // password request handling (SASL) - con.on('authenticationSASL', this.handleAuthenticationSASL.bind(this)) - con.on('authenticationSASLContinue', this.handleAuthenticationSASLContinue.bind(this)) - con.on('authenticationSASLFinal', this.handleAuthenticationSASLFinal.bind(this)) - con.on('backendKeyData', this.handleBackendKeyData.bind(this)) - con.on('error', this.handleErrorWhileConnecting) - con.on('errorMessage', this.handleErrorMessage) - con.on('readyForQuery', this.handleReadyForQuery.bind(this)) - con.on('notice', this.handleNotice.bind(this)) - con.on('rowDescription', this.handleRowDescription.bind(this)) - con.on('dataRow', this.handleDataRow.bind(this)) - con.on('portalSuspended', this.handlePortalSuspended.bind(this)) - con.on('emptyQuery', this.handleEmptyQuery.bind(this)) - con.on('commandComplete', this.handleCommandComplete.bind(this)) - con.on('parseComplete', this.handleParseComplete.bind(this)) - con.on('copyInResponse', this.handleCopyInResponse.bind(this)) - con.on('copyData', this.handleCopyData.bind(this)) - con.on('notification', this.handleNotification.bind(this)) + con.on('authenticationSASL', this._handleAuthSASL.bind(this)) + con.on('authenticationSASLContinue', this._handleAuthSASLContinue.bind(this)) + con.on('authenticationSASLFinal', this._handleAuthSASLFinal.bind(this)) + con.on('backendKeyData', this._handleBackendKeyData.bind(this)) + con.on('error', this._handleErrorEvent) + con.on('errorMessage', this._handleErrorMessage) + con.on('readyForQuery', this._handleReadyForQuery.bind(this)) + con.on('notice', this._handleNotice.bind(this)) + con.on('rowDescription', this._handleRowDescription.bind(this)) + con.on('dataRow', this._handleDataRow.bind(this)) + con.on('portalSuspended', this._handlePortalSuspended.bind(this)) + con.on('emptyQuery', this._handleEmptyQuery.bind(this)) + con.on('commandComplete', this._handleCommandComplete.bind(this)) + con.on('parseComplete', this._handleParseComplete.bind(this)) + con.on('copyInResponse', this._handleCopyInResponse.bind(this)) + con.on('copyData', this._handleCopyData.bind(this)) + con.on('notification', this._handleNotification.bind(this)) } // TODO(bmc): deprecate pgpass "built in" integration since this.password can be a function @@ -232,20 +232,20 @@ class Client extends EventEmitter { } } - handleAuthenticationCleartextPassword(msg) { + _handleAuthCleartextPassword(msg) { this._checkPgPass(() => { this.connection.password(this.password) }) } - handleAuthenticationMD5Password(msg) { + _handleAuthMD5Password(msg) { this._checkPgPass((msg) => { const hashedPassword = utils.postgresMd5PasswordHash(this.user, this.password, msg.salt) this.connection.password(hashedPassword) }) } - handleAuthenticationSASL(msg) { + _handleAuthSASL(msg) { this._checkPgPass((msg) => { this.saslSession = sasl.startSession(msg.mechanisms) const con = this.connection @@ -253,29 +253,26 @@ class Client extends EventEmitter { }) } - handleAuthenticationSASLContinue(msg) { + _handleAuthSASLContinue(msg) { const { saslSession } = this sasl.continueSession(saslSession, this.password, msg.data) con.sendSCRAMClientFinalMessage(saslSession.response) } - handleAuthenticationSASLFinal(msg) { + _handleAuthSASLFinal(msg) { sasl.finalizeSession(this.saslSession, msg.data) this.saslSession = null } - handleBackendKeyData(msg) { + _handleBackendKeyData(msg) { this.processID = msg.processID this.secretKey = msg.secretKey } - handleReadyForQuery(msg) { + _handleReadyForQuery(msg) { if (this._connecting) { this._connecting = false this._connected = true - const con = this.connection - con.removeListener('error', this.handleErrorWhileConnecting) - con.on('error', this.handleErrorWhileConnected) clearTimeout(this.connectionTimeoutHandle) // process possible callback argument to Client#connect @@ -296,8 +293,9 @@ class Client extends EventEmitter { this._pulseQueryQueue() } - // if we receieve an error event or error message during the connection process we handle it here - handleErrorWhileConnecting = (err) => { + // if we receieve an error event or error message + // during the connection process we handle it here + _handleErrorWhileConnecting = (err) => { if (this._connectionError) { // TODO(bmc): this is swallowing errors - we shouldn't do this return @@ -313,21 +311,24 @@ class Client extends EventEmitter { // if we're connected and we receive an error event from the connection // this means the socket is dead - do a hard abort of all queries and emit // the socket error on the client as well - handleErrorWhileConnected = (err) => { + _handleErrorEvent = (err) => { + if (this._connecting) { + return this._handleErrorWhileConnecting(err) + } this._queryable = false this._errorAllQueries(err) this.emit('error', err) } // handle error messages from the postgres backend - handleErrorMessage = (msg) => { + _handleErrorMessage = (msg) => { if (this._connecting) { - return this.handleErrorWhileConnecting(msg) + return this._handleErrorWhileConnecting(msg) } const activeQuery = this.activeQuery if (!activeQuery) { - this.handleErrorWhileConnected(msg) + this._handleErrorEvent(msg) return } @@ -335,32 +336,32 @@ class Client extends EventEmitter { activeQuery.handleError(msg, this.connection) } - handleRowDescription(msg) { + _handleRowDescription(msg) { // delegate rowDescription to active query this.activeQuery.handleRowDescription(msg) } - handleDataRow(msg) { + _handleDataRow(msg) { // delegate dataRow to active query this.activeQuery.handleDataRow(msg) } - handlePortalSuspended(msg) { + _handlePortalSuspended(msg) { // delegate portalSuspended to active query this.activeQuery.handlePortalSuspended(this.connection) } - handleEmptyQuery(msg) { + _handleEmptyQuery(msg) { // delegate emptyQuery to active query this.activeQuery.handleEmptyQuery(this.connection) } - handleCommandComplete(msg) { + _handleCommandComplete(msg) { // delegate commandComplete to active query this.activeQuery.handleCommandComplete(msg, this.connection) } - handleParseComplete(msg) { + _handleParseComplete(msg) { // if a prepared statement has a name and properly parses // we track that its already been executed so we don't parse // it again on the same client @@ -369,19 +370,19 @@ class Client extends EventEmitter { } } - handleCopyInResponse(msg) { + _handleCopyInResponse(msg) { this.activeQuery.handleCopyInResponse(this.connection) } - handleCopyData(msg) { + _handleCopyData(msg) { this.activeQuery.handleCopyData(msg, this.connection) } - handleNotification(msg) { + _handleNotification(msg) { this.emit('notification', msg) } - handleNotice(msg) { + _handleNotice(msg) { this.emit('notice', msg) } From 5ba7e3fb48f70ac749aea0d1ffa0cfbd45fec6e2 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 15 Jul 2020 11:49:54 -0500 Subject: [PATCH 0691/1037] Refactor connection to class --- packages/pg/lib/connection.js | 332 +++++++++++++++++----------------- 1 file changed, 166 insertions(+), 166 deletions(-) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 65867026d..0aa3c0969 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -13,201 +13,201 @@ var util = require('util') const { parse, serialize } = require('pg-protocol') -// TODO(bmc) support binary mode at some point -var Connection = function (config) { - EventEmitter.call(this) - config = config || {} - this.stream = config.stream || new net.Socket() - this._keepAlive = config.keepAlive - this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis - this.lastBuffer = false - this.parsedStatements = {} - this.ssl = config.ssl || false - this._ending = false - this._emitMessage = false - var self = this - this.on('newListener', function (eventName) { - if (eventName === 'message') { - self._emitMessage = true - } - }) -} - -util.inherits(Connection, EventEmitter) - -Connection.prototype.connect = function (port, host) { - var self = this - - this._connecting = true - this.stream.setNoDelay(true) - this.stream.connect(port, host) +const flushBuffer = serialize.flush() +const syncBuffer = serialize.sync() +const endBuffer = serialize.end() - this.stream.once('connect', function () { - if (self._keepAlive) { - self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis) - } - self.emit('connect') - }) +// TODO(bmc) support binary mode at some point +class Connection extends EventEmitter { + constructor(config) { + super() + config = config || {} + this.stream = config.stream || new net.Socket() + this._keepAlive = config.keepAlive + this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis + this.lastBuffer = false + this.parsedStatements = {} + this.ssl = config.ssl || false + this._ending = false + this._emitMessage = false + var self = this + this.on('newListener', function (eventName) { + if (eventName === 'message') { + self._emitMessage = true + } + }) + } - const reportStreamError = function (error) { - // errors about disconnections should be ignored during disconnect - if (self._ending && (error.code === 'ECONNRESET' || error.code === 'EPIPE')) { - return - } - self.emit('error', error) - } - this.stream.on('error', reportStreamError) - - this.stream.on('close', function () { - self.emit('end') - }) - - if (!this.ssl) { - return this.attachListeners(this.stream) - } - - this.stream.once('data', function (buffer) { - var responseCode = buffer.toString('utf8') - switch (responseCode) { - case 'S': // Server supports SSL connections, continue with a secure connection - break - case 'N': // Server does not support SSL connections - self.stream.end() - return self.emit('error', new Error('The server does not support SSL connections')) - default: - // Any other response byte, including 'E' (ErrorResponse) indicating a server error - self.stream.end() - return self.emit('error', new Error('There was an error establishing an SSL connection')) + connect(port, host) { + var self = this + + this._connecting = true + this.stream.setNoDelay(true) + this.stream.connect(port, host) + + this.stream.once('connect', function () { + if (self._keepAlive) { + self.stream.setKeepAlive(true, self._keepAliveInitialDelayMillis) + } + self.emit('connect') + }) + + const reportStreamError = function (error) { + // errors about disconnections should be ignored during disconnect + if (self._ending && (error.code === 'ECONNRESET' || error.code === 'EPIPE')) { + return + } + self.emit('error', error) } - var tls = require('tls') - const options = Object.assign( - { - socket: self.stream, - }, - self.ssl - ) - if (net.isIP(host) === 0) { - options.servername = host - } - self.stream = tls.connect(options) - self.attachListeners(self.stream) - self.stream.on('error', reportStreamError) + this.stream.on('error', reportStreamError) - self.emit('sslconnect') - }) -} + this.stream.on('close', function () { + self.emit('end') + }) -Connection.prototype.attachListeners = function (stream) { - stream.on('end', () => { - this.emit('end') - }) - parse(stream, (msg) => { - var eventName = msg.name === 'error' ? 'errorMessage' : msg.name - if (this._emitMessage) { - this.emit('message', msg) + if (!this.ssl) { + return this.attachListeners(this.stream) } - this.emit(eventName, msg) - }) -} -Connection.prototype.requestSsl = function () { - this.stream.write(serialize.requestSsl()) -} + this.stream.once('data', function (buffer) { + var responseCode = buffer.toString('utf8') + switch (responseCode) { + case 'S': // Server supports SSL connections, continue with a secure connection + break + case 'N': // Server does not support SSL connections + self.stream.end() + return self.emit('error', new Error('The server does not support SSL connections')) + default: + // Any other response byte, including 'E' (ErrorResponse) indicating a server error + self.stream.end() + return self.emit('error', new Error('There was an error establishing an SSL connection')) + } + var tls = require('tls') + const options = Object.assign( + { + socket: self.stream, + }, + self.ssl + ) + if (net.isIP(host) === 0) { + options.servername = host + } + self.stream = tls.connect(options) + self.attachListeners(self.stream) + self.stream.on('error', reportStreamError) + + self.emit('sslconnect') + }) + } -Connection.prototype.startup = function (config) { - this.stream.write(serialize.startup(config)) -} + attachListeners(stream) { + stream.on('end', () => { + this.emit('end') + }) + parse(stream, (msg) => { + var eventName = msg.name === 'error' ? 'errorMessage' : msg.name + if (this._emitMessage) { + this.emit('message', msg) + } + this.emit(eventName, msg) + }) + } -Connection.prototype.cancel = function (processID, secretKey) { - this._send(serialize.cancel(processID, secretKey)) -} + requestSsl() { + this.stream.write(serialize.requestSsl()) + } -Connection.prototype.password = function (password) { - this._send(serialize.password(password)) -} + startup(config) { + this.stream.write(serialize.startup(config)) + } -Connection.prototype.sendSASLInitialResponseMessage = function (mechanism, initialResponse) { - this._send(serialize.sendSASLInitialResponseMessage(mechanism, initialResponse)) -} + cancel(processID, secretKey) { + this._send(serialize.cancel(processID, secretKey)) + } -Connection.prototype.sendSCRAMClientFinalMessage = function (additionalData) { - this._send(serialize.sendSCRAMClientFinalMessage(additionalData)) -} + password(password) { + this._send(serialize.password(password)) + } -Connection.prototype._send = function (buffer) { - if (!this.stream.writable) { - return false + sendSASLInitialResponseMessage(mechanism, initialResponse) { + this._send(serialize.sendSASLInitialResponseMessage(mechanism, initialResponse)) } - return this.stream.write(buffer) -} -Connection.prototype.query = function (text) { - this._send(serialize.query(text)) -} + sendSCRAMClientFinalMessage(additionalData) { + this._send(serialize.sendSCRAMClientFinalMessage(additionalData)) + } -// send parse message -Connection.prototype.parse = function (query) { - this._send(serialize.parse(query)) -} + _send(buffer) { + if (!this.stream.writable) { + return false + } + return this.stream.write(buffer) + } -// send bind message -// "more" === true to buffer the message until flush() is called -Connection.prototype.bind = function (config) { - this._send(serialize.bind(config)) -} + query(text) { + this._send(serialize.query(text)) + } -// send execute message -// "more" === true to buffer the message until flush() is called -Connection.prototype.execute = function (config) { - this._send(serialize.execute(config)) -} + // send parse message + parse(query) { + this._send(serialize.parse(query)) + } -const flushBuffer = serialize.flush() -Connection.prototype.flush = function () { - if (this.stream.writable) { - this.stream.write(flushBuffer) + // send bind message + // "more" === true to buffer the message until flush() is called + bind(config) { + this._send(serialize.bind(config)) } -} -const syncBuffer = serialize.sync() -Connection.prototype.sync = function () { - this._ending = true - this._send(flushBuffer) - this._send(syncBuffer) -} + // send execute message + // "more" === true to buffer the message until flush() is called + execute(config) { + this._send(serialize.execute(config)) + } -const endBuffer = serialize.end() + flush() { + if (this.stream.writable) { + this.stream.write(flushBuffer) + } + } -Connection.prototype.end = function () { - // 0x58 = 'X' - this._ending = true - if (!this._connecting || !this.stream.writable) { - this.stream.end() - return + sync() { + this._ending = true + this._send(flushBuffer) + this._send(syncBuffer) } - return this.stream.write(endBuffer, () => { - this.stream.end() - }) -} -Connection.prototype.close = function (msg) { - this._send(serialize.close(msg)) -} + end() { + // 0x58 = 'X' + this._ending = true + if (!this._connecting || !this.stream.writable) { + this.stream.end() + return + } + return this.stream.write(endBuffer, () => { + this.stream.end() + }) + } -Connection.prototype.describe = function (msg) { - this._send(serialize.describe(msg)) -} + close(msg) { + this._send(serialize.close(msg)) + } -Connection.prototype.sendCopyFromChunk = function (chunk) { - this._send(serialize.copyData(chunk)) -} + describe(msg) { + this._send(serialize.describe(msg)) + } -Connection.prototype.endCopyFrom = function () { - this._send(serialize.copyDone()) -} + sendCopyFromChunk(chunk) { + this._send(serialize.copyData(chunk)) + } -Connection.prototype.sendCopyFail = function (msg) { - this._send(serialize.copyFail(msg)) + endCopyFrom() { + this._send(serialize.copyDone()) + } + + sendCopyFail(msg) { + this._send(serialize.copyFail(msg)) + } } module.exports = Connection From 9bf31060e162cd9f652ac63072a1dd6fd68e32f6 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 15 Jul 2020 12:22:13 -0500 Subject: [PATCH 0692/1037] Cleanup some dead code --- packages/pg/lib/connection.js | 2 -- packages/pg/lib/query.js | 55 ++++++++++++++--------------------- 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 0aa3c0969..2142a401b 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -154,13 +154,11 @@ class Connection extends EventEmitter { } // send bind message - // "more" === true to buffer the message until flush() is called bind(config) { this._send(serialize.bind(config)) } // send execute message - // "more" === true to buffer the message until flush() is called execute(config) { this._send(serialize.execute(config)) } diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index 2392b710e..37098ac82 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -176,30 +176,26 @@ class Query extends EventEmitter { } _getRows(connection, rows) { - connection.execute( - { - portal: this.portal, - rows: rows, - }, - true - ) + connection.execute({ + portal: this.portal, + rows: rows, + }) connection.flush() } + // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY prepare(connection) { // prepared statements need sync to be called after each command // complete or when an error is encountered this.isPreparedStatement = true + // TODO refactor this poor encapsulation if (!this.hasBeenParsed(connection)) { - connection.parse( - { - text: this.text, - name: this.name, - types: this.types, - }, - true - ) + connection.parse({ + text: this.text, + name: this.name, + types: this.types, + }) } if (this.values) { @@ -211,24 +207,17 @@ class Query extends EventEmitter { } } - // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY - connection.bind( - { - portal: this.portal, - statement: this.name, - values: this.values, - binary: this.binary, - }, - true - ) - - connection.describe( - { - type: 'P', - name: this.portal || '', - }, - true - ) + connection.bind({ + portal: this.portal, + statement: this.name, + values: this.values, + binary: this.binary, + }) + + connection.describe({ + type: 'P', + name: this.portal || '', + }) this._getRows(connection, this.rows) } From 966278a5ccbacca762bbebff6e7d9f06c14b8a59 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 15 Jul 2020 12:59:10 -0500 Subject: [PATCH 0693/1037] Instance bound methods are not supported in node 8 --- packages/pg/lib/client.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 1cac61f8b..600cf89fd 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -181,8 +181,8 @@ class Client extends EventEmitter { con.on('authenticationSASLContinue', this._handleAuthSASLContinue.bind(this)) con.on('authenticationSASLFinal', this._handleAuthSASLFinal.bind(this)) con.on('backendKeyData', this._handleBackendKeyData.bind(this)) - con.on('error', this._handleErrorEvent) - con.on('errorMessage', this._handleErrorMessage) + con.on('error', this._handleErrorEvent.bind(this)) + con.on('errorMessage', this._handleErrorMessage.bind(this)) con.on('readyForQuery', this._handleReadyForQuery.bind(this)) con.on('notice', this._handleNotice.bind(this)) con.on('rowDescription', this._handleRowDescription.bind(this)) @@ -295,7 +295,7 @@ class Client extends EventEmitter { // if we receieve an error event or error message // during the connection process we handle it here - _handleErrorWhileConnecting = (err) => { + _handleErrorWhileConnecting(err) { if (this._connectionError) { // TODO(bmc): this is swallowing errors - we shouldn't do this return @@ -311,7 +311,7 @@ class Client extends EventEmitter { // if we're connected and we receive an error event from the connection // this means the socket is dead - do a hard abort of all queries and emit // the socket error on the client as well - _handleErrorEvent = (err) => { + _handleErrorEvent(err) { if (this._connecting) { return this._handleErrorWhileConnecting(err) } @@ -321,7 +321,7 @@ class Client extends EventEmitter { } // handle error messages from the postgres backend - _handleErrorMessage = (msg) => { + _handleErrorMessage(msg) { if (this._connecting) { return this._handleErrorWhileConnecting(msg) } From 5425bc15d2c23caadaa2dcf30b636cde68bab8aa Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 15 Jul 2020 13:19:45 -0500 Subject: [PATCH 0694/1037] Fix untested pgpass code --- packages/pg/lib/client.js | 57 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 600cf89fd..842de57f9 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -199,36 +199,35 @@ class Client extends EventEmitter { // TODO(bmc): deprecate pgpass "built in" integration since this.password can be a function // it can be supplied by the user if required - this is a breaking change! _checkPgPass(cb) { - return function (msg) { - if (typeof this.password === 'function') { - this._Promise - .resolve() - .then(() => this.password()) - .then((pass) => { - if (pass !== undefined) { - if (typeof pass !== 'string') { - con.emit('error', new TypeError('Password must be a string')) - return - } - this.connectionParameters.password = this.password = pass - } else { - this.connectionParameters.password = this.password = null + const con = this.connection + if (typeof this.password === 'function') { + this._Promise + .resolve() + .then(() => this.password()) + .then((pass) => { + if (pass !== undefined) { + if (typeof pass !== 'string') { + con.emit('error', new TypeError('Password must be a string')) + return } - cb(msg) - }) - .catch((err) => { - con.emit('error', err) - }) - } else if (this.password !== null) { - cb(msg) - } else { - pgPass(this.connectionParameters, function (pass) { - if (undefined !== pass) { this.connectionParameters.password = this.password = pass + } else { + this.connectionParameters.password = this.password = null } - cb(msg) + cb() }) - } + .catch((err) => { + con.emit('error', err) + }) + } else if (this.password !== null) { + cb() + } else { + pgPass(this.connectionParameters, function (pass) { + if (undefined !== pass) { + this.connectionParameters.password = this.password = pass + } + cb() + }) } } @@ -239,14 +238,14 @@ class Client extends EventEmitter { } _handleAuthMD5Password(msg) { - this._checkPgPass((msg) => { + this._checkPgPass(() => { const hashedPassword = utils.postgresMd5PasswordHash(this.user, this.password, msg.salt) this.connection.password(hashedPassword) }) } - _handleAuthSASL(msg) { - this._checkPgPass((msg) => { + _handleAuthSASL() { + this._checkPgPass(() => { this.saslSession = sasl.startSession(msg.mechanisms) const con = this.connection con.sendSASLInitialResponseMessage(saslSession.mechanism, saslSession.response) From fdf13bac3476bcba581605cbb61028017d583fb2 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 15 Jul 2020 13:30:25 -0500 Subject: [PATCH 0695/1037] Fix msg not being passed for SASL --- packages/pg/lib/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 842de57f9..cf465c44b 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -244,7 +244,7 @@ class Client extends EventEmitter { }) } - _handleAuthSASL() { + _handleAuthSASL(msg) { this._checkPgPass(() => { this.saslSession = sasl.startSession(msg.mechanisms) const con = this.connection From 66d32c6f3fdf74d24e50bb1409d9ddab689e0aec Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 15 Jul 2020 13:38:34 -0500 Subject: [PATCH 0696/1037] Fix more SASL. Thank God for tests. --- packages/pg/lib/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index cf465c44b..ec1dd47c2 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -248,7 +248,7 @@ class Client extends EventEmitter { this._checkPgPass(() => { this.saslSession = sasl.startSession(msg.mechanisms) const con = this.connection - con.sendSASLInitialResponseMessage(saslSession.mechanism, saslSession.response) + con.sendSASLInitialResponseMessage(this.saslSession.mechanism, this.saslSession.response) }) } From 9ba4ebb80314fcc3dd752bdbaad472c79d9ffa50 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 15 Jul 2020 13:53:12 -0500 Subject: [PATCH 0697/1037] Fix SASL again --- packages/pg/lib/client.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index ec1dd47c2..bc91924e6 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -247,15 +247,13 @@ class Client extends EventEmitter { _handleAuthSASL(msg) { this._checkPgPass(() => { this.saslSession = sasl.startSession(msg.mechanisms) - const con = this.connection - con.sendSASLInitialResponseMessage(this.saslSession.mechanism, this.saslSession.response) + this.connection.sendSASLInitialResponseMessage(this.saslSession.mechanism, this.saslSession.response) }) } _handleAuthSASLContinue(msg) { - const { saslSession } = this - sasl.continueSession(saslSession, this.password, msg.data) - con.sendSCRAMClientFinalMessage(saslSession.response) + sasl.continueSession(this.saslSession, this.password, msg.data) + this.connection.sendSCRAMClientFinalMessage(this.saslSession.response) } _handleAuthSASLFinal(msg) { From 7b74392ce35ec1c986ffd513bade455727c7c412 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 19 Jul 2020 02:56:21 +0000 Subject: [PATCH 0698/1037] Bump lodash from 4.17.15 to 4.17.19 Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19) Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7bfd5878e..f64dfa14a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3611,9 +3611,9 @@ lodash.uniq@^4.5.0: integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: - version "4.17.15" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" - integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + version "4.17.19" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" + integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== log-driver@^1.2.7: version "1.2.7" From 692e418e0ff960e375d6fba457af456c4fa5dcaa Mon Sep 17 00:00:00 2001 From: Michael Chris Lopez Date: Tue, 21 Jul 2020 15:02:21 +0800 Subject: [PATCH 0699/1037] Fix documenation typo in README (#2291) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1fe69fa5f..522d67a9a 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ This repo is a monorepo which contains the core [pg](https://github.com/brianc/n - [pg-connection-string](https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string) -## Documenation +## Documentation Each package in this repo should have it's own readme more focused on how to develop/contribute. For overall documentation on the project and the related modules managed by this repo please see: From 1b022f8c5f61eccde8138aecd426844de6db9f75 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Sun, 26 Jul 2020 10:30:01 -0700 Subject: [PATCH 0700/1037] Remove accidentally duplicated methods Fixes #2293. --- packages/pg/lib/result.js | 73 --------------------------------------- 1 file changed, 73 deletions(-) diff --git a/packages/pg/lib/result.js b/packages/pg/lib/result.js index e1f6bea94..350609743 100644 --- a/packages/pg/lib/result.js +++ b/packages/pg/lib/result.js @@ -95,79 +95,6 @@ class Result { } } } - - // adds a command complete message - addCommandComplete(msg) { - var match - if (msg.text) { - // pure javascript - match = matchRegexp.exec(msg.text) - } else { - // native bindings - match = matchRegexp.exec(msg.command) - } - if (match) { - this.command = match[1] - if (match[3]) { - // COMMMAND OID ROWS - this.oid = parseInt(match[2], 10) - this.rowCount = parseInt(match[3], 10) - } else if (match[2]) { - // COMMAND ROWS - this.rowCount = parseInt(match[2], 10) - } - } - } - - _parseRowAsArray(rowData) { - var row = new Array(rowData.length) - for (var i = 0, len = rowData.length; i < len; i++) { - var rawValue = rowData[i] - if (rawValue !== null) { - row[i] = this._parsers[i](rawValue) - } else { - row[i] = null - } - } - return row - } - - parseRow(rowData) { - var row = {} - for (var i = 0, len = rowData.length; i < len; i++) { - var rawValue = rowData[i] - var field = this.fields[i].name - if (rawValue !== null) { - row[field] = this._parsers[i](rawValue) - } else { - row[field] = null - } - } - return row - } - - addRow(row) { - this.rows.push(row) - } - - addFields(fieldDescriptions) { - // clears field definitions - // multiple query statements in 1 action can result in multiple sets - // of rowDescriptions...eg: 'select NOW(); select 1::int;' - // you need to reset the fields - this.fields = fieldDescriptions - if (this.fields.length) { - this._parsers = new Array(fieldDescriptions.length) - } - for (var i = 0; i < fieldDescriptions.length; i++) { - var desc = fieldDescriptions[i] - if (this._types) { - this._parsers[i] = this._types.getTypeParser(desc.dataTypeID, desc.format || 'text') - } else { - this._parsers[i] = types.getTypeParser(desc.dataTypeID, desc.format || 'text') - } - } - } } module.exports = Result From 3edcbb784fde296311e16f8db665b20bfaf9ea8a Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Sun, 26 Jul 2020 20:54:43 -0700 Subject: [PATCH 0701/1037] Fix most SSL negotiation packet tests being ignored `tc` was only one variable and the tests are asynchronous, so every test was writing 'E'. --- packages/pg/test/unit/connection/error-tests.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/pg/test/unit/connection/error-tests.js b/packages/pg/test/unit/connection/error-tests.js index b9ccd8197..091c13e2c 100644 --- a/packages/pg/test/unit/connection/error-tests.js +++ b/packages/pg/test/unit/connection/error-tests.js @@ -58,8 +58,7 @@ var SSLNegotiationPacketTests = [ }, ] -for (var i = 0; i < SSLNegotiationPacketTests.length; i++) { - var tc = SSLNegotiationPacketTests[i] +for (const tc of SSLNegotiationPacketTests) { suite.test(tc.testName, function (done) { // our fake postgres server var socket From f4d123b09e7c2ec90e72b46a66011ceac5505a79 Mon Sep 17 00:00:00 2001 From: Christopher Young Date: Wed, 12 Aug 2020 07:22:34 -0700 Subject: [PATCH 0702/1037] Prevents bad ssl credentials from causing a crash Fixes: https://github.com/brianc/node-postgres/issues/2307 Fixes: https://github.com/brianc/node-postgres/issues/2004 --- packages/pg/lib/connection.js | 6 ++++- .../test/integration/gh-issues/2307-tests.js | 24 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 packages/pg/test/integration/gh-issues/2307-tests.js diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 1487dce87..6bc0952e0 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -85,7 +85,11 @@ class Connection extends EventEmitter { if (net.isIP(host) === 0) { options.servername = host } - self.stream = tls.connect(options) + try { + self.stream = tls.connect(options) + } catch (err) { + return self.emit('error', err) + } self.attachListeners(self.stream) self.stream.on('error', reportStreamError) diff --git a/packages/pg/test/integration/gh-issues/2307-tests.js b/packages/pg/test/integration/gh-issues/2307-tests.js new file mode 100644 index 000000000..d5f7c059d --- /dev/null +++ b/packages/pg/test/integration/gh-issues/2307-tests.js @@ -0,0 +1,24 @@ +'use strict' + +const pg = require('../../../lib') +const helper = require('../test-helper') + +const suite = new helper.Suite() + +suite.test('bad ssl credentials do not cause crash', (done) => { + const config = { + ssl: { + ca: 'invalid_value', + key: 'invalid_value', + cert: 'invalid_value', + }, + } + + const client = new pg.Client(config) + + client.connect((err) => { + assert(err) + client.end() + done() + }) +}) From 65156e7d24f0ad4250b34721e9b1b8e5221b1ac5 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 18 Aug 2020 09:03:38 -0500 Subject: [PATCH 0703/1037] Small readme updates & auto-formatting --- README.md | 72 +++++++++++++++++----------------- packages/pg-protocol/README.md | 3 ++ 2 files changed, 38 insertions(+), 37 deletions(-) create mode 100644 packages/pg-protocol/README.md diff --git a/README.md b/README.md index 522d67a9a..4b63c57b6 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ NPM version NPM downloads -Non-blocking PostgreSQL client for Node.js. Pure JavaScript and optional native libpq bindings. +Non-blocking PostgreSQL client for Node.js. Pure JavaScript and optional native libpq bindings. ## Monorepo @@ -16,35 +16,36 @@ This repo is a monorepo which contains the core [pg](https://github.com/brianc/n - [pg-cursor](https://github.com/brianc/node-postgres/tree/master/packages/pg-cursor) - [pg-query-stream](https://github.com/brianc/node-postgres/tree/master/packages/pg-query-stream) - [pg-connection-string](https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string) - +- [pg-protocol](https://github.com/brianc/node-postgres/tree/master/packages/pg-protocol) ## Documentation -Each package in this repo should have it's own readme more focused on how to develop/contribute. For overall documentation on the project and the related modules managed by this repo please see: +Each package in this repo should have it's own readme more focused on how to develop/contribute. For overall documentation on the project and the related modules managed by this repo please see: ### :star: [Documentation](https://node-postgres.com) :star: ### Features -* Pure JavaScript client and native libpq bindings share _the same API_ -* Connection pooling -* Extensible JS ↔ PostgreSQL data-type coercion -* Supported PostgreSQL features - * Parameterized queries - * Named statements with query plan caching - * Async notifications with `LISTEN/NOTIFY` - * Bulk import & export with `COPY TO/COPY FROM` +- Pure JavaScript client and native libpq bindings share _the same API_ +- Connection pooling +- Extensible JS ↔ PostgreSQL data-type coercion +- Supported PostgreSQL features + - Parameterized queries + - Named statements with query plan caching + - Async notifications with `LISTEN/NOTIFY` + - Bulk import & export with `COPY TO/COPY FROM` ### Extras -node-postgres is by design pretty light on abstractions. These are some handy modules we've been using over the years to complete the picture. +node-postgres is by design pretty light on abstractions. These are some handy modules we've been using over the years to complete the picture. The entire list can be found on our [wiki](https://github.com/brianc/node-postgres/wiki/Extras). ## Support -node-postgres is free software. If you encounter a bug with the library please open an issue on the [GitHub repo](https://github.com/brianc/node-postgres). If you have questions unanswered by the documentation please open an issue pointing out how the documentation was unclear & I will do my best to make it better! +node-postgres is free software. If you encounter a bug with the library please open an issue on the [GitHub repo](https://github.com/brianc/node-postgres). If you have questions unanswered by the documentation please open an issue pointing out how the documentation was unclear & I will do my best to make it better! When you open an issue please provide: + - version of Node - version of Postgres - smallest possible snippet of code to reproduce the problem @@ -56,10 +57,6 @@ You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) and these featured sponsors:
- - - - @@ -69,10 +66,11 @@ If you or your company are benefiting from node-postgres and would like to help ## Contributing -__:heart: contributions!__ +**:heart: contributions!** + +I will **happily** accept your pull request if it: -I will __happily__ accept your pull request if it: -- __has tests__ +- **has tests** - looks reasonable - does not break backwards compatibility @@ -94,20 +92,20 @@ The causes and solutions to common errors can be found among the [Frequently Ask Copyright (c) 2010-2020 Brian Carlson (brian.m.carlson@gmail.com) - 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. +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. diff --git a/packages/pg-protocol/README.md b/packages/pg-protocol/README.md new file mode 100644 index 000000000..905dfb522 --- /dev/null +++ b/packages/pg-protocol/README.md @@ -0,0 +1,3 @@ +# pg-protocol + +Low level postgres wire protocol parser and serailizer written in Typescript. Used by node-postgres. Needs more documentation. :smile: From 07ee1bad372cd458413bd35f01e70159f9974e04 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 18 Aug 2020 09:37:35 -0500 Subject: [PATCH 0704/1037] Bump version --- packages/pg-cursor/package.json | 4 ++-- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 00fbcaaa2..3aa596cb2 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.3.0", + "version": "2.3.1", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -17,6 +17,6 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.3.0" + "pg": "^8.3.1" } } diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 34009afca..7370fadc1 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.2.0", + "version": "3.2.1", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -26,12 +26,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.3.0", + "pg": "^8.3.1", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.3.0" + "pg-cursor": "^2.3.1" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index d60e9e4b1..89f3a31a9 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.3.0", + "version": "8.3.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From acfbafac82641ef909d9d6235d46d38378c67864 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 18 Aug 2020 09:38:12 -0500 Subject: [PATCH 0705/1037] Publish - pg-cursor@2.3.2 - pg-query-stream@3.2.2 - pg@8.3.2 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 3aa596cb2..067e40343 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.3.1", + "version": "2.3.2", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -17,6 +17,6 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.3.1" + "pg": "^8.3.2" } } diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 7370fadc1..545b658aa 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.2.1", + "version": "3.2.2", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -26,12 +26,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.3.1", + "pg": "^8.3.2", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.3.1" + "pg-cursor": "^2.3.2" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 89f3a31a9..0071a9b0d 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.3.1", + "version": "8.3.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From 0758b766aa04fecef24f0fd2f94bfcbea0481176 Mon Sep 17 00:00:00 2001 From: "Pimm \"de Chinchilla\" Hogeling" Date: Fri, 21 Aug 2020 16:18:43 +0200 Subject: [PATCH 0706/1037] Fix context (this) in _checkPgPass. --- packages/pg/lib/client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 72973c44f..3bc73f98b 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -215,7 +215,7 @@ class Client extends EventEmitter { } else if (this.password !== null) { cb() } else { - pgPass(this.connectionParameters, function (pass) { + pgPass(this.connectionParameters, (pass) => { if (undefined !== pass) { this.connectionParameters.password = this.password = pass } From 1f0d3d567f00a0fe18db7bf66f6b4295f4f7a564 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 26 Aug 2020 15:40:33 -0500 Subject: [PATCH 0707/1037] Add test for pgpass check function scope --- .../unit/client/cleartext-password-tests.js | 27 ++++++++++++------- packages/pg/test/unit/client/pgpass.file | 1 + 2 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 packages/pg/test/unit/client/pgpass.file diff --git a/packages/pg/test/unit/client/cleartext-password-tests.js b/packages/pg/test/unit/client/cleartext-password-tests.js index cd8dbb005..49db22d00 100644 --- a/packages/pg/test/unit/client/cleartext-password-tests.js +++ b/packages/pg/test/unit/client/cleartext-password-tests.js @@ -1,21 +1,30 @@ 'use strict' +const helper = require('./test-helper') const createClient = require('./test-helper').createClient -/* - * TODO: Add _some_ comments to explain what it is we're testing, and how the - * code-being-tested works behind the scenes. - */ - test('cleartext password authentication', function () { - var client = createClient() - client.password = '!' - client.connection.stream.packets = [] - client.connection.emit('authenticationCleartextPassword') test('responds with password', function () { + var client = createClient() + client.password = '!' + client.connection.stream.packets = [] + client.connection.emit('authenticationCleartextPassword') var packets = client.connection.stream.packets assert.lengthIs(packets, 1) var packet = packets[0] assert.equalBuffers(packet, [0x70, 0, 0, 0, 6, 33, 0]) }) + + test('does not crash with null password using pg-pass', function () { + process.env.PGPASSFILE = `${__dirname}/pgpass.file` + var client = new helper.Client({ + host: 'foo', + port: 5432, + database: 'bar', + user: 'baz', + stream: new MemoryStream(), + }) + client.connect() + client.connection.emit('authenticationCleartextPassword') + }) }) diff --git a/packages/pg/test/unit/client/pgpass.file b/packages/pg/test/unit/client/pgpass.file new file mode 100644 index 000000000..fa0cd41b6 --- /dev/null +++ b/packages/pg/test/unit/client/pgpass.file @@ -0,0 +1 @@ +foo:5432:bar:baz:quz From 95b5daadaade40ea343c0d3ad09ab230fa2ade4c Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 26 Aug 2020 15:59:37 -0500 Subject: [PATCH 0708/1037] Publish - pg-cursor@2.3.3 - pg-query-stream@3.2.3 - pg@8.3.3 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 067e40343..7a92f3062 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.3.2", + "version": "2.3.3", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -17,6 +17,6 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.3.2" + "pg": "^8.3.3" } } diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 545b658aa..a3531309c 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.2.2", + "version": "3.2.3", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -26,12 +26,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.3.2", + "pg": "^8.3.3", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.3.2" + "pg-cursor": "^2.3.3" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 0071a9b0d..9222219a3 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.3.2", + "version": "8.3.3", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From f0fc470d88b782607563040eb126455a7fbfb3b1 Mon Sep 17 00:00:00 2001 From: John Date: Fri, 4 Sep 2020 06:10:50 +0800 Subject: [PATCH 0709/1037] Update README.md (#2330) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4b63c57b6..695b44f48 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ This repo is a monorepo which contains the core [pg](https://github.com/brianc/n ## Documentation -Each package in this repo should have it's own readme more focused on how to develop/contribute. For overall documentation on the project and the related modules managed by this repo please see: +Each package in this repo should have its own readme more focused on how to develop/contribute. For overall documentation on the project and the related modules managed by this repo please see: ### :star: [Documentation](https://node-postgres.com) :star: From 6be3b9022f83efc721596cc41165afaa07bfceb0 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Thu, 10 Sep 2020 17:45:20 +0100 Subject: [PATCH 0710/1037] Add support for ?sslmode connection string param --- packages/pg-connection-string/index.js | 19 +++++++++ packages/pg-connection-string/test/parse.js | 46 +++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/packages/pg-connection-string/index.js b/packages/pg-connection-string/index.js index 65951c374..c07b146a9 100644 --- a/packages/pg-connection-string/index.js +++ b/packages/pg-connection-string/index.js @@ -81,6 +81,25 @@ function parse(str) { config.ssl.ca = fs.readFileSync(config.sslrootcert).toString() } + switch (config.sslmode) { + case 'disable': { + config.ssl = false + break + } + case 'prefer': + case 'require': + case 'verify-ca': + case 'verify-full': { + config.ssl = config.ssl || true + break + } + case 'no-verify': { + config.ssl = config.ssl || {} + config.ssl.rejectUnauthorized = false + break + } + } + return config } diff --git a/packages/pg-connection-string/test/parse.js b/packages/pg-connection-string/test/parse.js index 035b025d1..9a88f1d09 100644 --- a/packages/pg-connection-string/test/parse.js +++ b/packages/pg-connection-string/test/parse.js @@ -241,6 +241,52 @@ describe('parse', function () { }) }) + it('configuration parameter sslmode=no-verify', function () { + var connectionString = 'pg:///?sslmode=no-verify' + var subject = parse(connectionString) + subject.ssl.should.eql({ + rejectUnauthorized: false, + }) + }) + + it('configuration parameter sslmode=disable', function () { + var connectionString = 'pg:///?sslmode=disable' + var subject = parse(connectionString) + subject.ssl.should.eql(false) + }) + + it('configuration parameter sslmode=prefer', function () { + var connectionString = 'pg:///?sslmode=prefer' + var subject = parse(connectionString) + subject.ssl.should.eql(true) + }) + + it('configuration parameter sslmode=require', function () { + var connectionString = 'pg:///?sslmode=require' + var subject = parse(connectionString) + subject.ssl.should.eql(true) + }) + + it('configuration parameter sslmode=verify-ca', function () { + var connectionString = 'pg:///?sslmode=verify-ca' + var subject = parse(connectionString) + subject.ssl.should.eql(true) + }) + + it('configuration parameter sslmode=verify-full', function () { + var connectionString = 'pg:///?sslmode=verify-full' + var subject = parse(connectionString) + subject.ssl.should.eql(true) + }) + + it("configuration parameter sslmode=require doesn't overwrite sslrootcert=/path/to/ca", function () { + var connectionString = 'pg:///?sslrootcert=' + __dirname + '/example.ca&sslmode=require' + var subject = parse(connectionString) + subject.ssl.should.eql({ + ca: 'example ca\n', + }) + }) + it('allow other params like max, ...', function () { var subject = parse('pg://myhost/db?max=18&min=4') subject.max.should.equal('18') From 9cbea21587330155e2d88b25d50fdb9fe081af1d Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Thu, 10 Sep 2020 18:31:40 +0100 Subject: [PATCH 0711/1037] Solve issues caused by config.ssl = true --- packages/pg-connection-string/index.js | 4 +--- packages/pg-connection-string/test/parse.js | 8 ++++---- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/pg-connection-string/index.js b/packages/pg-connection-string/index.js index c07b146a9..995ff0684 100644 --- a/packages/pg-connection-string/index.js +++ b/packages/pg-connection-string/index.js @@ -65,7 +65,7 @@ function parse(str) { config.ssl = false } - if (config.sslcert || config.sslkey || config.sslrootcert) { + if (config.sslcert || config.sslkey || config.sslrootcert || config.sslmode) { config.ssl = {} } @@ -90,11 +90,9 @@ function parse(str) { case 'require': case 'verify-ca': case 'verify-full': { - config.ssl = config.ssl || true break } case 'no-verify': { - config.ssl = config.ssl || {} config.ssl.rejectUnauthorized = false break } diff --git a/packages/pg-connection-string/test/parse.js b/packages/pg-connection-string/test/parse.js index 9a88f1d09..910d26f7e 100644 --- a/packages/pg-connection-string/test/parse.js +++ b/packages/pg-connection-string/test/parse.js @@ -258,25 +258,25 @@ describe('parse', function () { it('configuration parameter sslmode=prefer', function () { var connectionString = 'pg:///?sslmode=prefer' var subject = parse(connectionString) - subject.ssl.should.eql(true) + subject.ssl.should.eql({}) }) it('configuration parameter sslmode=require', function () { var connectionString = 'pg:///?sslmode=require' var subject = parse(connectionString) - subject.ssl.should.eql(true) + subject.ssl.should.eql({}) }) it('configuration parameter sslmode=verify-ca', function () { var connectionString = 'pg:///?sslmode=verify-ca' var subject = parse(connectionString) - subject.ssl.should.eql(true) + subject.ssl.should.eql({}) }) it('configuration parameter sslmode=verify-full', function () { var connectionString = 'pg:///?sslmode=verify-full' var subject = parse(connectionString) - subject.ssl.should.eql(true) + subject.ssl.should.eql({}) }) it("configuration parameter sslmode=require doesn't overwrite sslrootcert=/path/to/ca", function () { From e421167d4631cf887960f44b477cafabffb2e7ee Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Thu, 17 Sep 2020 08:40:45 +0100 Subject: [PATCH 0712/1037] Add ssl=true into the test --- packages/pg-connection-string/test/parse.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/pg-connection-string/test/parse.js b/packages/pg-connection-string/test/parse.js index 910d26f7e..a0cd26385 100644 --- a/packages/pg-connection-string/test/parse.js +++ b/packages/pg-connection-string/test/parse.js @@ -279,8 +279,8 @@ describe('parse', function () { subject.ssl.should.eql({}) }) - it("configuration parameter sslmode=require doesn't overwrite sslrootcert=/path/to/ca", function () { - var connectionString = 'pg:///?sslrootcert=' + __dirname + '/example.ca&sslmode=require' + it('configuration parameter ssl=true and sslmode=require still work with sslrootcert=/path/to/ca', function () { + var connectionString = 'pg:///?ssl=true&sslrootcert=' + __dirname + '/example.ca&sslmode=require' var subject = parse(connectionString) subject.ssl.should.eql({ ca: 'example ca\n', From 58258430d52ee446721cc3e6611e26f8bcaa67f5 Mon Sep 17 00:00:00 2001 From: Tom Carrio Date: Sun, 4 Oct 2020 01:10:36 +0000 Subject: [PATCH 0713/1037] Public export of DatabaseError - Updated root exports of 'pg-protocol' to include DatabaseError Ref: #2340 --- packages/pg-protocol/src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/pg-protocol/src/index.ts b/packages/pg-protocol/src/index.ts index 486f79c86..00491ff7f 100644 --- a/packages/pg-protocol/src/index.ts +++ b/packages/pg-protocol/src/index.ts @@ -1,4 +1,4 @@ -import { BackendMessage } from './messages' +import { BackendMessage, DatabaseError } from './messages' import { serialize } from './serializer' import { Parser, MessageCallback } from './parser' @@ -8,4 +8,4 @@ export function parse(stream: NodeJS.ReadableStream, callback: MessageCallback): return new Promise((resolve) => stream.on('end', () => resolve())) } -export { serialize } +export { serialize, DatabaseError } From a02dfac5ad2e2abf0dc3a9817f953938acdc19b1 Mon Sep 17 00:00:00 2001 From: Bogdan Chadkin Date: Fri, 25 Sep 2020 10:44:13 +0300 Subject: [PATCH 0714/1037] Replace semver with optional peer dependencies See example https://github.com/sindresorhus/gulp-chown/blob/bb74168c957b3a94f122aafcecf7ebc87088ec46/package.json#L42-L49 This feature is supported by both npm and yarn. --- packages/pg/lib/native/client.js | 5 ----- packages/pg/package.json | 12 +++++++++--- yarn.lock | 5 ----- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index b2cc43479..6cf800d0e 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -3,16 +3,11 @@ // eslint-disable-next-line var Native = require('pg-native') var TypeOverrides = require('../type-overrides') -var semver = require('semver') var pkg = require('../../package.json') -var assert = require('assert') var EventEmitter = require('events').EventEmitter var util = require('util') var ConnectionParameters = require('../connection-parameters') -var msg = 'Version >= ' + pkg.minNativeVersion + ' of pg-native required.' -assert(semver.gte(Native.version, pkg.minNativeVersion), msg) - var NativeQuery = require('./query') var Client = (module.exports = function (config) { diff --git a/packages/pg/package.json b/packages/pg/package.json index 9222219a3..d7750deb0 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -25,8 +25,7 @@ "pg-pool": "^3.2.1", "pg-protocol": "^1.2.5", "pg-types": "^2.1.0", - "pgpass": "1.x", - "semver": "4.3.2" + "pgpass": "1.x" }, "devDependencies": { "async": "0.9.0", @@ -34,7 +33,14 @@ "co": "4.6.0", "pg-copy-streams": "0.3.0" }, - "minNativeVersion": "2.0.0", + "peerDependencies": { + "pg-native": ">=2.0.0" + }, + "peerDependenciesMeta": { + "pg-native": { + "optional": true + } + }, "scripts": { "test": "make test-all" }, diff --git a/yarn.lock b/yarn.lock index f64dfa14a..c673a5962 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5077,11 +5077,6 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.2.tgz#c7a07158a80bedd052355b770d82d6640f803be7" - integrity sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c= - semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" From c5445f028840bd2407ce74e9bd253cadbfc7e669 Mon Sep 17 00:00:00 2001 From: Benjie Gillam Date: Thu, 10 Sep 2020 17:26:21 +0100 Subject: [PATCH 0715/1037] Fix metadata for pg-connection-string --- packages/pg-connection-string/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index 9bf951d16..82724841a 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -22,9 +22,9 @@ "author": "Blaine Bublitz (http://iceddev.com/)", "license": "MIT", "bugs": { - "url": "https://github.com/iceddev/pg-connection-string/issues" + "url": "https://github.com/brianc/node-postgres/issues" }, - "homepage": "https://github.com/iceddev/pg-connection-string", + "homepage": "https://github.com/brianc/node-postgres/tree/master/packages/pg-connection-string", "devDependencies": { "chai": "^4.1.1", "coveralls": "^3.0.4", From 7649890bfafbf4dea890975a2c26114d8d16fe60 Mon Sep 17 00:00:00 2001 From: Brian C Date: Sun, 4 Oct 2020 13:52:54 -0500 Subject: [PATCH 0716/1037] Update SPONSORS.md --- SPONSORS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SPONSORS.md b/SPONSORS.md index d01c1090d..a11b2b55d 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -31,3 +31,4 @@ node-postgres is made possible by the helpful contributors from the community as - Raul Murray - Simple Analytics - Trevor Linton +- Ian Walter From da2bb859873d25a37343a5b9238cc018ce026179 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 12 Sep 2020 12:22:33 +0000 Subject: [PATCH 0717/1037] Bump node-fetch from 2.6.0 to 2.6.1 Bumps [node-fetch](https://github.com/bitinn/node-fetch) from 2.6.0 to 2.6.1. - [Release notes](https://github.com/bitinn/node-fetch/releases) - [Changelog](https://github.com/node-fetch/node-fetch/blob/master/docs/CHANGELOG.md) - [Commits](https://github.com/bitinn/node-fetch/compare/v2.6.0...v2.6.1) Signed-off-by: dependabot[bot] --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index c673a5962..83bdd4f6d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4039,9 +4039,9 @@ node-fetch-npm@^2.0.2: safe-buffer "^5.1.1" node-fetch@^2.3.0, node-fetch@^2.5.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" - integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== node-gyp@^5.0.2: version "5.0.7" From 125a2686e81f6c7d0892bc65289bc4ef4e3d9986 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 4 Oct 2020 14:26:04 -0500 Subject: [PATCH 0718/1037] Update changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dabeb479..b62cc0084 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### pg@8.4.0 + +- Switch to optional peer dependencies & remove [semver](https://github.com/brianc/node-postgres/commit/a02dfac5ad2e2abf0dc3a9817f953938acdc19b1) package which has been a small thorn in the side of a few users. +- Export `DatabaseError` from [pg-protocol](https://github.com/brianc/node-postgres/commit/58258430d52ee446721cc3e6611e26f8bcaa67f5). +- Add support for `ssl-mode` in the [connection string](https://github.com/brianc/node-postgres/commit/6be3b9022f83efc721596cc41165afaa07bfceb0). + ### pg@8.3.0 - Support passing a [string of command line options flags](https://github.com/brianc/node-postgres/pull/2216) via the `{ options: string }` field on client/pool config. From 7ffe68eba056b9a6d0fa88f928aa85e768c28838 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Sun, 4 Oct 2020 14:26:29 -0500 Subject: [PATCH 0719/1037] Publish - pg-connection-string@2.4.0 - pg-cursor@2.4.0 - pg-protocol@1.3.0 - pg-query-stream@3.3.0 - pg@8.4.0 --- packages/pg-connection-string/package.json | 2 +- packages/pg-cursor/package.json | 4 ++-- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index 82724841a..e8ea95a1f 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "2.3.0", + "version": "2.4.0", "description": "Functions for dealing with a PostgresSQL connection string", "main": "./index.js", "types": "./index.d.ts", diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 7a92f3062..49922a49b 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.3.3", + "version": "2.4.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -17,6 +17,6 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.3.3" + "pg": "^8.4.0" } } diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 0a65e77d9..3ad45e4cb 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.2.5", + "version": "1.3.0", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index a3531309c..130edc58d 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.2.3", + "version": "3.3.0", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -26,12 +26,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.3.3", + "pg": "^8.4.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.3.3" + "pg-cursor": "^2.4.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index d7750deb0..4741b16d5 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.3.3", + "version": "8.4.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -21,9 +21,9 @@ "dependencies": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-connection-string": "^2.3.0", + "pg-connection-string": "^2.4.0", "pg-pool": "^3.2.1", - "pg-protocol": "^1.2.5", + "pg-protocol": "^1.3.0", "pg-types": "^2.1.0", "pgpass": "1.x" }, From 9c678e108c4ef73187d16bd7b6fae8cd71fe9895 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Wed, 7 Oct 2020 14:50:12 -0500 Subject: [PATCH 0720/1037] Fix double-sync crash on postgres 9.x --- packages/pg/lib/query.js | 15 +++++++++++--- .../test/integration/gh-issues/1105-tests.js | 20 +++++++++++++++++++ .../test/integration/gh-issues/2085-tests.js | 4 ++++ 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 packages/pg/test/integration/gh-issues/1105-tests.js diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index 9cd0dab10..26d0aa614 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -31,6 +31,7 @@ class Query extends EventEmitter { this.isPreparedStatement = false this._canceledDueToError = false this._promise = null + this._hasSentSync = false } requiresPreparation() { @@ -100,7 +101,8 @@ class Query extends EventEmitter { this._checkForMultirow() this._result.addCommandComplete(msg) // need to sync after each command complete of a prepared statement - if (this.isPreparedStatement) { + if (this.isPreparedStatement && !this._hasSentSync) { + this._hasSentSync = true con.sync() } } @@ -109,7 +111,8 @@ class Query extends EventEmitter { // the backend will send an emptyQuery message but *not* a command complete message // execution on the connection will hang until the backend receives a sync message handleEmptyQuery(con) { - if (this.isPreparedStatement) { + if (this.isPreparedStatement && !this._hasSentSync) { + this._hasSentSync = true con.sync() } } @@ -126,7 +129,13 @@ class Query extends EventEmitter { handleError(err, connection) { // need to sync after error during a prepared statement - if (this.isPreparedStatement) { + // in postgres 9.6 the backend sends both a command complete and error response + // to a query which has timed out on rare, random occasions. If we send sync twice we will receive + // to 'readyForQuery' events. I think this might be a bug in postgres 9.6, but I'm not sure... + // the docs here: https://www.postgresql.org/docs/9.6/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY + // say "Therefore, an Execute phase is always terminated by the appearance of exactly one of these messages: CommandComplete, EmptyQueryResponse (if the portal was created from an empty query string), ErrorResponse, or PortalSuspended." + if (this.isPreparedStatement && !this._hasSentSync) { + this._hasSentSync = true connection.sync() } if (this._canceledDueToError) { diff --git a/packages/pg/test/integration/gh-issues/1105-tests.js b/packages/pg/test/integration/gh-issues/1105-tests.js new file mode 100644 index 000000000..2a36d6990 --- /dev/null +++ b/packages/pg/test/integration/gh-issues/1105-tests.js @@ -0,0 +1,20 @@ +const pg = require('../../../lib') +const helper = require('../test-helper') +const suite = new helper.Suite() + +suite.testAsync('timeout causing query crashes', async () => { + const client = new helper.Client() + await client.connect() + await client.query('CREATE TEMP TABLE foobar( name TEXT NOT NULL, id SERIAL)') + client.query('BEGIN') + await client.query("SET LOCAL statement_timeout TO '1ms'") + let count = 0 + while (count++ < 5000) { + try { + await client.query('INSERT INTO foobar(name) VALUES ($1)', [Math.random() * 1000 + '']) + } catch (e) { + await client.query('ROLLBACK') + } + } + await client.end() +}) diff --git a/packages/pg/test/integration/gh-issues/2085-tests.js b/packages/pg/test/integration/gh-issues/2085-tests.js index 23fd71d07..d65b5fdc2 100644 --- a/packages/pg/test/integration/gh-issues/2085-tests.js +++ b/packages/pg/test/integration/gh-issues/2085-tests.js @@ -4,6 +4,10 @@ var assert = require('assert') const suite = new helper.Suite() +if (process.env.PGTESTNOSSL) { + return +} + suite.testAsync('it should connect over ssl', async () => { const ssl = helper.args.native ? 'require' From 17e7e9ed3d9037fcd57627653c8bb7089deb1969 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 8 Oct 2020 10:02:26 -0500 Subject: [PATCH 0721/1037] Remove fix to fail tests --- packages/pg/lib/query.js | 52 +++++++++++++++++++--------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index 26d0aa614..824dee4ee 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -97,24 +97,33 @@ class Query extends EventEmitter { } } - handleCommandComplete(msg, con) { + handleCommandComplete(msg, connection) { this._checkForMultirow() this._result.addCommandComplete(msg) // need to sync after each command complete of a prepared statement - if (this.isPreparedStatement && !this._hasSentSync) { - this._hasSentSync = true - con.sync() - } + this.maybeSync(connection) } // if a named prepared statement is created with empty query text // the backend will send an emptyQuery message but *not* a command complete message // execution on the connection will hang until the backend receives a sync message - handleEmptyQuery(con) { - if (this.isPreparedStatement && !this._hasSentSync) { - this._hasSentSync = true - con.sync() + handleEmptyQuery(connection) { + this.maybeSync(connection) + } + + handleError(err, connection) { + // need to sync after error during a prepared statement + this.maybeSync(connection) + if (this._canceledDueToError) { + err = this._canceledDueToError + this._canceledDueToError = false + } + // if callback supplied do not emit error event as uncaught error + // events will bubble up to node process + if (this.callback) { + return this.callback(err) } + this.emit('error', err) } handleReadyForQuery(con) { @@ -127,27 +136,16 @@ class Query extends EventEmitter { this.emit('end', this._results) } - handleError(err, connection) { - // need to sync after error during a prepared statement - // in postgres 9.6 the backend sends both a command complete and error response - // to a query which has timed out on rare, random occasions. If we send sync twice we will receive - // to 'readyForQuery' events. I think this might be a bug in postgres 9.6, but I'm not sure... - // the docs here: https://www.postgresql.org/docs/9.6/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY - // say "Therefore, an Execute phase is always terminated by the appearance of exactly one of these messages: CommandComplete, EmptyQueryResponse (if the portal was created from an empty query string), ErrorResponse, or PortalSuspended." - if (this.isPreparedStatement && !this._hasSentSync) { + // in postgres 9.6 the backend sends both a command complete and error response + // to a query which has timed out on rare, random occasions. If we send sync twice we will receive + // to 'readyForQuery' events. I think this might be a bug in postgres 9.6, but I'm not sure... + // the docs here: https://www.postgresql.org/docs/9.6/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY + // say "Therefore, an Execute phase is always terminated by the appearance of exactly one of these messages: CommandComplete, EmptyQueryResponse (if the portal was created from an empty query string), ErrorResponse, or PortalSuspended." + maybeSync(connection) { + if (this.isPreparedStatement) { this._hasSentSync = true connection.sync() } - if (this._canceledDueToError) { - err = this._canceledDueToError - this._canceledDueToError = false - } - // if callback supplied do not emit error event as uncaught error - // events will bubble up to node process - if (this.callback) { - return this.callback(err) - } - this.emit('error', err) } submit(connection) { From f55d879c52f01a288686626a216b27b65498cc99 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 8 Oct 2020 10:37:00 -0500 Subject: [PATCH 0722/1037] Apply fix --- packages/pg/lib/query.js | 2 +- packages/pg/test/integration/gh-issues/1105-tests.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index 824dee4ee..514185ebe 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -142,7 +142,7 @@ class Query extends EventEmitter { // the docs here: https://www.postgresql.org/docs/9.6/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY // say "Therefore, an Execute phase is always terminated by the appearance of exactly one of these messages: CommandComplete, EmptyQueryResponse (if the portal was created from an empty query string), ErrorResponse, or PortalSuspended." maybeSync(connection) { - if (this.isPreparedStatement) { + if (this.isPreparedStatement && !this._hasSentSync) { this._hasSentSync = true connection.sync() } diff --git a/packages/pg/test/integration/gh-issues/1105-tests.js b/packages/pg/test/integration/gh-issues/1105-tests.js index 2a36d6990..d9885f8a7 100644 --- a/packages/pg/test/integration/gh-issues/1105-tests.js +++ b/packages/pg/test/integration/gh-issues/1105-tests.js @@ -6,7 +6,7 @@ suite.testAsync('timeout causing query crashes', async () => { const client = new helper.Client() await client.connect() await client.query('CREATE TEMP TABLE foobar( name TEXT NOT NULL, id SERIAL)') - client.query('BEGIN') + await client.query('BEGIN') await client.query("SET LOCAL statement_timeout TO '1ms'") let count = 0 while (count++ < 5000) { From b45051d72a96408a2c019d4e54490fba5f3270e3 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 8 Oct 2020 10:39:32 -0500 Subject: [PATCH 0723/1037] Update comments --- packages/pg/lib/query.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index 514185ebe..7214eaa30 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -136,11 +136,12 @@ class Query extends EventEmitter { this.emit('end', this._results) } - // in postgres 9.6 the backend sends both a command complete and error response - // to a query which has timed out on rare, random occasions. If we send sync twice we will receive - // to 'readyForQuery' events. I think this might be a bug in postgres 9.6, but I'm not sure... + // In postgres 9.x & 10.x the backend sends both a CommandComplete and ErrorResponse + // to the same query when it times out due to a statement_timeout on rare, random occasions. If we send sync twice we will receive + // to ReadyForQuery messages . I hink this might be a race condition in some versions of postgres, but I'm not sure... // the docs here: https://www.postgresql.org/docs/9.6/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY - // say "Therefore, an Execute phase is always terminated by the appearance of exactly one of these messages: CommandComplete, EmptyQueryResponse (if the portal was created from an empty query string), ErrorResponse, or PortalSuspended." + // say "Therefore, an Execute phase is always terminated by the appearance of exactly one of these messages: + // CommandComplete, EmptyQueryResponse (if the portal was created from an empty query string), ErrorResponse, or PortalSuspended." maybeSync(connection) { if (this.isPreparedStatement && !this._hasSentSync) { this._hasSentSync = true From d31486fb7c630ce0d10653ff731e8b563ba50af8 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 8 Oct 2020 13:22:53 -0500 Subject: [PATCH 0724/1037] Change when sync is sent during pipelining --- packages/pg/lib/query.js | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index 7214eaa30..b5cb5b6cc 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -101,19 +101,22 @@ class Query extends EventEmitter { this._checkForMultirow() this._result.addCommandComplete(msg) // need to sync after each command complete of a prepared statement - this.maybeSync(connection) + // if we were using a row count which results in multiple calls to _getRows + if (this.rows) { + this.maybeSync(connection) + } } // if a named prepared statement is created with empty query text // the backend will send an emptyQuery message but *not* a command complete message // execution on the connection will hang until the backend receives a sync message handleEmptyQuery(connection) { - this.maybeSync(connection) + // this.maybeSync(connection) } handleError(err, connection) { // need to sync after error during a prepared statement - this.maybeSync(connection) + // this.maybeSync(connection) if (this._canceledDueToError) { err = this._canceledDueToError this._canceledDueToError = false @@ -143,7 +146,7 @@ class Query extends EventEmitter { // say "Therefore, an Execute phase is always terminated by the appearance of exactly one of these messages: // CommandComplete, EmptyQueryResponse (if the portal was created from an empty query string), ErrorResponse, or PortalSuspended." maybeSync(connection) { - if (this.isPreparedStatement && !this._hasSentSync) { + if (this.isPreparedStatement) { this._hasSentSync = true connection.sync() } @@ -181,7 +184,11 @@ class Query extends EventEmitter { portal: this.portal, rows: rows, }) - connection.flush() + if (!rows) { + this.maybeSync(connection) + } else { + connection.flush() + } } // http://developer.postgresql.org/pgdocs/postgres/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY From dd3ce616d0fbdb92a7e146ecf4171bf3c1b3ea97 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 8 Oct 2020 13:35:57 -0500 Subject: [PATCH 0725/1037] Fixes based on postgres maintainer advice --- packages/pg/lib/query.js | 28 +++++++------------ .../client/prepared-statement-tests.js | 10 +++++++ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index b5cb5b6cc..4ae494c71 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -103,20 +103,22 @@ class Query extends EventEmitter { // need to sync after each command complete of a prepared statement // if we were using a row count which results in multiple calls to _getRows if (this.rows) { - this.maybeSync(connection) + connection.sync() } } // if a named prepared statement is created with empty query text // the backend will send an emptyQuery message but *not* a command complete message - // execution on the connection will hang until the backend receives a sync message + // since we pipeline sync immediately after execute we don't need to do anything here + // unless we have rows specified, in which case we did not pipeline the intial sync call handleEmptyQuery(connection) { - // this.maybeSync(connection) + if (this.rows) { + connection.sync() + } } handleError(err, connection) { // need to sync after error during a prepared statement - // this.maybeSync(connection) if (this._canceledDueToError) { err = this._canceledDueToError this._canceledDueToError = false @@ -139,19 +141,6 @@ class Query extends EventEmitter { this.emit('end', this._results) } - // In postgres 9.x & 10.x the backend sends both a CommandComplete and ErrorResponse - // to the same query when it times out due to a statement_timeout on rare, random occasions. If we send sync twice we will receive - // to ReadyForQuery messages . I hink this might be a race condition in some versions of postgres, but I'm not sure... - // the docs here: https://www.postgresql.org/docs/9.6/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY - // say "Therefore, an Execute phase is always terminated by the appearance of exactly one of these messages: - // CommandComplete, EmptyQueryResponse (if the portal was created from an empty query string), ErrorResponse, or PortalSuspended." - maybeSync(connection) { - if (this.isPreparedStatement) { - this._hasSentSync = true - connection.sync() - } - } - submit(connection) { if (typeof this.text !== 'string' && typeof this.name !== 'string') { return new Error('A query must have either text or a name. Supplying neither is unsupported.') @@ -184,9 +173,12 @@ class Query extends EventEmitter { portal: this.portal, rows: rows, }) + // if we're not reading pages of rows send the sync command + // to indicate the pipeline is finished if (!rows) { - this.maybeSync(connection) + connection.sync() } else { + // otherwise flush the call out to read more rows connection.flush() } } diff --git a/packages/pg/test/integration/client/prepared-statement-tests.js b/packages/pg/test/integration/client/prepared-statement-tests.js index 48d12f899..ebc1f7380 100644 --- a/packages/pg/test/integration/client/prepared-statement-tests.js +++ b/packages/pg/test/integration/client/prepared-statement-tests.js @@ -174,5 +174,15 @@ var suite = new helper.Suite() checkForResults(query) }) + suite.testAsync('with no data response and rows', async function () { + const result = await client.query({ + name: 'some insert', + text: '', + values: [], + rows: 1, + }) + assert.equal(result.rows.length, 0) + }) + suite.test('cleanup', () => client.end()) })() From d8681fc2cd1350731adec956367ff36aa1d67582 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 8 Oct 2020 13:56:59 -0500 Subject: [PATCH 0726/1037] Comments & cleanup --- packages/pg/lib/query.js | 1 - packages/pg/test/integration/gh-issues/2085-tests.js | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index 4ae494c71..3e3c5a640 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -31,7 +31,6 @@ class Query extends EventEmitter { this.isPreparedStatement = false this._canceledDueToError = false this._promise = null - this._hasSentSync = false } requiresPreparation() { diff --git a/packages/pg/test/integration/gh-issues/2085-tests.js b/packages/pg/test/integration/gh-issues/2085-tests.js index d65b5fdc2..2536bba82 100644 --- a/packages/pg/test/integration/gh-issues/2085-tests.js +++ b/packages/pg/test/integration/gh-issues/2085-tests.js @@ -4,6 +4,8 @@ var assert = require('assert') const suite = new helper.Suite() +// allow skipping of this test via env var for +// local testing when you don't have SSL set up if (process.env.PGTESTNOSSL) { return } From 36342c9a84b68123f666879a9f34ac319a44727a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Thu, 8 Oct 2020 15:53:16 -0500 Subject: [PATCH 0727/1037] Publish - pg-cursor@2.4.1 - pg-query-stream@3.3.1 - pg@8.4.1 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 49922a49b..d02defdaa 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.4.0", + "version": "2.4.1", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -17,6 +17,6 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.4.0" + "pg": "^8.4.1" } } diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 130edc58d..2d44c0e8a 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.3.0", + "version": "3.3.1", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -26,12 +26,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.4.0", + "pg": "^8.4.1", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.4.0" + "pg-cursor": "^2.4.1" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 4741b16d5..32ae91e6e 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.4.0", + "version": "8.4.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From fd2c3563a57f19ca49cefa6b1de999d9aaa9b5f5 Mon Sep 17 00:00:00 2001 From: Lewis Cowles Date: Wed, 5 Aug 2020 12:06:50 +0100 Subject: [PATCH 0728/1037] Security: simplify defineProperty non-enumerables * `password` already has this set, but was a little long considering we only want to override default of one property * `ssl.key` was showing up in tracebacks --- packages/pg-pool/index.js | 8 ++++++++ packages/pg/lib/client.js | 9 +++++++++ packages/pg/lib/connection-parameters.js | 5 +++++ 3 files changed, 22 insertions(+) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index eef490f91..cebcd9e4a 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -73,6 +73,14 @@ class Pool extends EventEmitter { value: options.password, }) } + if (options != null && options.ssl && options.ssl.key) { + // "hiding" the ssl->key so it doesn't show up in stack traces + // or if the client is console.logged + this.options.ssl.key = options.ssl.key + Object.defineProperty(this.options.ssl, 'key', { + enumerable: false, + }) + } this.options.max = this.options.max || this.options.poolSize || 10 this.options.maxUses = this.options.maxUses || Infinity diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 3bc73f98b..1e1e83374 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -57,6 +57,15 @@ class Client extends EventEmitter { this.processID = null this.secretKey = null this.ssl = this.connectionParameters.ssl || false + // As with Password, make SSL->Key (the private key) non-enumerable. + // It won't show up in stack traces + // or if the client is console.logged + if (this.ssl && this.ssl.key) { + Object.defineProperty(this.ssl, 'key', { + enumerable: false, + }) + } + this._connectionTimeoutMillis = c.connectionTimeoutMillis || 0 } diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index 7f39cfaef..62bee8c85 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -84,6 +84,11 @@ class ConnectionParameters { if (this.ssl === 'no-verify') { this.ssl = { rejectUnauthorized: false } } + if (this.ssl && this.ssl.key) { + Object.defineProperty(this.ssl, 'key', { + enumerable: false, + }) + } this.client_encoding = val('client_encoding', config) this.replication = val('replication', config) From e82137e6d3fcb0a84e90e0107a3606085da73806 Mon Sep 17 00:00:00 2001 From: Lewis Cowles Date: Wed, 5 Aug 2020 17:04:27 +0100 Subject: [PATCH 0729/1037] Tests --- .../test/integration/gh-issues/2303-tests.js | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 packages/pg/test/integration/gh-issues/2303-tests.js diff --git a/packages/pg/test/integration/gh-issues/2303-tests.js b/packages/pg/test/integration/gh-issues/2303-tests.js new file mode 100644 index 000000000..7496a6f6c --- /dev/null +++ b/packages/pg/test/integration/gh-issues/2303-tests.js @@ -0,0 +1,47 @@ +'use strict' +const helper = require('./../test-helper') +const assert = require('assert') +const util = require('util') + +const suite = new helper.Suite() + +const secret_value = 'FAIL THIS TEST' + +suite.test('SSL Key should not exist in toString() output', () => { + const pool = new helper.pg.Pool({ ssl: { key: secret_value } }) + const client = new helper.pg.Client({ ssl: { key: secret_value } }) + assert(pool.toString().indexOf(secret_value) === -1) + assert(client.toString().indexOf(secret_value) === -1) +}) + +suite.test('SSL Key should not exist in util.inspect output', () => { + const pool = new helper.pg.Pool({ ssl: { key: secret_value } }) + const client = new helper.pg.Client({ ssl: { key: secret_value } }) + const depth = 20 + assert(util.inspect(pool, { depth }).indexOf(secret_value) === -1) + assert(util.inspect(client, { depth }).indexOf(secret_value) === -1) +}) + +suite.test('SSL Key should not exist in json.stringfy output', () => { + const pool = new helper.pg.Pool({ ssl: { key: secret_value } }) + const client = new helper.pg.Client({ ssl: { key: secret_value } }) + const depth = 20 + assert(JSON.stringify(pool).indexOf(secret_value) === -1) + assert(JSON.stringify(client).indexOf(secret_value) === -1) +}) + +suite.test('SSL Key should exist for direct access', () => { + const pool = new helper.pg.Pool({ ssl: { key: secret_value } }) + const client = new helper.pg.Client({ ssl: { key: secret_value } }) + assert(pool.options.ssl.key === secret_value) + assert(client.connectionParameters.ssl.key === secret_value) +}) + +suite.test('SSL Key should exist for direct access even when non-enumerable custom config', () => { + const config = { ssl: { key: secret_value } } + Object.defineProperty(config.ssl, 'key', { enumerable: false }) + const pool = new helper.pg.Pool(config) + const client = new helper.pg.Client(config) + assert(pool.options.ssl.key === secret_value) + assert(client.connectionParameters.ssl.key === secret_value) +}) From 80c500ffbffff8c2445dce44661e85590dc026e3 Mon Sep 17 00:00:00 2001 From: Lewis Cowles Date: Thu, 8 Oct 2020 09:31:59 +0100 Subject: [PATCH 0730/1037] Update packages/pg-pool/index.js Co-authored-by: Charmander <~@charmander.me> --- packages/pg-pool/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index cebcd9e4a..780f18652 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -76,7 +76,6 @@ class Pool extends EventEmitter { if (options != null && options.ssl && options.ssl.key) { // "hiding" the ssl->key so it doesn't show up in stack traces // or if the client is console.logged - this.options.ssl.key = options.ssl.key Object.defineProperty(this.options.ssl, 'key', { enumerable: false, }) From b6d69d5bc2eb7df4f4e04bc864b133b795c76a7f Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 26 Oct 2020 12:19:03 -0500 Subject: [PATCH 0731/1037] Publish - pg-cursor@2.4.2 - pg-pool@3.2.2 - pg-query-stream@3.3.2 - pg@8.4.2 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index d02defdaa..aa4ff624b 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.4.1", + "version": "2.4.2", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -17,6 +17,6 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.4.1" + "pg": "^8.4.2" } } diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 3acac307e..19ae81777 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.2.1", + "version": "3.2.2", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 2d44c0e8a..15da00837 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.3.1", + "version": "3.3.2", "description": "Postgres query result returned as readable stream", "main": "index.js", "scripts": { @@ -26,12 +26,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.4.1", + "pg": "^8.4.2", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4" }, "dependencies": { - "pg-cursor": "^2.4.1" + "pg-cursor": "^2.4.2" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 32ae91e6e..da38ab5c6 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.4.1", + "version": "8.4.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -22,7 +22,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "^2.4.0", - "pg-pool": "^3.2.1", + "pg-pool": "^3.2.2", "pg-protocol": "^1.3.0", "pg-types": "^2.1.0", "pgpass": "1.x" From 415bf090411644dc2844b4a86a7d38b3fae6667a Mon Sep 17 00:00:00 2001 From: Casey Foster Date: Fri, 9 Oct 2020 16:16:23 -0500 Subject: [PATCH 0732/1037] Remove console.error on pg-native module not found --- packages/pg/lib/index.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/pg/lib/index.js b/packages/pg/lib/index.js index fa6580559..47eca1fd0 100644 --- a/packages/pg/lib/index.js +++ b/packages/pg/lib/index.js @@ -40,9 +40,6 @@ if (typeof process.env.NODE_PG_FORCE_NATIVE !== 'undefined') { if (err.code !== 'MODULE_NOT_FOUND') { throw err } - /* eslint-disable no-console */ - console.error(err.message) - /* eslint-enable no-console */ } // overwrite module.exports.native so that getter is never called again From c22c2f0ebd780ffc0068864ecd05d52d87f0c887 Mon Sep 17 00:00:00 2001 From: chyzwar Date: Sun, 11 Oct 2020 16:13:02 +0200 Subject: [PATCH 0733/1037] chore(): update eslint, run lint only on latest lts --- .travis.yml | 6 + .yarnrc | 1 + package.json | 20 +- yarn.lock | 2102 +++++++++++++++++++++++++++++--------------------- 4 files changed, 1226 insertions(+), 903 deletions(-) create mode 100644 .yarnrc diff --git a/.travis.yml b/.travis.yml index 7987f761b..1ccd7e5b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,6 +57,12 @@ matrix: addons: postgresql: '9.6' + # only run lint on latest Node LTS + - node_js: lts/* + addons: + postgresql: '9.6' + script: yarn lint + # PostgreSQL 9.2 only works on precise - node_js: lts/carbon addons: diff --git a/.yarnrc b/.yarnrc new file mode 100644 index 000000000..0366cbd92 --- /dev/null +++ b/.yarnrc @@ -0,0 +1 @@ +--install.ignore-engines true \ No newline at end of file diff --git a/package.json b/package.json index 282ca9376..98e3c4e98 100644 --- a/package.json +++ b/package.json @@ -10,22 +10,20 @@ "packages/*" ], "scripts": { - "test": "yarn lint && yarn lerna exec yarn test", + "test": "yarn lerna exec yarn test", "build": "yarn lerna exec --scope pg-protocol yarn build", "pretest": "yarn build", - "lint": "if [ -x ./node_modules/.bin/prettier ]; then eslint '*/**/*.{js,ts,tsx}'; fi;" + "lint": "eslint '*/**/*.{js,ts,tsx}'" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^2.27.0", - "@typescript-eslint/parser": "^2.27.0", - "eslint": "^6.8.0", - "eslint-config-prettier": "^6.10.1", + "@typescript-eslint/eslint-plugin": "^4.4.0", + "@typescript-eslint/parser": "^4.4.0", + "eslint": "^7.11.0", + "eslint-config-prettier": "^6.12.0", "eslint-plugin-node": "^11.1.0", - "eslint-plugin-prettier": "^3.1.2", - "lerna": "^3.19.0" - }, - "optionalDependencies": { - "prettier": "2.0.4" + "eslint-plugin-prettier": "^3.1.4", + "lerna": "^3.19.0", + "prettier": "2.1.2" }, "prettier": { "semi": false, diff --git a/yarn.lock b/yarn.lock index 83bdd4f6d..04b915afa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3,21 +3,42 @@ "@babel/code-frame@^7.0.0": - version "7.5.5" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" - integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.10.4.tgz#168da1a36e90da68ae8d49c0f1b48c7c6249213a" + integrity sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg== dependencies: - "@babel/highlight" "^7.0.0" + "@babel/highlight" "^7.10.4" -"@babel/highlight@^7.0.0": - version "7.5.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.5.0.tgz#56d11312bd9248fa619591d02472be6e8cb32540" - integrity sha512-7dV4eu9gBxoM0dAnj/BCFDW9LFU0zvTrkq0ugM7pnHEgguOEeOz1so2ZghEdzviYzQEED0r4EAgpsBChKy1TRQ== +"@babel/helper-validator-identifier@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" + integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== + +"@babel/highlight@^7.10.4": + version "7.10.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.10.4.tgz#7d1bdfd65753538fabe6c38596cdb76d9ac60143" + integrity sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA== dependencies: + "@babel/helper-validator-identifier" "^7.10.4" chalk "^2.0.0" - esutils "^2.0.2" js-tokens "^4.0.0" +"@eslint/eslintrc@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.1.3.tgz#7d1a2b2358552cc04834c0979bd4275362e37085" + integrity sha512-4YVwPkANLeNtRjMekzux1ci8hIaH5eGKktGqR0d3LWsKNn5B2X/1Z6Trxy7jQXl9EBGE6Yj02O+t09FMeRllaA== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.19" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + "@evocateur/libnpmaccess@^3.1.2": version "3.1.2" resolved "https://registry.yarnpkg.com/@evocateur/libnpmaccess/-/libnpmaccess-3.1.2.tgz#ecf7f6ce6b004e9f942b098d92200be4a4b1c845" @@ -92,15 +113,15 @@ unique-filename "^1.1.1" which "^1.3.1" -"@lerna/add@3.19.0": - version "3.19.0" - resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.19.0.tgz#33b6251c669895f842c14f05961432d464166249" - integrity sha512-qzhxPyoczvvT1W0wwCK9I0iJ4B9WR+HzYsusmRuzM3mEhWjowhbuvKEl5BjGYuXc9AvEErM/S0Fm5K0RcuS39Q== +"@lerna/add@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/add/-/add-3.21.0.tgz#27007bde71cc7b0a2969ab3c2f0ae41578b4577b" + integrity sha512-vhUXXF6SpufBE1EkNEXwz1VLW03f177G9uMOFMQkp6OJ30/PWg4Ekifuz9/3YfgB2/GH8Tu4Lk3O51P2Hskg/A== dependencies: "@evocateur/pacote" "^9.6.3" - "@lerna/bootstrap" "3.18.5" - "@lerna/command" "3.18.5" - "@lerna/filter-options" "3.18.4" + "@lerna/bootstrap" "3.21.0" + "@lerna/command" "3.21.0" + "@lerna/filter-options" "3.20.0" "@lerna/npm-conf" "3.16.0" "@lerna/validation-error" "3.13.0" dedent "^0.7.0" @@ -108,13 +129,13 @@ p-map "^2.1.0" semver "^6.2.0" -"@lerna/bootstrap@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-3.18.5.tgz#cc22a750d6b0402e136926e8b214148dfc2e1390" - integrity sha512-9vD/BfCz8YSF2Dx7sHaMVo6Cy33WjLEmoN1yrHgNkHjm7ykWbLHG5wru0f4Y4pvwa0s5Hf76rvT8aJWzGHk9IQ== +"@lerna/bootstrap@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/bootstrap/-/bootstrap-3.21.0.tgz#bcd1b651be5b0970b20d8fae04c864548123aed6" + integrity sha512-mtNHlXpmvJn6JTu0KcuTTPl2jLsDNud0QacV/h++qsaKbhAaJr/FElNZ5s7MwZFUM3XaDmvWzHKaszeBMHIbBw== dependencies: - "@lerna/command" "3.18.5" - "@lerna/filter-options" "3.18.4" + "@lerna/command" "3.21.0" + "@lerna/filter-options" "3.20.0" "@lerna/has-npm-version" "3.16.5" "@lerna/npm-install" "3.16.5" "@lerna/package-graph" "3.18.5" @@ -137,13 +158,13 @@ read-package-tree "^5.1.6" semver "^6.2.0" -"@lerna/changed@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-3.18.5.tgz#ef2c460f5497b8b4cfac7e5165fe46d7181fcdf5" - integrity sha512-IXS7VZ5VDQUfCsgK56WYxd42luMBxL456cNUf1yBgQ1cy1U2FPVMitIdLN4AcP7bJizdPWeG8yDptf47jN/xVw== +"@lerna/changed@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/changed/-/changed-3.21.0.tgz#108e15f679bfe077af500f58248c634f1044ea0b" + integrity sha512-hzqoyf8MSHVjZp0gfJ7G8jaz+++mgXYiNs9iViQGA8JlN/dnWLI5sWDptEH3/B30Izo+fdVz0S0s7ydVE3pWIw== dependencies: - "@lerna/collect-updates" "3.18.0" - "@lerna/command" "3.18.5" + "@lerna/collect-updates" "3.20.0" + "@lerna/command" "3.21.0" "@lerna/listable" "3.18.5" "@lerna/output" "3.13.0" @@ -165,13 +186,13 @@ execa "^1.0.0" strong-log-transformer "^2.0.0" -"@lerna/clean@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-3.18.5.tgz#44b4a6db68ae369778f2921c85ec6961bdd86072" - integrity sha512-tHxOj9frTIhB/H2gtgMU3xpIc4IJEhXcUlReko6RJt8TTiDZGPDudCcgjg6i7n15v9jXMOc1y4F+y5/1089bfA== +"@lerna/clean@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/clean/-/clean-3.21.0.tgz#c0b46b5300cc3dae2cda3bec14b803082da3856d" + integrity sha512-b/L9l+MDgE/7oGbrav6rG8RTQvRiZLO1zTcG17zgJAAuhlsPxJExMlh2DFwJEVi2les70vMhHfST3Ue1IMMjpg== dependencies: - "@lerna/command" "3.18.5" - "@lerna/filter-options" "3.18.4" + "@lerna/command" "3.21.0" + "@lerna/filter-options" "3.20.0" "@lerna/prompt" "3.18.5" "@lerna/pulse-till-done" "3.13.0" "@lerna/rimraf-dir" "3.16.5" @@ -199,10 +220,10 @@ figgy-pudding "^3.5.1" npmlog "^4.1.2" -"@lerna/collect-updates@3.18.0": - version "3.18.0" - resolved "https://registry.yarnpkg.com/@lerna/collect-updates/-/collect-updates-3.18.0.tgz#6086c64df3244993cc0a7f8fc0ddd6a0103008a6" - integrity sha512-LJMKgWsE/var1RSvpKDIxS8eJ7POADEc0HM3FQiTpEczhP6aZfv9x3wlDjaHpZm9MxJyQilqxZcasRANmRcNgw== +"@lerna/collect-updates@3.20.0": + version "3.20.0" + resolved "https://registry.yarnpkg.com/@lerna/collect-updates/-/collect-updates-3.20.0.tgz#62f9d76ba21a25b7d9fbf31c02de88744a564bd1" + integrity sha512-qBTVT5g4fupVhBFuY4nI/3FSJtQVcDh7/gEPOpRxoXB/yCSnT38MFHXWl+y4einLciCjt/+0x6/4AG80fjay2Q== dependencies: "@lerna/child-process" "3.16.5" "@lerna/describe-ref" "3.16.5" @@ -210,14 +231,14 @@ npmlog "^4.1.2" slash "^2.0.0" -"@lerna/command@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/command/-/command-3.18.5.tgz#14c6d2454adbfd365f8027201523e6c289cd3cd9" - integrity sha512-36EnqR59yaTU4HrR1C9XDFti2jRx0BgpIUBeWn129LZZB8kAB3ov1/dJNa1KcNRKp91DncoKHLY99FZ6zTNpMQ== +"@lerna/command@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/command/-/command-3.21.0.tgz#9a2383759dc7b700dacfa8a22b2f3a6e190121f7" + integrity sha512-T2bu6R8R3KkH5YoCKdutKv123iUgUbW8efVjdGCDnCMthAQzoentOJfDeodBwn0P2OqCl3ohsiNVtSn9h78fyQ== dependencies: "@lerna/child-process" "3.16.5" "@lerna/package-graph" "3.18.5" - "@lerna/project" "3.18.0" + "@lerna/project" "3.21.0" "@lerna/validation-error" "3.13.0" "@lerna/write-log-file" "3.13.0" clone-deep "^4.0.1" @@ -226,10 +247,10 @@ is-ci "^2.0.0" npmlog "^4.1.2" -"@lerna/conventional-commits@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/conventional-commits/-/conventional-commits-3.18.5.tgz#08efd2e5b45acfaf3f151a53a3ec7ecade58a7bc" - integrity sha512-qcvXIEJ3qSgalxXnQ7Yxp5H9Ta5TVyai6vEor6AAEHc20WiO7UIdbLDCxBtiiHMdGdpH85dTYlsoYUwsCJu3HQ== +"@lerna/conventional-commits@3.22.0": + version "3.22.0" + resolved "https://registry.yarnpkg.com/@lerna/conventional-commits/-/conventional-commits-3.22.0.tgz#2798f4881ee2ef457bdae027ab7d0bf0af6f1e09" + integrity sha512-z4ZZk1e8Mhz7+IS8NxHr64wyklHctCJyWpJKEZZPJiLFJ8yKto/x38O80R10pIzC0rr8Sy/OsjSH4bl0TbbgqA== dependencies: "@lerna/validation-error" "3.13.0" conventional-changelog-angular "^5.0.3" @@ -252,14 +273,14 @@ fs-extra "^8.1.0" npmlog "^4.1.2" -"@lerna/create@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/create/-/create-3.18.5.tgz#11ac539f069248eaf7bc4c42e237784330f4fc47" - integrity sha512-cHpjocbpKmLopCuZFI7cKEM3E/QY8y+yC7VtZ4FQRSaLU8D8i2xXtXmYaP1GOlVNavji0iwoXjuNpnRMInIr2g== +"@lerna/create@3.22.0": + version "3.22.0" + resolved "https://registry.yarnpkg.com/@lerna/create/-/create-3.22.0.tgz#d6bbd037c3dc5b425fe5f6d1b817057c278f7619" + integrity sha512-MdiQQzCcB4E9fBF1TyMOaAEz9lUjIHp1Ju9H7f3lXze5JK6Fl5NYkouAvsLgY6YSIhXMY8AHW2zzXeBDY4yWkw== dependencies: "@evocateur/pacote" "^9.6.3" "@lerna/child-process" "3.16.5" - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/npm-conf" "3.16.0" "@lerna/validation-error" "3.13.0" camelcase "^5.0.0" @@ -284,34 +305,35 @@ "@lerna/child-process" "3.16.5" npmlog "^4.1.2" -"@lerna/diff@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-3.18.5.tgz#e9e2cb882f84d5b84f0487c612137305f07accbc" - integrity sha512-u90lGs+B8DRA9Z/2xX4YaS3h9X6GbypmGV6ITzx9+1Ga12UWGTVlKaCXBgONMBjzJDzAQOK8qPTwLA57SeBLgA== +"@lerna/diff@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/diff/-/diff-3.21.0.tgz#e6df0d8b9916167ff5a49fcb02ac06424280a68d" + integrity sha512-5viTR33QV3S7O+bjruo1SaR40m7F2aUHJaDAC7fL9Ca6xji+aw1KFkpCtVlISS0G8vikUREGMJh+c/VMSc8Usw== dependencies: "@lerna/child-process" "3.16.5" - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/validation-error" "3.13.0" npmlog "^4.1.2" -"@lerna/exec@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-3.18.5.tgz#50f1bd6b8f88f2ec02c0768b8b1d9024feb1a96a" - integrity sha512-Q1nz95MeAxctS9bF+aG8FkjixzqEjRpg6ujtnDW84J42GgxedkPtNcJ2o/MBqLd/mxAlr+fW3UZ6CPC/zgoyCg== +"@lerna/exec@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/exec/-/exec-3.21.0.tgz#17f07533893cb918a17b41bcc566dc437016db26" + integrity sha512-iLvDBrIE6rpdd4GIKTY9mkXyhwsJ2RvQdB9ZU+/NhR3okXfqKc6py/24tV111jqpXTtZUW6HNydT4dMao2hi1Q== dependencies: "@lerna/child-process" "3.16.5" - "@lerna/command" "3.18.5" - "@lerna/filter-options" "3.18.4" + "@lerna/command" "3.21.0" + "@lerna/filter-options" "3.20.0" + "@lerna/profiler" "3.20.0" "@lerna/run-topologically" "3.18.5" "@lerna/validation-error" "3.13.0" p-map "^2.1.0" -"@lerna/filter-options@3.18.4": - version "3.18.4" - resolved "https://registry.yarnpkg.com/@lerna/filter-options/-/filter-options-3.18.4.tgz#f5476a7ee2169abed27ad433222e92103f56f9f1" - integrity sha512-4giVQD6tauRwweO/322LP2gfVDOVrt/xN4khkXyfkJDfcsZziFXq+668otD9KSLL8Ps+To4Fah3XbK0MoNuEvA== +"@lerna/filter-options@3.20.0": + version "3.20.0" + resolved "https://registry.yarnpkg.com/@lerna/filter-options/-/filter-options-3.20.0.tgz#0f0f5d5a4783856eece4204708cc902cbc8af59b" + integrity sha512-bmcHtvxn7SIl/R9gpiNMVG7yjx7WyT0HSGw34YVZ9B+3xF/83N3r5Rgtjh4hheLZ+Q91Or0Jyu5O3Nr+AwZe2g== dependencies: - "@lerna/collect-updates" "3.18.0" + "@lerna/collect-updates" "3.20.0" "@lerna/filter-packages" "3.18.0" dedent "^0.7.0" figgy-pudding "^3.5.1" @@ -342,13 +364,13 @@ ssri "^6.0.1" tar "^4.4.8" -"@lerna/github-client@3.16.5": - version "3.16.5" - resolved "https://registry.yarnpkg.com/@lerna/github-client/-/github-client-3.16.5.tgz#2eb0235c3bf7a7e5d92d73e09b3761ab21f35c2e" - integrity sha512-rHQdn8Dv/CJrO3VouOP66zAcJzrHsm+wFuZ4uGAai2At2NkgKH+tpNhQy2H1PSC0Ezj9LxvdaHYrUzULqVK5Hw== +"@lerna/github-client@3.22.0": + version "3.22.0" + resolved "https://registry.yarnpkg.com/@lerna/github-client/-/github-client-3.22.0.tgz#5d816aa4f76747ed736ae64ff962b8f15c354d95" + integrity sha512-O/GwPW+Gzr3Eb5bk+nTzTJ3uv+jh5jGho9BOqKlajXaOkMYGBELEAqV5+uARNGWZFvYAiF4PgqHb6aCUu7XdXg== dependencies: "@lerna/child-process" "3.16.5" - "@octokit/plugin-enterprise-rest" "^3.6.1" + "@octokit/plugin-enterprise-rest" "^6.0.1" "@octokit/rest" "^16.28.4" git-url-parse "^11.1.2" npmlog "^4.1.2" @@ -375,13 +397,13 @@ "@lerna/child-process" "3.16.5" semver "^6.2.0" -"@lerna/import@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/import/-/import-3.18.5.tgz#a9c7d8601870729851293c10abd18b3707f7ba5e" - integrity sha512-PH0WVLEgp+ORyNKbGGwUcrueW89K3Iuk/DDCz8mFyG2IG09l/jOF0vzckEyGyz6PO5CMcz4TI1al/qnp3FrahQ== +"@lerna/import@3.22.0": + version "3.22.0" + resolved "https://registry.yarnpkg.com/@lerna/import/-/import-3.22.0.tgz#1a5f0394f38e23c4f642a123e5e1517e70d068d2" + integrity sha512-uWOlexasM5XR6tXi4YehODtH9Y3OZrFht3mGUFFT3OIl2s+V85xIGFfqFGMTipMPAGb2oF1UBLL48kR43hRsOg== dependencies: "@lerna/child-process" "3.16.5" - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/prompt" "3.18.5" "@lerna/pulse-till-done" "3.13.0" "@lerna/validation-error" "3.13.0" @@ -389,35 +411,44 @@ fs-extra "^8.1.0" p-map-series "^1.0.0" -"@lerna/init@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/init/-/init-3.18.5.tgz#86dd0b2b3290755a96975069b5cb007f775df9f5" - integrity sha512-oCwipWrha98EcJAHm8AGd2YFFLNI7AW9AWi0/LbClj1+XY9ah+uifXIgYGfTk63LbgophDd8936ZEpHMxBsbAg== +"@lerna/info@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/info/-/info-3.21.0.tgz#76696b676fdb0f35d48c83c63c1e32bb5e37814f" + integrity sha512-0XDqGYVBgWxUquFaIptW2bYSIu6jOs1BtkvRTWDDhw4zyEdp6q4eaMvqdSap1CG+7wM5jeLCi6z94wS0AuiuwA== + dependencies: + "@lerna/command" "3.21.0" + "@lerna/output" "3.13.0" + envinfo "^7.3.1" + +"@lerna/init@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/init/-/init-3.21.0.tgz#1e810934dc8bf4e5386c031041881d3b4096aa5c" + integrity sha512-6CM0z+EFUkFfurwdJCR+LQQF6MqHbYDCBPyhu/d086LRf58GtYZYj49J8mKG9ktayp/TOIxL/pKKjgLD8QBPOg== dependencies: "@lerna/child-process" "3.16.5" - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" fs-extra "^8.1.0" p-map "^2.1.0" write-json-file "^3.2.0" -"@lerna/link@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/link/-/link-3.18.5.tgz#f24347e4f0b71d54575bd37cfa1794bc8ee91b18" - integrity sha512-xTN3vktJpkT7Nqc3QkZRtHO4bT5NvuLMtKNIBDkks0HpGxC9PRyyqwOoCoh1yOGbrWIuDezhfMg3Qow+6I69IQ== +"@lerna/link@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/link/-/link-3.21.0.tgz#8be68ff0ccee104b174b5bbd606302c2f06e9d9b" + integrity sha512-tGu9GxrX7Ivs+Wl3w1+jrLi1nQ36kNI32dcOssij6bg0oZ2M2MDEFI9UF2gmoypTaN9uO5TSsjCFS7aR79HbdQ== dependencies: - "@lerna/command" "3.18.5" + "@lerna/command" "3.21.0" "@lerna/package-graph" "3.18.5" "@lerna/symlink-dependencies" "3.17.0" p-map "^2.1.0" slash "^2.0.0" -"@lerna/list@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/list/-/list-3.18.5.tgz#58863f17c81e24e2c38018eb8619fc99d7cc5c82" - integrity sha512-qIeomm28C2OCM8TMjEe/chTnQf6XLN54wPVQ6kZy+axMYxANFNt/uhs6GZEmhem7GEVawzkyHSz5ZJPsfH3IFg== +"@lerna/list@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/list/-/list-3.21.0.tgz#42f76fafa56dea13b691ec8cab13832691d61da2" + integrity sha512-KehRjE83B1VaAbRRkRy6jLX1Cin8ltsrQ7FHf2bhwhRHK0S54YuA6LOoBnY/NtA8bHDX/Z+G5sMY78X30NS9tg== dependencies: - "@lerna/command" "3.18.5" - "@lerna/filter-options" "3.18.4" + "@lerna/command" "3.21.0" + "@lerna/filter-options" "3.20.0" "@lerna/listable" "3.18.5" "@lerna/output" "3.13.0" @@ -552,10 +583,20 @@ dependencies: semver "^6.2.0" -"@lerna/project@3.18.0": - version "3.18.0" - resolved "https://registry.yarnpkg.com/@lerna/project/-/project-3.18.0.tgz#56feee01daeb42c03cbdf0ed8a2a10cbce32f670" - integrity sha512-+LDwvdAp0BurOAWmeHE3uuticsq9hNxBI0+FMHiIai8jrygpJGahaQrBYWpwbshbQyVLeQgx3+YJdW2TbEdFWA== +"@lerna/profiler@3.20.0": + version "3.20.0" + resolved "https://registry.yarnpkg.com/@lerna/profiler/-/profiler-3.20.0.tgz#0f6dc236f4ea8f9ea5f358c6703305a4f32ad051" + integrity sha512-bh8hKxAlm6yu8WEOvbLENm42i2v9SsR4WbrCWSbsmOElx3foRnMlYk7NkGECa+U5c3K4C6GeBbwgqs54PP7Ljg== + dependencies: + figgy-pudding "^3.5.1" + fs-extra "^8.1.0" + npmlog "^4.1.2" + upath "^1.2.0" + +"@lerna/project@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/project/-/project-3.21.0.tgz#5d784d2d10c561a00f20320bcdb040997c10502d" + integrity sha512-xT1mrpET2BF11CY32uypV2GPtPVm6Hgtha7D81GQP9iAitk9EccrdNjYGt5UBYASl4CIDXBRxwmTTVGfrCx82A== dependencies: "@lerna/package" "3.16.0" "@lerna/validation-error" "3.13.0" @@ -578,18 +619,18 @@ inquirer "^6.2.0" npmlog "^4.1.2" -"@lerna/publish@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-3.18.5.tgz#8cc708d83a4cb7ab1c4cc020a02e7ebc4b6b0b0e" - integrity sha512-ifYqLX6mvw95T8vYRlhT68UC7Al0flQvnf5uF9lDgdrgR5Bs+BTwzk3D+0ctdqMtfooekrV6pqfW0R3gtwRffQ== +"@lerna/publish@3.22.1": + version "3.22.1" + resolved "https://registry.yarnpkg.com/@lerna/publish/-/publish-3.22.1.tgz#b4f7ce3fba1e9afb28be4a1f3d88222269ba9519" + integrity sha512-PG9CM9HUYDreb1FbJwFg90TCBQooGjj+n/pb3gw/eH5mEDq0p8wKdLFe0qkiqUkm/Ub5C8DbVFertIo0Vd0zcw== dependencies: "@evocateur/libnpmaccess" "^3.1.2" "@evocateur/npm-registry-fetch" "^4.0.0" "@evocateur/pacote" "^9.6.3" "@lerna/check-working-tree" "3.16.5" "@lerna/child-process" "3.16.5" - "@lerna/collect-updates" "3.18.0" - "@lerna/command" "3.18.5" + "@lerna/collect-updates" "3.20.0" + "@lerna/command" "3.21.0" "@lerna/describe-ref" "3.16.5" "@lerna/log-packed" "3.16.0" "@lerna/npm-conf" "3.16.0" @@ -604,7 +645,7 @@ "@lerna/run-lifecycle" "3.16.2" "@lerna/run-topologically" "3.18.5" "@lerna/validation-error" "3.13.0" - "@lerna/version" "3.18.5" + "@lerna/version" "3.22.1" figgy-pudding "^3.5.1" fs-extra "^8.1.0" npm-package-arg "^6.1.0" @@ -667,15 +708,16 @@ figgy-pudding "^3.5.1" p-queue "^4.0.0" -"@lerna/run@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/run/-/run-3.18.5.tgz#09ae809b16445d3621249c24596cf4ae8e250d5d" - integrity sha512-1S0dZccNJO8+gT5ztYE4rHTEnbXVwThHOfDnlVt2KDxl9cbnBALk3xprGLW7lSzJsxegS849hxrAPUh0UorMgw== +"@lerna/run@3.21.0": + version "3.21.0" + resolved "https://registry.yarnpkg.com/@lerna/run/-/run-3.21.0.tgz#2a35ec84979e4d6e42474fe148d32e5de1cac891" + integrity sha512-fJF68rT3veh+hkToFsBmUJ9MHc9yGXA7LSDvhziAojzOb0AI/jBDp6cEcDQyJ7dbnplba2Lj02IH61QUf9oW0Q== dependencies: - "@lerna/command" "3.18.5" - "@lerna/filter-options" "3.18.4" + "@lerna/command" "3.21.0" + "@lerna/filter-options" "3.20.0" "@lerna/npm-run-script" "3.16.5" "@lerna/output" "3.13.0" + "@lerna/profiler" "3.20.0" "@lerna/run-topologically" "3.18.5" "@lerna/timer" "3.13.0" "@lerna/validation-error" "3.13.0" @@ -716,17 +758,17 @@ dependencies: npmlog "^4.1.2" -"@lerna/version@3.18.5": - version "3.18.5" - resolved "https://registry.yarnpkg.com/@lerna/version/-/version-3.18.5.tgz#0c4f0c2f8d23e9c95c2aa77ad9ce5c7ef025fac0" - integrity sha512-eSMxLIDuVxZIq0JZKNih50x1IZuMmViwF59uwOGMx0hHB84N3waE8HXOF9CJXDSjeP6sHB8tS+Y+X5fFpBop2Q== +"@lerna/version@3.22.1": + version "3.22.1" + resolved "https://registry.yarnpkg.com/@lerna/version/-/version-3.22.1.tgz#9805a9247a47ee62d6b81bd9fa5fb728b24b59e2" + integrity sha512-PSGt/K1hVqreAFoi3zjD0VEDupQ2WZVlVIwesrE5GbrL2BjXowjCsTDPqblahDUPy0hp6h7E2kG855yLTp62+g== dependencies: "@lerna/check-working-tree" "3.16.5" "@lerna/child-process" "3.16.5" - "@lerna/collect-updates" "3.18.0" - "@lerna/command" "3.18.5" - "@lerna/conventional-commits" "3.18.5" - "@lerna/github-client" "3.16.5" + "@lerna/collect-updates" "3.20.0" + "@lerna/command" "3.21.0" + "@lerna/conventional-commits" "3.22.0" + "@lerna/github-client" "3.22.0" "@lerna/gitlab-client" "3.15.0" "@lerna/output" "3.13.0" "@lerna/prerelease-id-from-version" "3.16.0" @@ -764,53 +806,114 @@ call-me-maybe "^1.0.1" glob-to-regexp "^0.3.0" +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + "@nodelib/fs.stat@^1.1.2": version "1.1.3" resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== -"@octokit/endpoint@^5.5.0": - version "5.5.1" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-5.5.1.tgz#2eea81e110ca754ff2de11c79154ccab4ae16b3f" - integrity sha512-nBFhRUb5YzVTCX/iAK1MgQ4uWo89Gu0TH00qQHoYRCsE12dWcG1OiLd7v2EIo2+tpUKPMOQ62QFy9hy9Vg2ULg== +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== dependencies: - "@octokit/types" "^2.0.0" - is-plain-object "^3.0.0" - universal-user-agent "^4.0.0" + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" -"@octokit/plugin-enterprise-rest@^3.6.1": - version "3.6.2" - resolved "https://registry.yarnpkg.com/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-3.6.2.tgz#74de25bef21e0182b4fa03a8678cd00a4e67e561" - integrity sha512-3wF5eueS5OHQYuAEudkpN+xVeUsg8vYEMMenEzLphUZ7PRZ8OJtDcsreL3ad9zxXmBbaFWzLmFcdob5CLyZftA== +"@octokit/auth-token@^2.4.0": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.2.tgz#10d0ae979b100fa6b72fa0e8e63e27e6d0dbff8a" + integrity sha512-jE/lE/IKIz2v1+/P0u4fJqv0kYwXOTujKemJMFr6FeopsxlIK3+wKDCJGnysg81XID5TgZQbIfuJ5J0lnTiuyQ== + dependencies: + "@octokit/types" "^5.0.0" -"@octokit/request-error@^1.0.1", "@octokit/request-error@^1.0.2": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.2.0.tgz#a64d2a9d7a13555570cd79722de4a4d76371baaa" - integrity sha512-DNBhROBYjjV/I9n7A8kVkmQNkqFAMem90dSxqvPq57e2hBr7mNTX98y3R2zDpqMQHVRpBDjsvsfIGgBzy+4PAg== +"@octokit/endpoint@^6.0.1": + version "6.0.8" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.8.tgz#91b07e236fdb69929c678c6439f7a560dc6058ac" + integrity sha512-MuRrgv+bM4Q+e9uEvxAB/Kf+Sj0O2JAOBA131uo1o6lgdq1iS8ejKwtqHgdfY91V3rN9R/hdGKFiQYMzVzVBEQ== + dependencies: + "@octokit/types" "^5.0.0" + is-plain-object "^5.0.0" + universal-user-agent "^6.0.0" + +"@octokit/plugin-enterprise-rest@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-enterprise-rest/-/plugin-enterprise-rest-6.0.1.tgz#e07896739618dab8da7d4077c658003775f95437" + integrity sha512-93uGjlhUD+iNg1iWhUENAtJata6w5nE+V4urXOAlIXdco6xNZtUSfYY8dzp3Udy74aqO/B5UZL80x/YMa5PKRw== + +"@octokit/plugin-paginate-rest@^1.1.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz#004170acf8c2be535aba26727867d692f7b488fc" + integrity sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q== + dependencies: + "@octokit/types" "^2.0.1" + +"@octokit/plugin-request-log@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.0.tgz#eef87a431300f6148c39a7f75f8cfeb218b2547e" + integrity sha512-ywoxP68aOT3zHCLgWZgwUJatiENeHE7xJzYjfz8WI0goynp96wETBF+d95b8g/uL4QmS6owPVlaxiz3wyMAzcw== + +"@octokit/plugin-rest-endpoint-methods@2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz#3288ecf5481f68c494dd0602fc15407a59faf61e" + integrity sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ== + dependencies: + "@octokit/types" "^2.0.1" + deprecation "^2.3.1" + +"@octokit/request-error@^1.0.2": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.2.1.tgz#ede0714c773f32347576c25649dc013ae6b31801" + integrity sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA== dependencies: "@octokit/types" "^2.0.0" deprecation "^2.0.0" once "^1.4.0" +"@octokit/request-error@^2.0.0": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.2.tgz#0e76b83f5d8fdda1db99027ea5f617c2e6ba9ed0" + integrity sha512-2BrmnvVSV1MXQvEkrb9zwzP0wXFNbPJij922kYBTLIlIafukrGOb+ABBT2+c6wZiuyWDH1K1zmjGQ0toN/wMWw== + dependencies: + "@octokit/types" "^5.0.1" + deprecation "^2.0.0" + once "^1.4.0" + "@octokit/request@^5.2.0": - version "5.3.1" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.3.1.tgz#3a1ace45e6f88b1be4749c5da963b3a3b4a2f120" - integrity sha512-5/X0AL1ZgoU32fAepTfEoggFinO3rxsMLtzhlUX+RctLrusn/CApJuGFCd0v7GMFhF+8UiCsTTfsu7Fh1HnEJg== + version "5.4.9" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.9.tgz#0a46f11b82351b3416d3157261ad9b1558c43365" + integrity sha512-CzwVvRyimIM1h2n9pLVYfTDmX9m+KHSgCpqPsY8F1NdEK8IaWqXhSBXsdjOBFZSpEcxNEeg4p0UO9cQ8EnOCLA== dependencies: - "@octokit/endpoint" "^5.5.0" - "@octokit/request-error" "^1.0.1" - "@octokit/types" "^2.0.0" + "@octokit/endpoint" "^6.0.1" + "@octokit/request-error" "^2.0.0" + "@octokit/types" "^5.0.0" deprecation "^2.0.0" - is-plain-object "^3.0.0" - node-fetch "^2.3.0" + is-plain-object "^5.0.0" + node-fetch "^2.6.1" once "^1.4.0" - universal-user-agent "^4.0.0" + universal-user-agent "^6.0.0" "@octokit/rest@^16.28.4": - version "16.35.2" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.35.2.tgz#0098c9e2a895d4afb0fa6578479283553543143c" - integrity sha512-iijaNZpn9hBpUdh8YdXqNiWazmq4R1vCUsmxpBB0kCQ0asHZpCx+HNs22eiHuwYKRhO31ZSAGBJLi0c+3XHaKQ== - dependencies: + version "16.43.2" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.43.2.tgz#c53426f1e1d1044dee967023e3279c50993dd91b" + integrity sha512-ngDBevLbBTFfrHZeiS7SAMAZ6ssuVmXuya+F/7RaVvlysgGa1JKJkKWY+jV6TCJYcW0OALfJ7nTIGXcBXzycfQ== + dependencies: + "@octokit/auth-token" "^2.4.0" + "@octokit/plugin-paginate-rest" "^1.1.1" + "@octokit/plugin-request-log" "^1.0.0" + "@octokit/plugin-rest-endpoint-methods" "2.4.0" "@octokit/request" "^5.2.0" "@octokit/request-error" "^1.0.2" atob-lite "^2.0.0" @@ -824,100 +927,138 @@ once "^1.4.0" universal-user-agent "^4.0.0" -"@octokit/types@^2.0.0": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.0.2.tgz#0888497f5a664e28b0449731d5e88e19b2a74f90" - integrity sha512-StASIL2lgT3TRjxv17z9pAqbnI7HGu9DrJlg3sEBFfCLaMEqp+O3IQPUF6EZtQ4xkAu2ml6kMBBCtGxjvmtmuQ== +"@octokit/types@^2.0.0", "@octokit/types@^2.0.1": + version "2.16.2" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.16.2.tgz#4c5f8da3c6fecf3da1811aef678fda03edac35d2" + integrity sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q== dependencies: "@types/node" ">= 8" -"@types/chai@^4.2.7": - version "4.2.7" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.7.tgz#1c8c25cbf6e59ffa7d6b9652c78e547d9a41692d" - integrity sha512-luq8meHGYwvky0O7u0eQZdA7B4Wd9owUCqvbw2m3XCrCU8mplYOujMBbvyS547AxJkC+pGnd0Cm15eNxEUNU8g== - -"@types/eslint-visitor-keys@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" - integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== +"@octokit/types@^5.0.0", "@octokit/types@^5.0.1": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b" + integrity sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ== + dependencies: + "@types/node" ">= 8" -"@types/events@*": - version "3.0.0" - resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" - integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== +"@types/chai@^4.2.7": + version "4.2.13" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.13.tgz#8a3801f6655179d1803d81e94a2e4aaf317abd16" + integrity sha512-o3SGYRlOpvLFpwJA6Sl1UPOwKFEvE4FxTEB/c9XHI2whdnd4kmPVkNLL8gY4vWGBxWWDumzLbKsAhEH5SKn37Q== "@types/glob@^7.1.1": - version "7.1.1" - resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" - integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== + version "7.1.3" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183" + integrity sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w== dependencies: - "@types/events" "*" "@types/minimatch" "*" "@types/node" "*" "@types/json-schema@^7.0.3": - version "7.0.4" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" - integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" + integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== +"@types/minimist@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" + integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= + "@types/mocha@^5.2.7": version "5.2.7" resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== -"@types/node@*", "@types/node@>= 8", "@types/node@^12.12.21": - version "12.12.21" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.21.tgz#aa44a6363291c7037111c47e4661ad210aded23f" - integrity sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA== +"@types/node@*", "@types/node@>= 8": + version "14.11.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.8.tgz#fe2012f2355e4ce08bca44aeb3abbb21cf88d33f" + integrity sha512-KPcKqKm5UKDkaYPTuXSx8wEP7vE9GnuaXIZKijwRYcePpZFDVuy2a57LarFKiORbHOuTOOwYzxVxcUzsh2P2Pw== + +"@types/node@^12.12.21": + version "12.12.67" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.67.tgz#4f86badb292e822e3b13730a1f9713ed2377f789" + integrity sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg== -"@typescript-eslint/eslint-plugin@^2.27.0": - version "2.27.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.27.0.tgz#e479cdc4c9cf46f96b4c287755733311b0d0ba4b" - integrity sha512-/my+vVHRN7zYgcp0n4z5A6HAK7bvKGBiswaM5zIlOQczsxj/aiD7RcgD+dvVFuwFaGh5+kM7XA6Q6PN0bvb1tw== +"@types/normalize-package-data@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" + integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== + +"@typescript-eslint/eslint-plugin@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.4.0.tgz#0321684dd2b902c89128405cf0385e9fe8561934" + integrity sha512-RVt5wU9H/2H+N/ZrCasTXdGbUTkbf7Hfi9eLiA8vPQkzUJ/bLDCC3CsoZioPrNcnoyN8r0gT153dC++A4hKBQQ== dependencies: - "@typescript-eslint/experimental-utils" "2.27.0" + "@typescript-eslint/experimental-utils" "4.4.0" + "@typescript-eslint/scope-manager" "4.4.0" + debug "^4.1.1" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" + semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/experimental-utils@2.27.0": - version "2.27.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.27.0.tgz#801a952c10b58e486c9a0b36cf21e2aab1e9e01a" - integrity sha512-vOsYzjwJlY6E0NJRXPTeCGqjv5OHgRU1kzxHKWJVPjDYGbPgLudBXjIlc+OD1hDBZ4l1DLbOc5VjofKahsu9Jw== +"@typescript-eslint/experimental-utils@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.4.0.tgz#62a05d3f543b8fc5dec4982830618ea4d030e1a9" + integrity sha512-01+OtK/oWeSJTjQcyzDztfLF1YjvKpLFo+JZmurK/qjSRcyObpIecJ4rckDoRCSh5Etw+jKfdSzVEHevh9gJ1w== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/typescript-estree" "2.27.0" + "@typescript-eslint/scope-manager" "4.4.0" + "@typescript-eslint/types" "4.4.0" + "@typescript-eslint/typescript-estree" "4.4.0" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@^2.27.0": - version "2.27.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.27.0.tgz#d91664335b2c46584294e42eb4ff35838c427287" - integrity sha512-HFUXZY+EdwrJXZo31DW4IS1ujQW3krzlRjBrFRrJcMDh0zCu107/nRfhk/uBasO8m0NVDbBF5WZKcIUMRO7vPg== +"@typescript-eslint/parser@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.4.0.tgz#65974db9a75f23b036f17b37e959b5f99b659ec0" + integrity sha512-yc14iEItCxoGb7W4Nx30FlTyGpU9r+j+n1LUK/exlq2eJeFxczrz/xFRZUk2f6yzWfK+pr1DOTyQnmDkcC4TnA== dependencies: - "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "2.27.0" - "@typescript-eslint/typescript-estree" "2.27.0" - eslint-visitor-keys "^1.1.0" + "@typescript-eslint/scope-manager" "4.4.0" + "@typescript-eslint/types" "4.4.0" + "@typescript-eslint/typescript-estree" "4.4.0" + debug "^4.1.1" + +"@typescript-eslint/scope-manager@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.4.0.tgz#2f3dd27692a12cc9a046a90ba6a9d8cb7731190a" + integrity sha512-r2FIeeU1lmW4K3CxgOAt8djI5c6Q/5ULAgdVo9AF3hPMpu0B14WznBAtxrmB/qFVbVIB6fSx2a+EVXuhSVMEyA== + dependencies: + "@typescript-eslint/types" "4.4.0" + "@typescript-eslint/visitor-keys" "4.4.0" -"@typescript-eslint/typescript-estree@2.27.0": - version "2.27.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.27.0.tgz#a288e54605412da8b81f1660b56c8b2e42966ce8" - integrity sha512-t2miCCJIb/FU8yArjAvxllxbTiyNqaXJag7UOpB5DVoM3+xnjeOngtqlJkLRnMtzaRcJhe3CIR9RmL40omubhg== +"@typescript-eslint/types@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.4.0.tgz#63440ef87a54da7399a13bdd4b82060776e9e621" + integrity sha512-nU0VUpzanFw3jjX+50OTQy6MehVvf8pkqFcURPAE06xFNFenMj1GPEI6IESvp7UOHAnq+n/brMirZdR+7rCrlA== + +"@typescript-eslint/typescript-estree@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.4.0.tgz#16a2df7c16710ddd5406b32b86b9c1124b1ca526" + integrity sha512-Fh85feshKXwki4nZ1uhCJHmqKJqCMba+8ZicQIhNi5d5jSQFteWiGeF96DTjO8br7fn+prTP+t3Cz/a/3yOKqw== dependencies: + "@typescript-eslint/types" "4.4.0" + "@typescript-eslint/visitor-keys" "4.4.0" debug "^4.1.1" - eslint-visitor-keys "^1.1.0" - glob "^7.1.6" + globby "^11.0.1" is-glob "^4.0.1" lodash "^4.17.15" - semver "^6.3.0" + semver "^7.3.2" tsutils "^3.17.1" +"@typescript-eslint/visitor-keys@4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.4.0.tgz#0a9118344082f14c0f051342a74b42dfdb012640" + integrity sha512-oBWeroUZCVsHLiWRdcTXJB7s1nB3taFY8WGvS23tiAlT6jXVvsdAV4rs581bgdEjOhn43q6ro7NkOiLKu6kFqA== + dependencies: + "@typescript-eslint/types" "4.4.0" + eslint-visitor-keys "^2.0.0" + "@zkochan/cmd-shim@^3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@zkochan/cmd-shim/-/cmd-shim-3.1.0.tgz#2ab8ed81f5bb5452a85f25758eb9b8681982fd2e" @@ -953,15 +1094,15 @@ abbrev@1.0.x: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.0.9.tgz#91b4792588a7738c25f35dd6f63752a2f8776135" integrity sha1-kbR5JYinc4wl813W9jdSovh3YTU= -acorn-jsx@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.1.0.tgz#294adb71b57398b0680015f0a38c563ee1db5384" - integrity sha512-tMUqwBWfLFbJbizRmEcWSLw6HnFzfdJs2sOJEOwwtVPMoH/0Ay+E703oZz78VSXZiiDcZrQ5XKjPIUQixhmgVw== +acorn-jsx@^5.2.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== -acorn@^7.1.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.1.1.tgz#e35668de0b402f359de515c5482a1ab9f89a69bf" - integrity sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg== +acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== agent-base@4, agent-base@^4.3.0: version "4.3.0" @@ -984,12 +1125,12 @@ agentkeepalive@^3.4.1: dependencies: humanize-ms "^1.2.1" -ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5: - version "6.10.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.2.tgz#d3cea04d6b017b2894ad69040fec8b623eb4bd52" - integrity sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw== +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: - fast-deep-equal "^2.0.1" + fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" @@ -1004,18 +1145,16 @@ ansi-colors@3.2.3: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== +ansi-colors@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + ansi-escapes@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== -ansi-escapes@^4.2.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" - integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== - dependencies: - type-fest "^0.8.1" - ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" @@ -1043,6 +1182,13 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + any-promise@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" @@ -1075,9 +1221,9 @@ are-we-there-yet@~1.1.2: readable-stream "^2.0.6" arg@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.2.tgz#e70c90579e02c63d80e3ad4e31d8bfdb8bd50064" - integrity sha512-+ytCkGcBtHZ3V2r2Z06AncYO8jz46UEamcspGoU8lHcEbpn6J77QK0vdWvChsclg/tM5XIJC5tnjmPp7Eq6Obg== + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== argparse@^1.0.7: version "1.0.10" @@ -1123,6 +1269,11 @@ array-union@^1.0.2: dependencies: array-uniq "^1.0.1" +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + array-uniq@^1.0.1: version "1.0.3" resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" @@ -1199,7 +1350,7 @@ atob-lite@^2.0.0: resolved "https://registry.yarnpkg.com/atob-lite/-/atob-lite-2.0.0.tgz#0fef5ad46f1bd7a8502c65727f0367d5ee43d696" integrity sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY= -atob@^2.1.1: +atob@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== @@ -1210,9 +1361,9 @@ aws-sign2@~0.7.0: integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c" - integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A== + version "1.10.1" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428" + integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA== balanced-match@^1.0.0: version "1.0.0" @@ -1250,9 +1401,9 @@ before-after-hook@^2.0.0: integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A== binary-extensions@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" - integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== + version "2.1.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" + integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== bluebird@3.4.1: version "3.4.1" @@ -1301,7 +1452,7 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -braces@~3.0.2: +braces@^3.0.1, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -1344,9 +1495,9 @@ byte-size@^5.0.1: integrity sha512-/XuKeqWocKsYa/cBY1YbSJSWWqTi4cFgr9S6OyM7PBaPbr9zvNGwWP33vt0uqGhwDdN+y3yhbXVILEUpnwEWGw== cacache@^12.0.0, cacache@^12.0.3: - version "12.0.3" - resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" - integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== + version "12.0.4" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.4.tgz#668bcbd105aeb5f1d92fe25570ec9525c8faa40c" + integrity sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ== dependencies: bluebird "^3.5.5" chownr "^1.1.1" @@ -1425,6 +1576,15 @@ camelcase-keys@^4.0.0: map-obj "^2.0.0" quick-lru "^1.0.0" +camelcase-keys@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/camelcase-keys/-/camelcase-keys-6.2.2.tgz#5e755d6ba51aa223ec7d3d52f25778210f9dc3c0" + integrity sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg== + dependencies: + camelcase "^5.3.1" + map-obj "^4.0.0" + quick-lru "^4.0.1" + camelcase@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-2.1.1.tgz#7c1d16d679a1bbe59ca02cacecfb011e201f5a1f" @@ -1435,7 +1595,7 @@ camelcase@^4.1.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= -camelcase@^5.0.0: +camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== @@ -1457,7 +1617,7 @@ chai@^4.1.1, chai@^4.2.0: pathval "^1.1.0" type-detect "^4.0.5" -chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.3.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -1466,6 +1626,14 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.3.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -1492,9 +1660,9 @@ chokidar@3.3.0: fsevents "~2.1.1" chownr@^1.1.1, chownr@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" - integrity sha512-i70fVHhmV3DtTl6nqvZOnIjbY0Pe4kAUjwHj8z0zAdgBtYrJyYwLKCCuRBQ5ppkyL0AkN7HKRnETdmdp1zqNXw== + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== chunky@^0.0.0: version "0.0.0" @@ -1523,17 +1691,10 @@ cli-cursor@^2.1.0: dependencies: restore-cursor "^2.0.0" -cli-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" - integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== - dependencies: - restore-cursor "^3.1.0" - cli-width@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" - integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48" + integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw== cliui@^5.0.0: version "5.0.0" @@ -1583,11 +1744,23 @@ color-convert@^1.9.0: dependencies: color-name "1.1.3" +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + columnify@^1.5.4: version "1.5.4" resolved "https://registry.yarnpkg.com/columnify/-/columnify-1.5.4.tgz#4737ddf1c7b69a8a7c340570782e947eec8e78bb" @@ -1603,18 +1776,13 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@~2.20.3: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - -compare-func@^1.3.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-1.3.2.tgz#99dd0ba457e1f9bc722b12c08ec33eeab31fa648" - integrity sha1-md0LpFfh+bxyKxLAjsM+6rMfpkg= +compare-func@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/compare-func/-/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3" + integrity sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA== dependencies: array-ify "^1.0.0" - dot-prop "^3.0.0" + dot-prop "^5.1.0" component-emitter@^1.2.1: version "1.3.0" @@ -1667,11 +1835,11 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= conventional-changelog-angular@^5.0.3: - version "5.0.6" - resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.6.tgz#269540c624553aded809c29a3508fdc2b544c059" - integrity sha512-QDEmLa+7qdhVIv8sFZfVxU1VSyVvnXPsxq8Vam49mKUcO1Z8VTLEJk9uI21uiJUsnmm0I4Hrsdc9TgkOQo9WSA== + version "5.0.11" + resolved "https://registry.yarnpkg.com/conventional-changelog-angular/-/conventional-changelog-angular-5.0.11.tgz#99a3ca16e4a5305e0c2c2fae3ef74fd7631fc3fb" + integrity sha512-nSLypht/1yEflhuTogC03i7DX7sOrXGsRn14g131Potqi6cbGbGEE9PSDEHKldabB6N76HiSyw9Ph+kLmC04Qw== dependencies: - compare-func "^1.3.1" + compare-func "^2.0.0" q "^1.5.1" conventional-changelog-core@^3.1.6: @@ -1694,43 +1862,43 @@ conventional-changelog-core@^3.1.6: through2 "^3.0.0" conventional-changelog-preset-loader@^2.1.1: - version "2.3.0" - resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.0.tgz#580fa8ab02cef22c24294d25e52d7ccd247a9a6a" - integrity sha512-/rHb32J2EJnEXeK4NpDgMaAVTFZS3o1ExmjKMtYVgIC4MQn0vkNSbYpdGRotkfGGRWiqk3Ri3FBkiZGbAfIfOQ== + version "2.3.4" + resolved "https://registry.yarnpkg.com/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz#14a855abbffd59027fd602581f1f34d9862ea44c" + integrity sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g== conventional-changelog-writer@^4.0.6: - version "4.0.11" - resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.11.tgz#9f56d2122d20c96eb48baae0bf1deffaed1edba4" - integrity sha512-g81GQOR392I+57Cw3IyP1f+f42ME6aEkbR+L7v1FBBWolB0xkjKTeCWVguzRrp6UiT1O6gBpJbEy2eq7AnV1rw== + version "4.0.17" + resolved "https://registry.yarnpkg.com/conventional-changelog-writer/-/conventional-changelog-writer-4.0.17.tgz#4753aaa138bf5aa59c0b274cb5937efcd2722e21" + integrity sha512-IKQuK3bib/n032KWaSb8YlBFds+aLmzENtnKtxJy3+HqDq5kohu3g/UdNbIHeJWygfnEbZjnCKFxAW0y7ArZAw== dependencies: - compare-func "^1.3.1" - conventional-commits-filter "^2.0.2" + compare-func "^2.0.0" + conventional-commits-filter "^2.0.6" dateformat "^3.0.0" - handlebars "^4.4.0" + handlebars "^4.7.6" json-stringify-safe "^5.0.1" lodash "^4.17.15" - meow "^5.0.0" + meow "^7.0.0" semver "^6.0.0" split "^1.0.0" through2 "^3.0.0" -conventional-commits-filter@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.2.tgz#f122f89fbcd5bb81e2af2fcac0254d062d1039c1" - integrity sha512-WpGKsMeXfs21m1zIw4s9H5sys2+9JccTzpN6toXtxhpw2VNF2JUXwIakthKBy+LN4DvJm+TzWhxOMWOs1OFCFQ== +conventional-commits-filter@^2.0.2, conventional-commits-filter@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/conventional-commits-filter/-/conventional-commits-filter-2.0.6.tgz#0935e1240c5ca7698329affee1b6a46d33324c4c" + integrity sha512-4g+sw8+KA50/Qwzfr0hL5k5NWxqtrOVw4DDk3/h6L85a9Gz0/Eqp3oP+CWCNfesBvZZZEFHF7OTEbRe+yYSyKw== dependencies: lodash.ismatch "^4.4.0" modify-values "^1.0.0" conventional-commits-parser@^3.0.3: - version "3.0.8" - resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.0.8.tgz#23310a9bda6c93c874224375e72b09fb275fe710" - integrity sha512-YcBSGkZbYp7d+Cr3NWUeXbPDFUN6g3SaSIzOybi8bjHL5IJ5225OSCxJJ4LgziyEJ7AaJtE9L2/EU6H7Nt/DDQ== + version "3.1.0" + resolved "https://registry.yarnpkg.com/conventional-commits-parser/-/conventional-commits-parser-3.1.0.tgz#10140673d5e7ef5572633791456c5d03b69e8be4" + integrity sha512-RSo5S0WIwXZiRxUGTPuYFbqvrR4vpJ1BDdTlthFgvHt5kEdnd1+pdvwWphWn57/oIl4V72NMmOocFqqJ8mFFhA== dependencies: JSONStream "^1.0.4" is-text-path "^1.0.1" lodash "^4.17.15" - meow "^5.0.0" + meow "^7.0.0" split2 "^2.0.0" through2 "^3.0.0" trim-off-newlines "^1.0.0" @@ -1792,7 +1960,7 @@ coveralls@^3.0.4: minimist "^1.2.5" request "^2.88.2" -cross-spawn@^6.0.0, cross-spawn@^6.0.5: +cross-spawn@^6.0.0: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -1803,6 +1971,15 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + currently-unhandled@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/currently-unhandled/-/currently-unhandled-0.4.1.tgz#988df33feab191ef799a61369dd76c17adf957ea" @@ -1861,18 +2038,18 @@ debug@^2.2.0, debug@^2.3.3: ms "2.0.0" debug@^4.0.1, debug@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== dependencies: - ms "^2.1.1" + ms "2.1.2" debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= -decamelize-keys@^1.0.0: +decamelize-keys@^1.0.0, decamelize-keys@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9" integrity sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk= @@ -1902,7 +2079,7 @@ deep-eql@^3.0.1: dependencies: type-detect "^4.0.0" -deep-is@~0.1.3: +deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= @@ -1953,7 +2130,7 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= -deprecation@^2.0.0: +deprecation@^2.0.0, deprecation@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== @@ -1977,9 +2154,9 @@ diff@3.5.0: integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== diff@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.1.tgz#0c667cb467ebbb5cea7f14f135cc2dba7780a8ff" - integrity sha512-s2+XdvhPCOF01LRQBC8hf4vhbVmI2CGS5aZnxLJlT5FtdhPCDFq80q++zK2KlrVorVDdL5BOGZ/VfLrVtYNF+Q== + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== dir-glob@^2.2.2: version "2.2.2" @@ -1988,6 +2165,13 @@ dir-glob@^2.2.2: dependencies: path-type "^3.0.0" +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -1995,24 +2179,24 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dot-prop@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-3.0.0.tgz#1b708af094a49c9a0e7dbcad790aba539dac1177" - integrity sha1-G3CK8JSknJoOfbyteQq6U52sEXc= +dot-prop@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.1.tgz#45884194a71fc2cda71cbb4bceb3a4dd2f433ba4" + integrity sha512-l0p4+mIuJIua0mhxGoh4a+iNL9bmeK5DvnSVQa6T0OhrVmaEa1XScX5Etc673FePCJOArq/4Pa2cLGODUWTPOQ== dependencies: is-obj "^1.0.0" -dot-prop@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" - integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== +dot-prop@^5.1.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88" + integrity sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q== dependencies: - is-obj "^1.0.0" + is-obj "^2.0.0" duplexer@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" - integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== duplexify@^3.4.2, duplexify@^3.6.0: version "3.7.1" @@ -2037,17 +2221,12 @@ emoji-regex@^7.0.1: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== -emoji-regex@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" - integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== - encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - integrity sha1-U4tm8+5izRq1HsMjgp0flIDHS+s= + version "0.1.13" + resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" + integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A== dependencies: - iconv-lite "~0.4.13" + iconv-lite "^0.6.2" end-of-stream@^1.0.0, end-of-stream@^1.1.0: version "1.4.4" @@ -2056,11 +2235,23 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== + dependencies: + ansi-colors "^4.1.1" + env-paths@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== +envinfo@^7.3.1: + version "7.7.3" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.7.3.tgz#4b2d8622e3e7366afb8091b23ed95569ea0208cc" + integrity sha512-46+j5QxbPWza0PB1i15nZx0xQ4I/EfQxg9J8Had3b408SV63nEtor2e+oiY63amTo9KTuh2a3XLObNwduxYwwA== + err-code@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" @@ -2073,22 +2264,40 @@ error-ex@^1.2.0, error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.17.0-next.1: - version "1.17.0-next.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.0-next.1.tgz#94acc93e20b05a6e96dacb5ab2f1cb3a81fc2172" - integrity sha512-7MmGr03N7Rnuid6+wyhD9sHNE2n4tFSwExnU2lQl3lIo2ShXWGePY80zYaoMOmILWv57H0amMjZGHNzzGG70Rw== +es-abstract@^1.17.0-next.1, es-abstract@^1.17.5: + version "1.17.7" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.7.tgz#a4de61b2f66989fc7421676c1cb9787573ace54c" + integrity sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g== dependencies: es-to-primitive "^1.2.1" function-bind "^1.1.1" has "^1.0.3" has-symbols "^1.0.1" - is-callable "^1.1.4" - is-regex "^1.0.4" - object-inspect "^1.7.0" + is-callable "^1.2.2" + is-regex "^1.1.1" + object-inspect "^1.8.0" + object-keys "^1.1.1" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" + +es-abstract@^1.18.0-next.0: + version "1.18.0-next.1" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0-next.1.tgz#6e3a0a4bda717e5023ab3b8e90bec36108d22c68" + integrity sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.2.2" + is-negative-zero "^2.0.0" + is-regex "^1.1.1" + object-inspect "^1.8.0" object-keys "^1.1.1" - object.assign "^4.1.0" - string.prototype.trimleft "^2.1.0" - string.prototype.trimright "^2.1.0" + object.assign "^4.1.1" + string.prototype.trimend "^1.0.1" + string.prototype.trimstart "^1.0.1" es-to-primitive@^1.2.1: version "1.2.1" @@ -2128,17 +2337,17 @@ escodegen@1.8.x: optionalDependencies: source-map "~0.2.0" -eslint-config-prettier@^6.10.1: - version "6.10.1" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.10.1.tgz#129ef9ec575d5ddc0e269667bf09defcd898642a" - integrity sha512-svTy6zh1ecQojvpbJSgH3aei/Rt7C6i090l5f2WQ4aB05lYHeZIR1qL4wZyyILTbtmnbHP5Yn8MrsOJMGa8RkQ== +eslint-config-prettier@^6.12.0: + version "6.12.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.12.0.tgz#9eb2bccff727db1c52104f0b49e87ea46605a0d2" + integrity sha512-9jWPlFlgNwRUYVoujvWTQ1aMO8o6648r+K7qU7K5Jmkbyqav1fuEZC0COYpGBxyiAJb65Ra9hrmFx19xRGwXWw== dependencies: get-stdin "^6.0.0" eslint-plugin-es@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.0.tgz#98cb1bc8ab0aa807977855e11ad9d1c9422d014b" - integrity sha512-6/Jb/J/ZvSebydwbBJO1R9E5ky7YeElfK56Veh7e4QGFHCXoIXGH9HhVz+ibJLM3XJ1XjP+T7rKBLUa/Y7eIng== + version "3.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-3.0.1.tgz#75a7cdfdccddc0589934aeeb384175f221c57893" + integrity sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ== dependencies: eslint-utils "^2.0.0" regexpp "^3.0.0" @@ -2155,10 +2364,10 @@ eslint-plugin-node@^11.1.0: resolve "^1.10.1" semver "^6.1.0" -eslint-plugin-prettier@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.2.tgz#432e5a667666ab84ce72f945c72f77d996a5c9ba" - integrity sha512-GlolCC9y3XZfv3RQfwGew7NnuFDKsfI4lbvRK+PIIo23SFH+LemGs4cKwzAaRa+Mdb+lQO/STaIayno8T5sJJA== +eslint-plugin-prettier@^3.1.4: + version "3.1.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz#168ab43154e2ea57db992a2cd097c828171f75c2" + integrity sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg== dependencies: prettier-linter-helpers "^1.0.0" @@ -2167,49 +2376,49 @@ eslint-plugin-promise@^3.5.0: resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621" integrity sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ== -eslint-scope@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.0.0.tgz#e87c8887c73e8d1ec84f1ca591645c358bfc8fb9" - integrity sha512-oYrhJW7S0bxAFDvWqzvMPRm6pcgcnWc4QnofCAqRTRfQC0JcwenzGglTtsLyIuuWFfkqDG9vz67cnttSd53djw== +eslint-scope@^5.0.0, eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== dependencies: - esrecurse "^4.1.0" + esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-utils@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f" - integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q== +eslint-utils@^2.0.0, eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== dependencies: eslint-visitor-keys "^1.1.0" -eslint-utils@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.0.0.tgz#7be1cc70f27a72a76cd14aa698bcabed6890e1cd" - integrity sha512-0HCPuJv+7Wv1bACm8y5/ECVfYdfsAm9xmVb7saeFlxjPYALefjhbYoCkBjPdPzGH8wWyTpAez82Fh3VKYEZ8OA== - dependencies: - eslint-visitor-keys "^1.1.0" +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== -eslint-visitor-keys@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== -eslint@^6.8.0: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb" - integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig== +eslint@^7.11.0: + version "7.11.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.11.0.tgz#aaf2d23a0b5f1d652a08edacea0c19f7fadc0b3b" + integrity sha512-G9+qtYVCHaDi1ZuWzBsOWo2wSwd70TXnU6UHA3cTYHp7gCTXZcpggWFoUVAMRarg68qtPoNfFbzPh+VdOgmwmw== dependencies: "@babel/code-frame" "^7.0.0" + "@eslint/eslintrc" "^0.1.3" ajv "^6.10.0" - chalk "^2.1.0" - cross-spawn "^6.0.5" + chalk "^4.0.0" + cross-spawn "^7.0.2" debug "^4.0.1" doctrine "^3.0.0" - eslint-scope "^5.0.0" - eslint-utils "^1.4.3" - eslint-visitor-keys "^1.1.0" - espree "^6.1.2" - esquery "^1.0.1" + enquirer "^2.3.5" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.0" + esquery "^1.2.0" esutils "^2.0.2" file-entry-cache "^5.0.1" functional-red-black-tree "^1.0.1" @@ -2218,33 +2427,31 @@ eslint@^6.8.0: ignore "^4.0.6" import-fresh "^3.0.0" imurmurhash "^0.1.4" - inquirer "^7.0.0" is-glob "^4.0.0" js-yaml "^3.13.1" json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.14" + levn "^0.4.1" + lodash "^4.17.19" minimatch "^3.0.4" - mkdirp "^0.5.1" natural-compare "^1.4.0" - optionator "^0.8.3" + optionator "^0.9.1" progress "^2.0.0" - regexpp "^2.0.1" - semver "^6.1.2" - strip-ansi "^5.2.0" - strip-json-comments "^3.0.1" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" table "^5.2.3" text-table "^0.2.0" v8-compile-cache "^2.0.3" -espree@^6.1.2: - version "6.1.2" - resolved "https://registry.yarnpkg.com/espree/-/espree-6.1.2.tgz#6c272650932b4f91c3714e5e7b5f5e2ecf47262d" - integrity sha512-2iUPuuPP+yW1PZaMSDM9eyVf8D5P0Hi8h83YtZ5bPc/zHYjII5khoixIUTMO794NOY8F/ThF1Bo8ncZILarUTA== +espree@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348" + integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw== dependencies: - acorn "^7.1.0" - acorn-jsx "^5.1.0" - eslint-visitor-keys "^1.1.0" + acorn "^7.4.0" + acorn-jsx "^5.2.0" + eslint-visitor-keys "^1.3.0" esprima@2.7.x, esprima@^2.7.1: version "2.7.3" @@ -2256,30 +2463,35 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== -esquery@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.0.1.tgz#406c51658b1f5991a5f9b62b1dc25b00e3e5c708" - integrity sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA== +esquery@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" + integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== dependencies: - estraverse "^4.0.0" + estraverse "^5.1.0" -esrecurse@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" - integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== dependencies: - estraverse "^4.1.0" + estraverse "^5.2.0" estraverse@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44" integrity sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q= -estraverse@^4.0.0, estraverse@^4.1.0, estraverse@^4.1.1: +estraverse@^4.1.1: version "4.3.0" resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + esutils@^2.0.2: version "2.0.3" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" @@ -2374,10 +2586,10 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= -fast-deep-equal@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" - integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk= +fast-deep-equal@^3.1.1: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== fast-diff@^1.1.2: version "1.2.0" @@ -2396,20 +2608,39 @@ fast-glob@^2.2.6: merge2 "^1.2.3" micromatch "^3.1.10" +fast-glob@^3.1.1: + version "3.2.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" + integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== -fast-levenshtein@~2.0.6: +fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fastq@^1.6.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.8.0.tgz#550e1f9f59bbc65fe185cb6a9b4d95357107f481" + integrity sha512-SMIZoZdLh/fgofivvIkmknUXyPnvxRE3DhtZ5Me3Mrsk5gyPL42F0xr51TdRXskBxHfMp+07bcYzfsYEsSQA9Q== + dependencies: + reusify "^1.0.4" + figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" - integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== + version "3.5.2" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" + integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== figures@^2.0.0: version "2.0.0" @@ -2418,13 +2649,6 @@ figures@^2.0.0: dependencies: escape-string-regexp "^1.0.5" -figures@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" - integrity sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg== - dependencies: - escape-string-regexp "^1.0.5" - file-entry-cache@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" @@ -2471,6 +2695,14 @@ find-up@^2.0.0: dependencies: locate-path "^2.0.0" +find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -2488,9 +2720,9 @@ flat@^4.1.0: is-buffer "~2.0.3" flatted@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.1.tgz#69e57caa8f0eacbc281d2e2cb458d46fdb449e08" - integrity sha512-a1hQMktqW9Nmqr5aktAux3JMNqaucxGcjtjWnZLHX7yyPCmlSV3M54nGYbqT8K+0GhF3NBgmJCc3ma+WOgX8Jg== + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== flush-write-stream@^1.0.0: version "1.1.1" @@ -2691,17 +2923,17 @@ git-semver-tags@^2.0.3: semver "^6.0.0" git-up@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/git-up/-/git-up-4.0.1.tgz#cb2ef086653640e721d2042fe3104857d89007c0" - integrity sha512-LFTZZrBlrCrGCG07/dm1aCjjpL1z9L3+5aEeI9SBhAqSc+kiA9Or1bgZhQFNppJX6h/f5McrvJt1mQXTFm6Qrw== + version "4.0.2" + resolved "https://registry.yarnpkg.com/git-up/-/git-up-4.0.2.tgz#10c3d731051b366dc19d3df454bfca3f77913a7c" + integrity sha512-kbuvus1dWQB2sSW4cbfTeGpCMd8ge9jx9RKnhXhuJ7tnvT+NIrTVfYZxjtflZddQYcmdOTlkAcjmx7bor+15AQ== dependencies: is-ssh "^1.3.0" parse-url "^5.0.0" git-url-parse@^11.1.2: - version "11.1.2" - resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-11.1.2.tgz#aff1a897c36cc93699270587bea3dbcbbb95de67" - integrity sha512-gZeLVGY8QVKMIkckncX+iCq2/L8PlwncvDFKiWkBn9EtCfYDbliRTTp6qzyQ1VMdITUfq7293zDzfpjdiGASSQ== + version "11.3.0" + resolved "https://registry.yarnpkg.com/git-url-parse/-/git-url-parse-11.3.0.tgz#1515b4574c4eb2efda7d25cc50b29ce8beaefaae" + integrity sha512-i3XNa8IKmqnUqWBcdWBjOcnyZYfN3C1WRvnKI6ouFWwsXCZEnlgbwbm55ZpJ3OJMhfEP/ryFhqW8bBhej3C5Ug== dependencies: git-up "^4.0.0" @@ -2720,14 +2952,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.0.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" - integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== - dependencies: - is-glob "^4.0.1" - -glob-parent@~5.1.0: +glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: version "5.1.1" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== @@ -2762,7 +2987,7 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -2775,12 +3000,24 @@ glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: path-is-absolute "^1.0.0" globals@^12.1.0: - version "12.3.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-12.3.0.tgz#1e564ee5c4dded2ab098b0f88f24702a3c56be13" - integrity sha512-wAfjdLgFsPZsklLJvOBUBmzYE8/CwhEqSBEMRXA3qxIiNtyqvjYurAtIfDh6chlEPUfmTY3MnZh5Hfh4q0UlIw== + version "12.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== dependencies: type-fest "^0.8.1" +globby@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" + integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + globby@^9.2.0: version "9.2.0" resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" @@ -2796,16 +3033,16 @@ globby@^9.2.0: slash "^2.0.0" graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2: - version "4.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" - integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + version "4.2.4" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" + integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== growl@1.10.5: version "1.10.5" resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== -handlebars@^4.0.1: +handlebars@^4.0.1, handlebars@^4.7.6: version "4.7.6" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e" integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA== @@ -2817,30 +3054,24 @@ handlebars@^4.0.1: optionalDependencies: uglify-js "^3.1.4" -handlebars@^4.4.0: - version "4.5.3" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.5.3.tgz#5cf75bd8714f7605713511a56be7c349becb0482" - integrity sha512-3yPecJoJHK/4c6aZhSvxOyG4vJKDshV36VHp0iVCDVh7o9w2vwi3NSnL2MMPj3YdduqaBcu7cGbggJQM0br9xA== - dependencies: - neo-async "^2.6.0" - optimist "^0.6.1" - source-map "^0.6.1" - optionalDependencies: - uglify-js "^3.1.4" - har-schema@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= -har-validator@~5.1.0, har-validator@~5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== +har-validator@~5.1.3: + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== dependencies: - ajv "^6.5.5" + ajv "^6.12.3" har-schema "^2.0.0" +hard-rejection@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" + integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== + has-flag@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" @@ -2851,6 +3082,11 @@ has-flag@^3.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has-symbols@^1.0.0, has-symbols@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" @@ -2905,9 +3141,9 @@ he@1.2.0: integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== hosted-git-info@^2.1.4, hosted-git-info@^2.7.1: - version "2.8.5" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.5.tgz#759cfcf2c4d156ade59b0b2dfabddc42a6b9c70c" - integrity sha512-kssjab8CvdXfcXMXVcvsXum4Hwdq9XGtRD3TteMEvEbq0LXyiNQr6AprqKqfeaDXze7SxWvRxdpwE6ku7ikLkg== + version "2.8.8" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488" + integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg== http-cache-semantics@^3.8.1: version "3.8.1" @@ -2946,13 +3182,20 @@ humanize-ms@^1.2.1: dependencies: ms "^2.0.0" -iconv-lite@^0.4.24, iconv-lite@~0.4.13: +iconv-lite@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.2.tgz#ce13d1875b0c3a674bd6a04b7f76b01b1b6ded01" + integrity sha512-2y91h5OpQlolefMPmUlivelittSWy0rP+oYVpn6A7GwVHNE8AWzoYOBNmlwks3LobaJxgHCYZAnyNo2GgpNRNQ== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + iferr@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" @@ -2970,10 +3213,10 @@ ignore@^4.0.3, ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.1: - version "5.1.4" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" - integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== +ignore@^5.1.1, ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== import-fresh@^2.0.0: version "2.0.0" @@ -2983,7 +3226,7 @@ import-fresh@^2.0.0: caller-path "^2.0.0" resolve-from "^3.0.0" -import-fresh@^3.0.0: +import-fresh@^3.0.0, import-fresh@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== @@ -3016,6 +3259,11 @@ indent-string@^3.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" integrity sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok= +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + infer-owner@^1.0.3, infer-owner@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" @@ -3029,7 +3277,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.3: +inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -3072,25 +3320,6 @@ inquirer@^6.2.0: strip-ansi "^5.1.0" through "^2.3.6" -inquirer@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.0.1.tgz#13f7980eedc73c689feff3994b109c4e799c6ebb" - integrity sha512-V1FFQ3TIO15det8PijPLFR9M9baSlnRs9nL7zWu1MNVA2T9YVl9ZbrHJhYs7e9X8jeMZ3lr2JH/rdHFgNCBdYw== - dependencies: - ansi-escapes "^4.2.1" - chalk "^2.4.2" - cli-cursor "^3.1.0" - cli-width "^2.0.0" - external-editor "^3.0.3" - figures "^3.0.0" - lodash "^4.17.15" - mute-stream "0.0.8" - run-async "^2.2.0" - rxjs "^6.5.3" - string-width "^4.1.0" - strip-ansi "^5.1.0" - through "^2.3.6" - ip@1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" @@ -3132,10 +3361,10 @@ is-buffer@~2.0.3: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== -is-callable@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA== +is-callable@^1.1.4, is-callable@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.2.tgz#c7c6715cd22d4ddb48d3e19970223aceabb080d9" + integrity sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA== is-ci@^2.0.0: version "2.0.0" @@ -3159,9 +3388,9 @@ is-data-descriptor@^1.0.0: kind-of "^6.0.0" is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY= + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== is-descriptor@^0.1.0: version "0.1.6" @@ -3204,11 +3433,9 @@ is-extglob@^2.1.0, is-extglob@^2.1.1: integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-finite@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - integrity sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko= - dependencies: - number-is-nan "^1.0.0" + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" + integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== is-fullwidth-code-point@^1.0.0: version "1.0.0" @@ -3222,11 +3449,6 @@ is-fullwidth-code-point@^2.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= -is-fullwidth-code-point@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" - integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== - is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -3241,6 +3463,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-negative-zero@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" + integrity sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE= + is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -3258,6 +3485,11 @@ is-obj@^1.0.0: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= +is-obj@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" + integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== + is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" @@ -3270,29 +3502,22 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-plain-object@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.0.tgz#47bfc5da1b5d50d64110806c199359482e75a928" - integrity sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg== - dependencies: - isobject "^4.0.0" - -is-promise@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" - integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= +is-plain-object@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== -is-regex@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" - integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== +is-regex@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" + integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== dependencies: - has "^1.0.3" + has-symbols "^1.0.1" is-ssh@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.1.tgz#f349a8cadd24e65298037a522cf7520f2e81a0f3" - integrity sha512-0eRIASHZt1E68/ixClI8bp2YK2wmBPVWEismTs6M+M099jKgrzl/3E976zIbImSIob48N2/XGe9y7ZiYdImSlg== + version "1.3.2" + resolved "https://registry.yarnpkg.com/is-ssh/-/is-ssh-1.3.2.tgz#a4b82ab63d73976fd8263cceee27f99a88bdae2b" + integrity sha512-elEw0/0c2UscLrNG+OAorbP539E3rhliKPg+hDMWN9VwrDXfYK+4PBEykDPfxlYYtQvl84TascnQyobfQLHEhQ== dependencies: protocols "^1.1.0" @@ -3352,11 +3577,6 @@ isobject@^3.0.0, isobject@^3.0.1: resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= -isobject@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0" - integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA== - isstream@~0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" @@ -3387,7 +3607,7 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@3.13.1, js-yaml@3.x, js-yaml@^3.13.1: +js-yaml@3.13.1: version "3.13.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== @@ -3395,6 +3615,14 @@ js-yaml@3.13.1, js-yaml@3.x, js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@3.x, js-yaml@^3.13.1: + version "3.14.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -3405,6 +3633,11 @@ json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1: resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== +json-parse-even-better-errors@^2.3.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" + integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== + json-schema-traverse@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" @@ -3471,10 +3704,10 @@ kind-of@^5.0.0: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== -kind-of@^6.0.0, kind-of@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" - integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== +kind-of@^6.0.0, kind-of@^6.0.2, kind-of@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== lcov-parse@^1.0.0: version "1.0.0" @@ -3482,29 +3715,38 @@ lcov-parse@^1.0.0: integrity sha1-6w1GtUER68VhrLTECO+TY73I9+A= lerna@^3.19.0: - version "3.19.0" - resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.19.0.tgz#6d53b613eca7da426ab1e97c01ce6fb39754da6c" - integrity sha512-YtMmwEqzWHQCh7Ynk7BvjrZri3EkSeVqTAcwZIqWlv9V/dCfvFPyRqp+2NIjPB5nj1FWXLRH6F05VT/qvzuuOA== - dependencies: - "@lerna/add" "3.19.0" - "@lerna/bootstrap" "3.18.5" - "@lerna/changed" "3.18.5" - "@lerna/clean" "3.18.5" + version "3.22.1" + resolved "https://registry.yarnpkg.com/lerna/-/lerna-3.22.1.tgz#82027ac3da9c627fd8bf02ccfeff806a98e65b62" + integrity sha512-vk1lfVRFm+UuEFA7wkLKeSF7Iz13W+N/vFd48aW2yuS7Kv0RbNm2/qcDPV863056LMfkRlsEe+QYOw3palj5Lg== + dependencies: + "@lerna/add" "3.21.0" + "@lerna/bootstrap" "3.21.0" + "@lerna/changed" "3.21.0" + "@lerna/clean" "3.21.0" "@lerna/cli" "3.18.5" - "@lerna/create" "3.18.5" - "@lerna/diff" "3.18.5" - "@lerna/exec" "3.18.5" - "@lerna/import" "3.18.5" - "@lerna/init" "3.18.5" - "@lerna/link" "3.18.5" - "@lerna/list" "3.18.5" - "@lerna/publish" "3.18.5" - "@lerna/run" "3.18.5" - "@lerna/version" "3.18.5" + "@lerna/create" "3.22.0" + "@lerna/diff" "3.21.0" + "@lerna/exec" "3.21.0" + "@lerna/import" "3.22.0" + "@lerna/info" "3.21.0" + "@lerna/init" "3.21.0" + "@lerna/link" "3.21.0" + "@lerna/list" "3.21.0" + "@lerna/publish" "3.22.1" + "@lerna/run" "3.21.0" + "@lerna/version" "3.22.1" import-local "^2.0.0" npmlog "^4.1.2" -levn@^0.3.0, levn@~0.3.0: +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +levn@~0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" integrity sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= @@ -3512,6 +3754,11 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +lines-and-columns@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" + integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + load-json-file@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" @@ -3560,6 +3807,13 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -3610,10 +3864,10 @@ lodash.uniq@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= -lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.2.1: - version "4.17.19" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" - integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== +lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.2.1: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== log-driver@^1.2.7: version "1.2.7" @@ -3648,9 +3902,9 @@ macgyver@~1.10: integrity sha1-sJ0VmdizbtWxb1lYlRXZ0UvC/Yg= macos-release@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" - integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA== + version "2.4.1" + resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.4.1.tgz#64033d0ec6a5e6375155a74b1a1eba8e509820ac" + integrity sha512-H/QHeBIN1fIGJX517pvK8IEK53yQOW7YcEI55oYtgjDdoCQQz7eJS94qt5kNrscReEyuD/JcdFCm2XBEcGOITg== make-dir@^1.0.0: version "1.3.0" @@ -3668,9 +3922,9 @@ make-dir@^2.1.0: semver "^5.6.0" make-error@^1.1.1: - version "1.3.5" - resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.5.tgz#efe4e81f6db28cadd605c70f29c831b58ef776c8" - integrity sha512-c3sIjNUow0+8swNwVpqoH4YCShKNFkMaw6oH1mNS2haDZQqkeZFlHS3dhoeEbKKmJB4vXpJucU6oH75aDYeE9g== + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== make-fetch-happen@^5.0.0: version "5.0.2" @@ -3704,6 +3958,11 @@ map-obj@^2.0.0: resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-2.0.0.tgz#a65cd29087a92598b8791257a523e021222ac1f9" integrity sha1-plzSkIepJZi4eRJXpSPgISIqwfk= +map-obj@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.1.0.tgz#b91221b542734b9f14256c0132c897c5d7256fd5" + integrity sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g== + map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" @@ -3742,25 +4001,27 @@ meow@^4.0.0: redent "^2.0.0" trim-newlines "^2.0.0" -meow@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-5.0.0.tgz#dfc73d63a9afc714a5e371760eb5c88b91078aa4" - integrity sha512-CbTqYU17ABaLefO8vCU153ZZlprKYWDljcndKKDCFcYQITzWCXZAVk4QMFZPgvzrnUQ3uItnIE/LoUOwrT15Ig== - dependencies: - camelcase-keys "^4.0.0" - decamelize-keys "^1.0.0" - loud-rejection "^1.0.0" - minimist-options "^3.0.1" - normalize-package-data "^2.3.4" - read-pkg-up "^3.0.0" - redent "^2.0.0" - trim-newlines "^2.0.0" - yargs-parser "^10.0.0" +meow@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/meow/-/meow-7.1.1.tgz#7c01595e3d337fcb0ec4e8eed1666ea95903d306" + integrity sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA== + dependencies: + "@types/minimist" "^1.2.0" + camelcase-keys "^6.2.2" + decamelize-keys "^1.1.0" + hard-rejection "^2.1.0" + minimist-options "4.1.0" + normalize-package-data "^2.5.0" + read-pkg-up "^7.0.1" + redent "^3.0.0" + trim-newlines "^3.0.0" + type-fest "^0.13.1" + yargs-parser "^18.1.3" -merge2@^1.2.3: - version "1.3.0" - resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" - integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== +merge2@^1.2.3, merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== micromatch@^3.1.10: version "3.1.10" @@ -3781,27 +4042,35 @@ micromatch@^3.1.10: snapdragon "^0.8.1" to-regex "^3.0.2" -mime-db@1.42.0: - version "1.42.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.42.0.tgz#3e252907b4c7adb906597b4b65636272cf9e7bac" - integrity sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ== +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + +mime-db@1.44.0: + version "1.44.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" + integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.25" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.25.tgz#39772d46621f93e2a80a856c53b86a62156a6437" - integrity sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg== + version "2.1.27" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" + integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== dependencies: - mime-db "1.42.0" + mime-db "1.44.0" mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== -mimic-fn@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" - integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== +min-indent@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" + integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== "minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.4: version "3.0.4" @@ -3810,6 +4079,15 @@ mimic-fn@^2.1.0: dependencies: brace-expansion "^1.1.7" +minimist-options@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" + integrity sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A== + dependencies: + arrify "^1.0.1" + is-plain-obj "^1.1.0" + kind-of "^6.0.3" + minimist-options@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-3.0.2.tgz#fba4c8191339e13ecf4d61beb03f070103f3d954" @@ -3818,26 +4096,11 @@ minimist-options@^3.0.1: arrify "^1.0.1" is-plain-obj "^1.1.0" -minimist@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= - -minimist@^1.1.3, minimist@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= - -minimist@^1.2.5: +minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== -minimist@~0.0.1: - version "0.0.10" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" - integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= - minipass@^2.3.5, minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" @@ -3884,14 +4147,12 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@^0.5.0, mkdirp@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= - dependencies: - minimist "0.0.8" +mkdirp@*: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@0.5.5, mkdirp@0.5.x: +mkdirp@0.5.5, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -3899,9 +4160,9 @@ mkdirp@0.5.5, mkdirp@0.5.x: minimist "^1.2.5" mocha@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.1.2.tgz#8e40d198acf91a52ace122cd7599c9ab857b29e6" - integrity sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA== + version "7.2.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.2.0.tgz#01cc227b00d875ab1eed03a75106689cfed5a604" + integrity sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ== dependencies: ansi-colors "3.2.3" browser-stdout "1.3.1" @@ -3955,7 +4216,7 @@ ms@2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== -ms@^2.0.0, ms@^2.1.1: +ms@2.1.2, ms@^2.0.0, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== @@ -3975,7 +4236,7 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= -mute-stream@0.0.8, mute-stream@~0.0.4: +mute-stream@~0.0.4: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== @@ -4012,9 +4273,9 @@ natural-compare@^1.4.0: integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= neo-async@^2.6.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== + version "2.6.2" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" + integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== nice-try@^1.0.4: version "1.0.5" @@ -4030,23 +4291,23 @@ node-environment-flags@1.0.6: semver "^5.7.0" node-fetch-npm@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.2.tgz#7258c9046182dca345b4208eda918daf33697ff7" - integrity sha512-nJIxm1QmAj4v3nfCvEeCrYSoVwXyxLnaPBK5W1W5DGEJwjlKuC2VEUycGw5oxk+4zZahRrB84PUJJgEmhFTDFw== + version "2.0.4" + resolved "https://registry.yarnpkg.com/node-fetch-npm/-/node-fetch-npm-2.0.4.tgz#6507d0e17a9ec0be3bec516958a497cec54bf5a4" + integrity sha512-iOuIQDWDyjhv9qSDrj9aq/klt6F9z1p2otB3AV7v3zBDcL/x+OfGsvGQZZCcMZbUf4Ujw1xGNQkjvGnVT22cKg== dependencies: encoding "^0.1.11" json-parse-better-errors "^1.0.0" safe-buffer "^5.1.1" -node-fetch@^2.3.0, node-fetch@^2.5.0: +node-fetch@^2.5.0, node-fetch@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== node-gyp@^5.0.2: - version "5.0.7" - resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.0.7.tgz#dd4225e735e840cf2870e4037c2ed9c28a31719e" - integrity sha512-K8aByl8OJD51V0VbUURTKsmdswkQQusIvlvmTyhHlIT1hBvaSxzdxpSle857XuXa7uc02UEZx9OR5aDxSWS5Qw== + version "5.1.1" + resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-5.1.1.tgz#eb915f7b631c937d282e33aed44cb7a025f62a3e" + integrity sha512-WH0WKGi+a4i4DUt2mHnvocex/xPLp9pYt5R6M2JdFB7pJ7Z34hveZ4nDTGTiLXCkitA9T8HFZjhinBCiVHYcWw== dependencies: env-paths "^2.2.0" glob "^7.1.4" @@ -4068,9 +4329,9 @@ nopt@3.x: abbrev "1" nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= + version "4.0.3" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" + integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== dependencies: abbrev "1" osenv "^0.1.4" @@ -4103,9 +4364,9 @@ npm-bundled@^1.0.1: npm-normalize-package-bin "^1.0.1" npm-lifecycle@^3.1.2: - version "3.1.4" - resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-3.1.4.tgz#de6975c7d8df65f5150db110b57cce498b0b604c" - integrity sha512-tgs1PaucZwkxECGKhC/stbEgFyc3TGh2TJcg2CDr6jbvQRdteHNhmMeljRzpe4wgFAXQADoy1cSqqi7mtiAa5A== + version "3.1.5" + resolved "https://registry.yarnpkg.com/npm-lifecycle/-/npm-lifecycle-3.1.5.tgz#9882d3642b8c82c815782a12e6a1bfeed0026309" + integrity sha512-lDLVkjfZmvmfvpvBzA4vzee9cn+Me4orq0QF8glbswJVEbIcSNWib7qGOffolysc3teCqbbPZZkzbr3GQZTL1g== dependencies: byline "^5.0.0" graceful-fs "^4.1.15" @@ -4132,12 +4393,13 @@ npm-normalize-package-bin@^1.0.0, npm-normalize-package-bin@^1.0.1: validate-npm-package-name "^3.0.0" npm-packlist@^1.4.4: - version "1.4.7" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.7.tgz#9e954365a06b80b18111ea900945af4f88ed4848" - integrity sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ== + version "1.4.8" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" + integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" + npm-normalize-package-bin "^1.0.1" npm-pick-manifest@^3.0.0: version "3.0.2" @@ -4189,10 +4451,10 @@ object-copy@^0.1.0: define-property "^0.2.5" kind-of "^3.0.3" -object-inspect@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" - integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== +object-inspect@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" + integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.1: version "1.1.1" @@ -4206,7 +4468,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@4.1.0, object.assign@^4.1.0: +object.assign@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== @@ -4216,6 +4478,16 @@ object.assign@4.1.0, object.assign@^4.1.0: has-symbols "^1.0.0" object-keys "^1.0.11" +object.assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.1.tgz#303867a666cdd41936ecdedfb1f8f3e32a478cdd" + integrity sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.18.0-next.0" + has-symbols "^1.0.1" + object-keys "^1.1.1" + object.getownpropertydescriptors@^2.0.3: version "2.1.0" resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" @@ -4250,22 +4522,7 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" -onetime@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" - integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== - dependencies: - mimic-fn "^2.1.0" - -optimist@^0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/optimist/-/optimist-0.6.1.tgz#da3ea74686fa21a19a111c326e90eb15a0196686" - integrity sha1-2j6nRob6IaGaERwybpDrFaAZZoY= - dependencies: - minimist "~0.0.1" - wordwrap "~0.0.2" - -optionator@^0.8.1, optionator@^0.8.3: +optionator@^0.8.1: version "0.8.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== @@ -4277,6 +4534,18 @@ optionator@^0.8.1, optionator@^0.8.3: type-check "~0.3.2" word-wrap "~1.2.3" +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -4315,10 +4584,10 @@ p-limit@^1.1.0: dependencies: p-try "^1.0.0" -p-limit@^2.0.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.1.tgz#aa07a788cc3151c939b5131f63570f0dd2009537" - integrity sha512-85Tk+90UCVWvbDavCLKPOLC9vvY8OwEX/RtKF+/1OADJMVlFfEHOiMTPVyxg7mk/dKa+ipdHm0OUkTvCpMTuwg== +p-limit@^2.0.0, p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== dependencies: p-try "^2.0.0" @@ -4336,6 +4605,13 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-map-series@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-map-series/-/p-map-series-1.0.0.tgz#bf98fe575705658a9e1351befb85ae4c1f07bdca" @@ -4423,18 +4699,28 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" +parse-json@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.1.0.tgz#f96088cdf24a8faa9aea9a009f2d9d942c999646" + integrity sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ== + dependencies: + "@babel/code-frame" "^7.0.0" + error-ex "^1.3.1" + json-parse-even-better-errors "^2.3.0" + lines-and-columns "^1.1.6" + parse-path@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.1.tgz#0ec769704949778cb3b8eda5e994c32073a1adff" - integrity sha512-d7yhga0Oc+PwNXDvQ0Jv1BuWkLVPXcAoQ/WREgd6vNNoKYaW52KI+RdOFjI63wjkmps9yUE8VS4veP+AgpQ/hA== + version "4.0.2" + resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.2.tgz#ef14f0d3d77bae8dd4bc66563a4c151aac9e65aa" + integrity sha512-HSqVz6iuXSiL8C1ku5Gl1Z5cwDd9Wo0q8CoffdAghP6bz8pJa1tcMC+m4N+z6VAS8QdksnIGq1TB6EgR4vPR6w== dependencies: is-ssh "^1.3.0" protocols "^1.4.0" parse-url@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-5.0.1.tgz#99c4084fc11be14141efa41b3d117a96fcb9527f" - integrity sha512-flNUPP27r3vJpROi0/R3/2efgKkyXqnXwyP1KQ2U0SfFRgdizOdWfvrrvJg1LuOoxs7GQhmxJlq23IpQ/BkByg== + version "5.0.2" + resolved "https://registry.yarnpkg.com/parse-url/-/parse-url-5.0.2.tgz#856a3be1fcdf78dc93fc8b3791f169072d898b59" + integrity sha512-Czj+GIit4cdWtxo3ISZCvLiUjErSo0iI3wJ+q9Oi3QuMYTI6OZu+7cewMWZ+C1YAnKhYTk6/TLuhIgCypLthPA== dependencies: is-ssh "^1.3.0" normalize-url "^3.3.0" @@ -4463,6 +4749,11 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -4473,6 +4764,11 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -4494,6 +4790,11 @@ path-type@^3.0.0: dependencies: pify "^3.0.0" +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + pathval@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" @@ -4537,7 +4838,7 @@ pgpass@1.x: dependencies: split "^1.0.0" -picomatch@^2.0.4: +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== @@ -4592,9 +4893,9 @@ postgres-bytea@~1.0.0: integrity sha1-AntTPAqokOJtFy1Hz5zOzFIazTU= postgres-date@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.4.tgz#1c2728d62ef1bff49abdd35c1f86d4bdf118a728" - integrity sha512-bESRvKVuTrjoBluEcpv2346+6kgB7UlnqWZsnbnCccTNq/pqfj1j6oBaN5+b/NrDXepYUT/HKadqv3iS9lJuVA== + version "1.0.7" + resolved "https://registry.yarnpkg.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8" + integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q== postgres-interval@^1.1.0: version "1.2.0" @@ -4603,6 +4904,11 @@ postgres-interval@^1.1.0: dependencies: xtend "^4.0.0" +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + prelude-ls@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" @@ -4615,10 +4921,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.4.tgz#2d1bae173e355996ee355ec9830a7a1ee05457ef" - integrity sha512-SVJIQ51spzFDvh4fIbCLvciiDMCrRhlN3mbZvv/+ycjvmF5E73bKdGfU8QDLNmjYJf+lsGnDBC4UUnvTe5OO0w== +prettier@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5" + integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg== process-nextick-args@~2.0.0: version "2.0.1" @@ -4656,9 +4962,9 @@ proto-list@~1.2.1: integrity sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk= protocols@^1.1.0, protocols@^1.4.0: - version "1.4.7" - resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.7.tgz#95f788a4f0e979b291ffefcf5636ad113d037d32" - integrity sha512-Fx65lf9/YDn3hUX08XUc0J8rSux36rEsyiv21ZGUC1mOyeM3lTRpZLcrm8aAolzS4itwVfm7TAPyxC2E5zd6xg== + version "1.4.8" + resolved "https://registry.yarnpkg.com/protocols/-/protocols-1.4.8.tgz#48eea2d8f58d9644a4a32caae5d5db290a075ce8" + integrity sha512-IgjKyaUSjsROSO8/D49Ab7hP8mJgTYcqApOqdPhLoPxAplXmkp+zRvsrSQjFn5by0rhm4VH0GAUELIPpx7B1yg== protoduck@^5.0.1: version "5.0.1" @@ -4667,11 +4973,6 @@ protoduck@^5.0.1: dependencies: genfun "^5.0.0" -psl@^1.1.24: - version "1.6.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.6.0.tgz#60557582ee23b6c43719d9890fb4170ecd91e110" - integrity sha512-SYKKmVel98NCOYXpkwUqZqh0ahZeeKfmisiLIcEZdsb+WbLv02g/dI5BUmZnIyOe7RzZtLax81nnb2HbvC2tzA== - psl@^1.1.28: version "1.8.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" @@ -4702,11 +5003,6 @@ pumpify@^1.3.3: inherits "^2.0.3" pump "^2.0.0" -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= - punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -4727,6 +5023,11 @@ quick-lru@^1.0.0: resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" integrity sha1-Q2CxfGETatOAeDl/8RQW4Ybc+7g= +quick-lru@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-4.0.1.tgz#5b8878f113a58217848c6482026c73e1ba57727f" + integrity sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g== + read-cmd-shim@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/read-cmd-shim/-/read-cmd-shim-1.0.5.tgz#87e43eba50098ba5a32d0ceb583ab8e43b961c16" @@ -4735,16 +5036,14 @@ read-cmd-shim@^1.0.1: graceful-fs "^4.1.2" "read-package-json@1 || 2", read-package-json@^2.0.0, read-package-json@^2.0.13: - version "2.1.1" - resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.1.tgz#16aa66c59e7d4dad6288f179dd9295fd59bb98f1" - integrity sha512-dAiqGtVc/q5doFz6096CcnXhpYk0ZN8dEKVkGLU0CsASt8SrgF6SF7OTKAYubfvFhWaqofl+Y8HK19GR8jwW+A== + version "2.1.2" + resolved "https://registry.yarnpkg.com/read-package-json/-/read-package-json-2.1.2.tgz#6992b2b66c7177259feb8eaac73c3acd28b9222a" + integrity sha512-D1KmuLQr6ZSJS0tW8hf3WGpRlwszJOXZ3E8Yd/DNRaM5d+1wVRZdHlpGBLAuovjr28LbWvjpWkBHMxpRGGjzNA== dependencies: glob "^7.1.1" - json-parse-better-errors "^1.0.1" + json-parse-even-better-errors "^2.3.0" normalize-package-data "^2.0.0" npm-normalize-package-bin "^1.0.0" - optionalDependencies: - graceful-fs "^4.1.2" read-package-tree@^5.1.6: version "5.3.1" @@ -4771,6 +5070,15 @@ read-pkg-up@^3.0.0: find-up "^2.0.0" read-pkg "^3.0.0" +read-pkg-up@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507" + integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg== + dependencies: + find-up "^4.1.0" + read-pkg "^5.2.0" + type-fest "^0.8.1" + read-pkg@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" @@ -4789,6 +5097,16 @@ read-pkg@^3.0.0: normalize-package-data "^2.3.2" path-type "^3.0.0" +read-pkg@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc" + integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg== + dependencies: + "@types/normalize-package-data" "^2.4.0" + normalize-package-data "^2.5.0" + parse-json "^5.0.0" + type-fest "^0.6.0" + read@1, read@~1.0.1: version "1.0.7" resolved "https://registry.yarnpkg.com/read/-/read-1.0.7.tgz#b3da19bd052431a97671d44a42634adf710b40c4" @@ -4797,9 +5115,9 @@ read@1, read@~1.0.1: mute-stream "~0.0.4" "readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@~2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -4810,9 +5128,9 @@ read@1, read@~1.0.1: util-deprecate "~1.0.1" "readable-stream@2 || 3", readable-stream@^3.0.2: - version "3.4.0" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.4.0.tgz#a51c26754658e0a3c21dbf59163bd45ba6f447fc" - integrity sha512-jItXPLmrSR8jmTRmRWJXCnGJsfy85mB3Wd/uINMXA65yrnFo0cPClFIUWzo2najVNSl+mx7/4W8ttlLWJe99pQ== + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== dependencies: inherits "^2.0.3" string_decoder "^1.1.1" @@ -4851,6 +5169,14 @@ redent@^2.0.0: indent-string "^3.0.0" strip-indent "^2.0.0" +redent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" + integrity sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg== + dependencies: + indent-string "^4.0.0" + strip-indent "^3.0.0" + regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -4859,12 +5185,7 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" -regexpp@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" - integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== - -regexpp@^3.0.0: +regexpp@^3.0.0, regexpp@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== @@ -4893,33 +5214,7 @@ repeating@^2.0.0: dependencies: is-finite "^1.0.0" -request@^2.88.0: - version "2.88.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.0" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.4.3" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -request@^2.88.2: +request@^2.88.0, request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -4983,9 +5278,9 @@ resolve@1.1.x: integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs= resolve@^1.10.0, resolve@^1.10.1: - version "1.14.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.0.tgz#6d14c6f9db9f8002071332b600039abf82053f64" - integrity sha512-uviWSi5N67j3t3UKFxej1loCH0VZn5XuqdNxoLShPcYPw6cUZn74K1VRj+9myynRX03bxIBEkwlkob/ujLsJVw== + version "1.17.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" + integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== dependencies: path-parse "^1.0.6" @@ -4997,14 +5292,6 @@ restore-cursor@^2.0.0: onetime "^2.0.0" signal-exit "^3.0.2" -restore-cursor@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" - integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== - dependencies: - onetime "^5.1.0" - signal-exit "^3.0.2" - ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" @@ -5015,6 +5302,11 @@ retry@^0.10.0: resolved "https://registry.yarnpkg.com/retry/-/retry-0.10.1.tgz#e76388d217992c252750241d3d3956fed98d8ff4" integrity sha1-52OI0heZLCUnUCQdPTlW/tmNj/Q= +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" @@ -5030,11 +5322,14 @@ rimraf@^2.5.4, rimraf@^2.6.2, rimraf@^2.6.3: glob "^7.1.3" run-async@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" - integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= - dependencies: - is-promise "^2.1.0" + version "2.4.1" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" + integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== + +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== run-queue@^1.0.0, run-queue@^1.0.3: version "1.0.3" @@ -5043,17 +5338,17 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -rxjs@^6.4.0, rxjs@^6.5.3: - version "6.5.3" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.3.tgz#510e26317f4db91a7eb1de77d9dd9ba0a4899a3a" - integrity sha512-wuYsAYYFdWTAnAaPoKGNhfpWwKZbJW+HgAJ+mImp+Epl7BG8oNWBCTyRM8gba9k4lk8BgWdoYm21Mo/RYhhbgA== +rxjs@^6.4.0: + version "6.6.3" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552" + integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ== dependencies: tslib "^1.9.0" safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" - integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" @@ -5067,7 +5362,7 @@ safe-regex@^1.1.0: dependencies: ret "~0.1.10" -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -5077,11 +5372,16 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== -semver@^6.0.0, semver@^6.1.0, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.0, semver@^6.2.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.2.1, semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -5111,21 +5411,38 @@ shebang-command@^1.2.0: dependencies: shebang-regex "^1.0.0" +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + signal-exit@^3.0.0, signal-exit@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== slash@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/slash/-/slash-2.0.0.tgz#de552851a1759df3a8f206535442f5ec4ddeab44" integrity sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A== +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + slice-ansi@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" @@ -5199,20 +5516,20 @@ sort-keys@^2.0.0: is-plain-obj "^1.0.0" source-map-resolve@^0.5.0: - version "0.5.2" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" - integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== dependencies: - atob "^2.1.1" + atob "^2.1.2" decode-uri-component "^0.2.0" resolve-url "^0.2.1" source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.6: - version "0.5.16" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" - integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== +source-map-support@^0.5.17: + version "0.5.19" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" + integrity sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -5227,7 +5544,7 @@ source-map@^0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -5240,30 +5557,30 @@ source-map@~0.2.0: amdefine ">=0.0.4" spdx-correct@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.0.tgz#fb83e504445268f154b074e218c87c003cd31df4" - integrity sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q== + version "3.1.1" + resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" + integrity sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w== dependencies: spdx-expression-parse "^3.0.0" spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz#2ea450aee74f2a89bfb94519c07fcd6f41322977" - integrity sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" + integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - integrity sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg== + version "3.0.1" + resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679" + integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q== dependencies: spdx-exceptions "^2.1.0" spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.5" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz#3694b5804567a458d3c8045842a6358632f62654" - integrity sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q== + version "3.0.6" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.6.tgz#c80757383c28abf7296744998cbc106ae8b854ce" + integrity sha512-+orQK83kyMva3WyPf59k1+Y525csj5JejicWut55zeTWANuN17qSiSLUXWtzHeNWORSvT7GLDJ/E/XiIWoXBTw== split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" @@ -5376,30 +5693,21 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string-width@^4.1.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" - integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - -string.prototype.trimleft@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.0.tgz#6cc47f0d7eb8d62b0f3701611715a3954591d634" - integrity sha512-FJ6b7EgdKxxbDxc79cOlok6Afd++TTs5szo+zJTUyow3ycrRfJVE2pq3vcN53XexvKZu/DJMDfeI/qMiZTrjTw== +string.prototype.trimend@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" + integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== dependencies: define-properties "^1.1.3" - function-bind "^1.1.1" + es-abstract "^1.17.5" -string.prototype.trimright@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.0.tgz#669d164be9df9b6f7559fa8e89945b168a5a6c58" - integrity sha512-fXZTSV55dNBwv16uw+hh5jkghxSnc5oHq+5K/gXgizHwAvMetdAJlHqqoFC1FSDVPYWLkAKl2cxpUT41sV7nSg== +string.prototype.trimstart@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" + integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== dependencies: define-properties "^1.1.3" - function-bind "^1.1.1" + es-abstract "^1.17.5" string_decoder@^1.1.1: version "1.3.0" @@ -5472,15 +5780,22 @@ strip-indent@^2.0.0: resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-2.0.0.tgz#5ef8db295d01e6ed6cbf7aab96998d7822527b68" integrity sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= +strip-indent@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" + integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ== + dependencies: + min-indent "^1.0.0" + strip-json-comments@2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= -strip-json-comments@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.0.1.tgz#85713975a91fb87bf1b305cca77395e40d2a64a7" - integrity sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw== +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== strong-log-transformer@^2.0.0: version "2.1.0" @@ -5512,6 +5827,13 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + table@^5.2.3: version "5.4.6" resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" @@ -5570,9 +5892,9 @@ thenify-all@^1.0.0: thenify ">= 3.1.0 < 4" "thenify@>= 3.1.0 < 4": - version "3.3.0" - resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" - integrity sha1-5p44obq+lpsBCCB5eLn2K4hgSDk= + version "3.3.1" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f" + integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw== dependencies: any-promise "^1.0.0" @@ -5585,10 +5907,11 @@ through2@^2.0.0, through2@^2.0.2: xtend "~4.0.1" through2@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" - integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== + version "3.0.2" + resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4" + integrity sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ== dependencies: + inherits "^2.0.4" readable-stream "2 || 3" through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@~2.3.4: @@ -5645,14 +5968,6 @@ to-utf8@0.0.1: resolved "https://registry.yarnpkg.com/to-utf8/-/to-utf8-0.0.1.tgz#d17aea72ff2fba39b9e43601be7b3ff72e089852" integrity sha1-0Xrqcv8vujm55DYBvns/9y4ImFI= -tough-cookie@~2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== - dependencies: - psl "^1.1.24" - punycode "^1.4.1" - tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" @@ -5692,31 +6007,31 @@ trim-newlines@^2.0.0: resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-2.0.0.tgz#b403d0b91be50c331dfc4b82eeceb22c3de16d20" integrity sha1-tAPQuRvlDDMd/EuC7s6yLD3hbSA= +trim-newlines@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.0.tgz#79726304a6a898aa8373427298d54c2ee8b1cb30" + integrity sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA== + trim-off-newlines@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM= ts-node@^8.5.4: - version "8.5.4" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.5.4.tgz#a152add11fa19c221d0b48962c210cf467262ab2" - integrity sha512-izbVCRV68EasEPQ8MSIGBNK9dc/4sYJJKYA+IarMQct1RtEot6Xp0bXuClsbUSnKpg50ho+aOAx8en5c+y4OFw== + version "8.10.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d" + integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA== dependencies: arg "^4.1.0" diff "^4.0.1" make-error "^1.1.1" - source-map-support "^0.5.6" - yn "^3.0.0" - -tslib@^1.8.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" - integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== + source-map-support "^0.5.17" + yn "3.1.1" -tslib@^1.9.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" - integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== +tslib@^1.8.1, tslib@^1.9.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tsutils@^3.17.1: version "3.17.1" @@ -5737,6 +6052,13 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" @@ -5749,11 +6071,21 @@ type-detect@^4.0.0, type-detect@^4.0.5: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== +type-fest@^0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" + integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg== + type-fest@^0.3.0: version "0.3.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== +type-fest@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b" + integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg== + type-fest@^0.8.1: version "0.8.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" @@ -5765,17 +6097,14 @@ typedarray@^0.0.6: integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= typescript@^3.7.3: - version "3.7.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.3.tgz#b36840668a16458a7025b9eabfad11b66ab85c69" - integrity sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw== + version "3.9.7" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" + integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== uglify-js@^3.1.4: - version "3.7.2" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.7.2.tgz#cb1a601e67536e9ed094a92dd1e333459643d3f9" - integrity sha512-uhRwZcANNWVLrxLfNFEdltoPNhECUR3lc+UdJoG9CBpMcSnKyWA94tc3eAujB1GcMY5Uwq8ZMp4qWpxWYDQmaA== - dependencies: - commander "~2.20.3" - source-map "~0.6.1" + version "3.11.1" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.11.1.tgz#32d274fea8aac333293044afd7f81409d5040d38" + integrity sha512-OApPSuJcxcnewwjSGGfWOjx3oix5XpmrK9Z2j0fTRlHGoZ49IU6kExfZTM0++fCArOOCet+vIfWwFHbvWqwp6g== uid-number@0.0.6: version "0.0.6" @@ -5812,12 +6141,17 @@ unique-slug@^2.0.0: imurmurhash "^0.1.4" universal-user-agent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.0.tgz#27da2ec87e32769619f68a14996465ea1cb9df16" - integrity sha512-eM8knLpev67iBDizr/YtqkJsF3GK8gzDc6st/WKzrTuPtcsOKW/0IdL4cnMBsU69pOx0otavLWBDGTwg+dB0aA== + version "4.0.1" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.1.tgz#fd8d6cb773a679a709e967ef8288a31fcc03e557" + integrity sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg== dependencies: os-name "^3.1.0" +universal-user-agent@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" + integrity sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w== + universalify@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" @@ -5831,10 +6165,15 @@ unset-value@^1.0.0: has-value "^0.3.1" isobject "^3.0.0" +upath@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + version "4.4.0" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" + integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== dependencies: punycode "^2.1.0" @@ -5861,14 +6200,14 @@ util-promisify@^2.1.0: object.getownpropertydescriptors "^2.0.3" uuid@^3.0.1, uuid@^3.3.2: - version "3.3.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" - integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== v8-compile-cache@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.0.tgz#e14de37b31a6d194f5690d67efc4e7f6fc6ab30e" - integrity sha512-usZBT3PW+LOjM25wbqIlZwPeJV+3OSz3M1k1Ws8snlW39dZyYL9lOGC5FgPVHfk0jKmjiDV8Z0mIbVQPiwFs7g== + version "2.1.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz#54bc3cdd43317bca91e35dcaf305b1a7237de745" + integrity sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ== validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.3: version "3.0.4" @@ -5927,6 +6266,13 @@ which@1.3.1, which@^1.1.1, which@^1.2.9, which@^1.3.1: dependencies: isexe "^2.0.0" +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + wide-align@1.1.3, wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" @@ -5935,13 +6281,13 @@ wide-align@1.1.3, wide-align@^1.1.0: string-width "^1.0.2 || 2" windows-release@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.2.0.tgz#8122dad5afc303d833422380680a79cdfa91785f" - integrity sha512-QTlz2hKLrdqukrsapKsINzqMgOUpQW268eJ0OaOpJN32h272waxR9fkB9VoWRtK7uKHG5EHJcTXQBD8XZVJkFA== + version "3.3.3" + resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.3.tgz#1c10027c7225743eec6b89df160d64c2e0293999" + integrity sha512-OSOGH1QYiW5yVor9TtmXKQvt2vjQqbYS+DqmsZw+r7xDwLXEeT3JGW0ZppFmHx4diyXmxt238KFR3N9jzevBRg== dependencies: execa "^1.0.0" -word-wrap@~1.2.3: +word-wrap@^1.2.3, word-wrap@~1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== @@ -5951,11 +6297,6 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= -wordwrap@~0.0.2: - version "0.0.3" - resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.3.tgz#a3d5da6cd5c0bc0008d37234bbaf1bed63059107" - integrity sha1-o9XabNXAvAAI03I0u68b7WMFkQc= - wrap-ansi@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" @@ -6041,25 +6382,18 @@ yargs-parser@13.1.2, yargs-parser@^13.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^10.0.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" - integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== - dependencies: - camelcase "^4.1.0" - -yargs-parser@^13.1.1: - version "13.1.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0" - integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ== +yargs-parser@^15.0.1: + version "15.0.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.1.tgz#54786af40b820dcb2fb8025b11b4d659d76323b3" + integrity sha512-0OAMV2mAZQrs3FkNpDQcBk1x5HXb8X4twADss4S0Iuk+2dGnLOE/fRHrsYm542GduMveyA77OF4wrNJuanRCWw== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^15.0.0: - version "15.0.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-15.0.0.tgz#cdd7a97490ec836195f59f3f4dbe5ea9e8f75f08" - integrity sha512-xLTUnCMc4JhxrPEPUYD5IBR1mWCK/aT6+RJ/K29JY2y1vD+FhtgKK0AXRWvI262q3QSffAQuTouFIKUuHX89wQ== +yargs-parser@^18.1.3: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== dependencies: camelcase "^5.0.0" decamelize "^1.2.0" @@ -6073,7 +6407,7 @@ yargs-unparser@1.6.0: lodash "^4.17.15" yargs "^13.3.0" -yargs@13.3.2: +yargs@13.3.2, yargs@^13.3.0: version "13.3.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== @@ -6089,26 +6423,10 @@ yargs@13.3.2: y18n "^4.0.0" yargs-parser "^13.1.2" -yargs@^13.3.0: - version "13.3.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.0.tgz#4c657a55e07e5f2cf947f8a366567c04a0dedc83" - integrity sha512-2eehun/8ALW8TLoIl7MVaRUrg+yCnenu8B4kBlRxj3GJGDKU1Og7sMXPNm1BYyM1DOJmTZ4YeN/Nwxv+8XJsUA== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.1" - yargs@^14.2.2: - version "14.2.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.2.tgz#2769564379009ff8597cdd38fba09da9b493c4b5" - integrity sha512-/4ld+4VV5RnrynMhPZJ/ZpOCGSCeghMykZ3BhdFBDa9Wy/RH6uEGNWDJog+aUlq+9OM1CFTgtYRW5Is1Po9NOA== + version "14.2.3" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-14.2.3.tgz#1a1c3edced1afb2a2fea33604bc6d1d8d688a414" + integrity sha512-ZbotRWhF+lkjijC/VhmOT9wSgyBQ7+zr13+YLkhfsSiTriYsMzkTUFP18pFhWwBeMa5gUc1MzbhrO6/VB7c9Xg== dependencies: cliui "^5.0.0" decamelize "^1.2.0" @@ -6120,9 +6438,9 @@ yargs@^14.2.2: string-width "^3.0.0" which-module "^2.0.0" y18n "^4.0.0" - yargs-parser "^15.0.0" + yargs-parser "^15.0.1" -yn@^3.0.0: +yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== From 52dfca493cfaf5b4374921a285925be2c102df29 Mon Sep 17 00:00:00 2001 From: chyzwar Date: Mon, 12 Oct 2020 08:37:40 +0200 Subject: [PATCH 0734/1037] chore(): remove postgres from lint travis task --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1ccd7e5b8..8adb26836 100644 --- a/.travis.yml +++ b/.travis.yml @@ -59,8 +59,6 @@ matrix: # only run lint on latest Node LTS - node_js: lts/* - addons: - postgresql: '9.6' script: yarn lint # PostgreSQL 9.2 only works on precise From 78a14a164d855b08ab0f6c629e8840f66b125478 Mon Sep 17 00:00:00 2001 From: Marcin K Date: Tue, 3 Nov 2020 18:17:49 +0100 Subject: [PATCH 0735/1037] feat(): pg-query-stream typescript (#2376) * feat(): start converting pg-query stream * feat(): solution project, initial version of typescript-pg-query stream * chore(): mocha with typescript * fix(): eslint ignore query stream dist * refactor(pg-query-stream): convert test to ts * chore(): fixed type errors * chore(): fix helper usage * chore(): use ts-node compatibile with node v8 * fix(): addd es extension * chore(): remove emitClose and added compilation for async iterators * chore(): condition for asyc iteration test * chore(): rename class to match ts-defs * chore(): tests to import from src instead of dist * chore(): remove prettier from peer deps: * chore(): update lock file --- .eslintrc | 2 +- package.json | 6 +- packages/pg-protocol/package.json | 8 +- packages/pg-protocol/tsconfig.json | 1 + packages/pg-query-stream/package.json | 17 ++- .../{index.js => src/index.ts} | 43 +++++-- .../pg-query-stream/test/async-iterator.es6 | 112 ----------------- .../pg-query-stream/test/async-iterator.js | 4 - .../pg-query-stream/test/async-iterator.ts | 116 ++++++++++++++++++ .../{client-options.js => client-options.ts} | 15 +-- .../test/{close.js => close.ts} | 32 ++--- .../test/{concat.js => concat.ts} | 17 ++- packages/pg-query-stream/test/config.js | 26 ---- packages/pg-query-stream/test/config.ts | 26 ++++ .../test/{empty-query.js => empty-query.ts} | 5 +- .../test/{error.js => error.ts} | 11 +- .../test/{fast-reader.js => fast-reader.ts} | 16 +-- .../test/{helper.js => helper.ts} | 7 +- packages/pg-query-stream/test/instant.js | 17 --- packages/pg-query-stream/test/instant.ts | 17 +++ .../test/{issue-3.js => issue-3.ts} | 15 +-- ...{passing-options.js => passing-options.ts} | 18 +-- packages/pg-query-stream/test/pauses.js | 23 ---- packages/pg-query-stream/test/pauses.ts | 26 ++++ .../test/{slow-reader.js => slow-reader.ts} | 12 +- .../test/stream-tester-timestamp.js | 25 ---- .../test/stream-tester-timestamp.ts | 26 ++++ .../pg-query-stream/test/stream-tester.js | 12 -- .../pg-query-stream/test/stream-tester.ts | 12 ++ packages/pg-query-stream/tsconfig.json | 26 ++++ tsconfig.json | 12 ++ yarn.lock | 39 ++++-- 32 files changed, 424 insertions(+), 320 deletions(-) rename packages/pg-query-stream/{index.js => src/index.ts} (55%) delete mode 100644 packages/pg-query-stream/test/async-iterator.es6 delete mode 100644 packages/pg-query-stream/test/async-iterator.js create mode 100644 packages/pg-query-stream/test/async-iterator.ts rename packages/pg-query-stream/test/{client-options.js => client-options.ts} (62%) rename packages/pg-query-stream/test/{close.js => close.ts} (72%) rename packages/pg-query-stream/test/{concat.js => concat.ts} (51%) delete mode 100644 packages/pg-query-stream/test/config.js create mode 100644 packages/pg-query-stream/test/config.ts rename packages/pg-query-stream/test/{empty-query.js => empty-query.ts} (82%) rename packages/pg-query-stream/test/{error.js => error.ts} (67%) rename packages/pg-query-stream/test/{fast-reader.js => fast-reader.ts} (69%) rename packages/pg-query-stream/test/{helper.js => helper.ts} (68%) delete mode 100644 packages/pg-query-stream/test/instant.js create mode 100644 packages/pg-query-stream/test/instant.ts rename packages/pg-query-stream/test/{issue-3.js => issue-3.ts} (73%) rename packages/pg-query-stream/test/{passing-options.js => passing-options.ts} (62%) delete mode 100644 packages/pg-query-stream/test/pauses.js create mode 100644 packages/pg-query-stream/test/pauses.ts rename packages/pg-query-stream/test/{slow-reader.js => slow-reader.ts} (61%) delete mode 100644 packages/pg-query-stream/test/stream-tester-timestamp.js create mode 100644 packages/pg-query-stream/test/stream-tester-timestamp.ts delete mode 100644 packages/pg-query-stream/test/stream-tester.js create mode 100644 packages/pg-query-stream/test/stream-tester.ts create mode 100644 packages/pg-query-stream/tsconfig.json create mode 100644 tsconfig.json diff --git a/.eslintrc b/.eslintrc index e03680342..4766b9889 100644 --- a/.eslintrc +++ b/.eslintrc @@ -2,7 +2,7 @@ "plugins": ["prettier"], "parser": "@typescript-eslint/parser", "extends": ["plugin:prettier/recommended", "prettier/@typescript-eslint"], - "ignorePatterns": ["node_modules", "coverage", "packages/pg-protocol/dist/**/*"], + "ignorePatterns": ["node_modules", "coverage", "packages/pg-protocol/dist/**/*", "packages/pg-query-stream/dist/**/*"], "parserOptions": { "ecmaVersion": 2017, "sourceType": "module" diff --git a/package.json b/package.json index 98e3c4e98..d87548d6d 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ ], "scripts": { "test": "yarn lerna exec yarn test", - "build": "yarn lerna exec --scope pg-protocol yarn build", + "build": "tsc --build", + "build:watch": "tsc --build --watch", "pretest": "yarn build", "lint": "eslint '*/**/*.{js,ts,tsx}'" }, @@ -23,7 +24,8 @@ "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^3.1.4", "lerna": "^3.19.0", - "prettier": "2.1.2" + "prettier": "2.1.2", + "typescript": "^4.0.3" }, "prettier": { "semi": false, diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 3ad45e4cb..7fc1eb8ac 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -13,7 +13,7 @@ "chunky": "^0.0.0", "mocha": "^7.1.2", "ts-node": "^8.5.4", - "typescript": "^3.7.3" + "typescript": "^4.0.3" }, "scripts": { "test": "mocha dist/**/*.test.js", @@ -21,5 +21,9 @@ "build:watch": "tsc --watch", "prepublish": "yarn build", "pretest": "yarn build" - } + }, + "files": [ + "/dist/*{js,ts,map}", + "/src" + ] } diff --git a/packages/pg-protocol/tsconfig.json b/packages/pg-protocol/tsconfig.json index bdbe07a39..b273c52d6 100644 --- a/packages/pg-protocol/tsconfig.json +++ b/packages/pg-protocol/tsconfig.json @@ -9,6 +9,7 @@ "moduleResolution": "node", "sourceMap": true, "outDir": "dist", + "incremental": true, "baseUrl": ".", "declaration": true, "paths": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 15da00837..94f9f02d0 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -2,9 +2,10 @@ "name": "pg-query-stream", "version": "3.3.2", "description": "Postgres query result returned as readable stream", - "main": "index.js", + "main": "./dist/index.js", + "types": "./dist/index.d.ts", "scripts": { - "test": "mocha" + "test": "mocha -r ts-node/register test/**/*.ts" }, "repository": { "type": "git", @@ -16,12 +17,20 @@ "query", "stream" ], + "files": [ + "/dist/*{js,ts,map}", + "/src" + ], "author": "Brian M. Carlson", "license": "MIT", "bugs": { "url": "https://github.com/brianc/node-postgres/issues" }, "devDependencies": { + "@types/node": "^14.0.0", + "@types/pg": "^7.14.5", + "@types/chai": "^4.2.13", + "@types/mocha": "^8.0.3", "JSONStream": "~0.7.1", "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", @@ -29,7 +38,9 @@ "pg": "^8.4.2", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", - "through": "~2.3.4" + "through": "~2.3.4", + "ts-node": "^8.5.4", + "typescript": "^4.0.3" }, "dependencies": { "pg-cursor": "^2.4.2" diff --git a/packages/pg-query-stream/index.js b/packages/pg-query-stream/src/index.ts similarity index 55% rename from packages/pg-query-stream/index.js rename to packages/pg-query-stream/src/index.ts index 3806e60aa..c942b0441 100644 --- a/packages/pg-query-stream/index.js +++ b/packages/pg-query-stream/src/index.ts @@ -1,11 +1,30 @@ -const { Readable } = require('stream') -const Cursor = require('pg-cursor') +import { Readable } from 'stream' +import { Submittable, Connection } from 'pg' +import Cursor from 'pg-cursor' -class PgQueryStream extends Readable { - constructor(text, values, config = {}) { +interface QueryStreamConfig { + batchSize?: number + highWaterMark?: number + rowMode?: 'array' + types?: any +} + +class QueryStream extends Readable implements Submittable { + cursor: any + _result: any + + handleRowDescription: Function + handleDataRow: Function + handlePortalSuspended: Function + handleCommandComplete: Function + handleReadyForQuery: Function + handleError: Function + handleEmptyQuery: Function + + public constructor(text: string, values?: any[], config: QueryStreamConfig = {}) { const { batchSize, highWaterMark = 100 } = config - // https://nodejs.org/api/stream.html#stream_new_stream_readable_options - super({ objectMode: true, emitClose: true, autoDestroy: true, highWaterMark: batchSize || highWaterMark }) + + super({ objectMode: true, autoDestroy: true, highWaterMark: batchSize || highWaterMark }) this.cursor = new Cursor(text, values, config) // delegate Submittable callbacks to cursor @@ -21,19 +40,19 @@ class PgQueryStream extends Readable { this._result = this.cursor._result } - submit(connection) { + public submit(connection: Connection): void { this.cursor.submit(connection) } - _destroy(_err, cb) { - this.cursor.close((err) => { + public _destroy(_err: Error, cb: Function) { + this.cursor.close((err?: Error) => { cb(err || _err) }) } // https://nodejs.org/api/stream.html#stream_readable_read_size_1 - _read(size) { - this.cursor.read(size, (err, rows, result) => { + public _read(size: number) { + this.cursor.read(size, (err: Error, rows: any[]) => { if (err) { // https://nodejs.org/api/stream.html#stream_errors_while_reading this.destroy(err) @@ -45,4 +64,4 @@ class PgQueryStream extends Readable { } } -module.exports = PgQueryStream +export = QueryStream diff --git a/packages/pg-query-stream/test/async-iterator.es6 b/packages/pg-query-stream/test/async-iterator.es6 deleted file mode 100644 index 47bda86d2..000000000 --- a/packages/pg-query-stream/test/async-iterator.es6 +++ /dev/null @@ -1,112 +0,0 @@ -const QueryStream = require('../') -const pg = require('pg') -const assert = require('assert') - -const queryText = 'SELECT * FROM generate_series(0, 200) num' -describe('Async iterator', () => { - it('works', async () => { - const stream = new QueryStream(queryText, []) - const client = new pg.Client() - await client.connect() - const query = client.query(stream) - const rows = [] - for await (const row of query) { - rows.push(row) - } - assert.equal(rows.length, 201) - await client.end() - }) - - it('can async iterate and then do a query afterwards', async () => { - const stream = new QueryStream(queryText, []) - const client = new pg.Client() - await client.connect() - const query = client.query(stream) - const iteratorRows = [] - for await (const row of query) { - iteratorRows.push(row) - } - assert.equal(iteratorRows.length, 201) - const { rows } = await client.query('SELECT NOW()') - assert.equal(rows.length, 1) - await client.end() - }) - - it('can async iterate multiple times with a pool', async () => { - const pool = new pg.Pool({ max: 1 }) - - const allRows = [] - const run = async () => { - // get the client - const client = await pool.connect() - // stream some rows - const stream = new QueryStream(queryText, []) - const iteratorRows = [] - client.query(stream) - for await (const row of stream) { - iteratorRows.push(row) - allRows.push(row) - } - assert.equal(iteratorRows.length, 201) - client.release() - } - await Promise.all([run(), run(), run()]) - assert.equal(allRows.length, 603) - await pool.end() - }) - - it('can break out of iteration early', async () => { - const pool = new pg.Pool({ max: 1 }) - const client = await pool.connect() - const rows = [] - for await (const row of client.query(new QueryStream(queryText, [], { batchSize: 1 }))) { - rows.push(row) - break; - } - for await (const row of client.query(new QueryStream(queryText, []))) { - rows.push(row) - break; - } - for await (const row of client.query(new QueryStream(queryText, []))) { - rows.push(row) - break; - } - assert.strictEqual(rows.length, 3) - client.release() - await pool.end() - }) - - it('only returns rows on first iteration', async () => { - const pool = new pg.Pool({ max: 1 }) - const client = await pool.connect() - const rows = [] - const stream = client.query(new QueryStream(queryText, [])) - for await (const row of stream) { - rows.push(row) - break; - } - for await (const row of stream) { - rows.push(row) - } - for await (const row of stream) { - rows.push(row) - } - assert.strictEqual(rows.length, 1) - client.release() - await pool.end() - }) - - it('can read with delays', async () => { - const pool = new pg.Pool({ max: 1 }) - const client = await pool.connect() - const rows = [] - const stream = client.query(new QueryStream(queryText, [], { batchSize: 1 })) - for await (const row of stream) { - rows.push(row) - await new Promise((resolve) => setTimeout(resolve, 1)) - } - assert.strictEqual(rows.length, 201) - client.release() - await pool.end() - }) -}) diff --git a/packages/pg-query-stream/test/async-iterator.js b/packages/pg-query-stream/test/async-iterator.js deleted file mode 100644 index 19718fe3b..000000000 --- a/packages/pg-query-stream/test/async-iterator.js +++ /dev/null @@ -1,4 +0,0 @@ -// only newer versions of node support async iterator -if (!process.version.startsWith('v8')) { - require('./async-iterator.es6') -} diff --git a/packages/pg-query-stream/test/async-iterator.ts b/packages/pg-query-stream/test/async-iterator.ts new file mode 100644 index 000000000..06539d124 --- /dev/null +++ b/packages/pg-query-stream/test/async-iterator.ts @@ -0,0 +1,116 @@ +import QueryStream from '../src' +import pg from 'pg' +import assert from 'assert' + +const queryText = 'SELECT * FROM generate_series(0, 200) num' + +// node v8 do not support async iteration +if (!process.version.startsWith('v8')) { + describe('Async iterator', () => { + it('works', async () => { + const stream = new QueryStream(queryText, []) + const client = new pg.Client() + await client.connect() + const query = client.query(stream) + const rows = [] + for await (const row of query) { + rows.push(row) + } + assert.equal(rows.length, 201) + await client.end() + }) + + it('can async iterate and then do a query afterwards', async () => { + const stream = new QueryStream(queryText, []) + const client = new pg.Client() + await client.connect() + const query = client.query(stream) + const iteratorRows = [] + for await (const row of query) { + iteratorRows.push(row) + } + assert.equal(iteratorRows.length, 201) + const { rows } = await client.query('SELECT NOW()') + assert.equal(rows.length, 1) + await client.end() + }) + + it('can async iterate multiple times with a pool', async () => { + const pool = new pg.Pool({ max: 1 }) + + const allRows = [] + const run = async () => { + // get the client + const client = await pool.connect() + // stream some rows + const stream = new QueryStream(queryText, []) + const iteratorRows = [] + client.query(stream) + for await (const row of stream) { + iteratorRows.push(row) + allRows.push(row) + } + assert.equal(iteratorRows.length, 201) + client.release() + } + await Promise.all([run(), run(), run()]) + assert.equal(allRows.length, 603) + await pool.end() + }) + + it('can break out of iteration early', async () => { + const pool = new pg.Pool({ max: 1 }) + const client = await pool.connect() + const rows = [] + for await (const row of client.query(new QueryStream(queryText, [], { batchSize: 1 }))) { + rows.push(row) + break + } + for await (const row of client.query(new QueryStream(queryText, []))) { + rows.push(row) + break + } + for await (const row of client.query(new QueryStream(queryText, []))) { + rows.push(row) + break + } + assert.strictEqual(rows.length, 3) + client.release() + await pool.end() + }) + + it('only returns rows on first iteration', async () => { + const pool = new pg.Pool({ max: 1 }) + const client = await pool.connect() + const rows = [] + const stream = client.query(new QueryStream(queryText, [])) + for await (const row of stream) { + rows.push(row) + break + } + for await (const row of stream) { + rows.push(row) + } + for await (const row of stream) { + rows.push(row) + } + assert.strictEqual(rows.length, 1) + client.release() + await pool.end() + }) + + it('can read with delays', async () => { + const pool = new pg.Pool({ max: 1 }) + const client = await pool.connect() + const rows = [] + const stream = client.query(new QueryStream(queryText, [], { batchSize: 1 })) + for await (const row of stream) { + rows.push(row) + await new Promise((resolve) => setTimeout(resolve, 1)) + } + assert.strictEqual(rows.length, 201) + client.release() + await pool.end() + }) + }) +} diff --git a/packages/pg-query-stream/test/client-options.js b/packages/pg-query-stream/test/client-options.ts similarity index 62% rename from packages/pg-query-stream/test/client-options.js rename to packages/pg-query-stream/test/client-options.ts index 3820d96b2..6646347fb 100644 --- a/packages/pg-query-stream/test/client-options.js +++ b/packages/pg-query-stream/test/client-options.ts @@ -1,17 +1,18 @@ -var pg = require('pg') -var assert = require('assert') -var QueryStream = require('../') +import pg from 'pg' +import assert from 'assert' +import QueryStream from '../src' describe('client options', function () { it('uses custom types from client config', function (done) { const types = { getTypeParser: () => (string) => string, } - var client = new pg.Client({ types }) + //@ts-expect-error + const client = new pg.Client({ types }) client.connect() - var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num') - var query = client.query(stream) - var result = [] + const stream = new QueryStream('SELECT * FROM generate_series(0, 10) num') + const query = client.query(stream) + const result = [] query.on('data', (datum) => { result.push(datum) }) diff --git a/packages/pg-query-stream/test/close.js b/packages/pg-query-stream/test/close.ts similarity index 72% rename from packages/pg-query-stream/test/close.js rename to packages/pg-query-stream/test/close.ts index 4a95464a7..97e4627d9 100644 --- a/packages/pg-query-stream/test/close.js +++ b/packages/pg-query-stream/test/close.ts @@ -1,16 +1,18 @@ -var assert = require('assert') -var concat = require('concat-stream') - -var QueryStream = require('../') -var helper = require('./helper') +import assert from 'assert' +import concat from 'concat-stream' +import QueryStream from '../src' +import helper from './helper' if (process.version.startsWith('v8.')) { console.error('warning! node less than 10lts stream closing semantics may not behave properly') } else { helper('close', function (client) { it('emits close', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], { batchSize: 2, highWaterMark: 2 }) - var query = client.query(stream) + const stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [3], { + batchSize: 2, + highWaterMark: 2, + }) + const query = client.query(stream) query.pipe(concat(function () {})) query.on('close', done) }) @@ -18,12 +20,12 @@ if (process.version.startsWith('v8.')) { helper('early close', function (client) { it('can be closed early', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [20000], { + const stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [20000], { batchSize: 2, highWaterMark: 2, }) - var query = client.query(stream) - var readCount = 0 + const query = client.query(stream) + let readCount = 0 query.on('readable', function () { readCount++ query.read() @@ -38,7 +40,7 @@ if (process.version.startsWith('v8.')) { }) it('can destroy stream while reading', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') + const stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') client.query(stream) stream.on('data', () => done(new Error('stream should not have returned rows'))) setTimeout(() => { @@ -48,7 +50,7 @@ if (process.version.startsWith('v8.')) { }) it('emits an error when calling destroy with an error', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') + const stream = new QueryStream('SELECT * FROM generate_series(0, 100), pg_sleep(1)') client.query(stream) stream.on('data', () => done(new Error('stream should not have returned rows'))) setTimeout(() => { @@ -63,7 +65,7 @@ if (process.version.startsWith('v8.')) { }) it('can destroy stream while reading an error', function (done) { - var stream = new QueryStream('SELECT * from pg_sleep(1), basdfasdf;') + const stream = new QueryStream('SELECT * from pg_sleep(1), basdfasdf;') client.query(stream) stream.on('data', () => done(new Error('stream should not have returned rows'))) stream.once('error', () => { @@ -74,7 +76,7 @@ if (process.version.startsWith('v8.')) { }) it('does not crash when destroying the stream immediately after calling read', function (done) { - var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') + const stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') client.query(stream) stream.on('data', () => done(new Error('stream should not have returned rows'))) stream.destroy() @@ -82,7 +84,7 @@ if (process.version.startsWith('v8.')) { }) it('does not crash when destroying the stream before its submitted', function (done) { - var stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') + const stream = new QueryStream('SELECT * from generate_series(0, 100), pg_sleep(1);') stream.on('data', () => done(new Error('stream should not have returned rows'))) stream.destroy() stream.on('close', done) diff --git a/packages/pg-query-stream/test/concat.js b/packages/pg-query-stream/test/concat.ts similarity index 51% rename from packages/pg-query-stream/test/concat.js rename to packages/pg-query-stream/test/concat.ts index 6ce17a28e..980038578 100644 --- a/packages/pg-query-stream/test/concat.js +++ b/packages/pg-query-stream/test/concat.ts @@ -1,14 +1,13 @@ -var assert = require('assert') -var concat = require('concat-stream') -var through = require('through') -var helper = require('./helper') - -var QueryStream = require('../') +import assert from 'assert' +import concat from 'concat-stream' +import through from 'through' +import helper from './helper' +import QueryStream from '../src' helper('concat', function (client) { it('concats correctly', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) - var query = client.query(stream) + const stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) + const query = client.query(stream) query .pipe( through(function (row) { @@ -17,7 +16,7 @@ helper('concat', function (client) { ) .pipe( concat(function (result) { - var total = result.reduce(function (prev, cur) { + const total = result.reduce(function (prev, cur) { return prev + cur }) assert.equal(total, 20100) diff --git a/packages/pg-query-stream/test/config.js b/packages/pg-query-stream/test/config.js deleted file mode 100644 index 061fb1153..000000000 --- a/packages/pg-query-stream/test/config.js +++ /dev/null @@ -1,26 +0,0 @@ -var assert = require('assert') -var QueryStream = require('../') - -describe('stream config options', () => { - // this is mostly for backwards compatability. - it('sets readable.highWaterMark based on batch size', () => { - var stream = new QueryStream('SELECT NOW()', [], { - batchSize: 88, - }) - assert.equal(stream._readableState.highWaterMark, 88) - }) - - it('sets readable.highWaterMark based on highWaterMark config', () => { - var stream = new QueryStream('SELECT NOW()', [], { - highWaterMark: 88, - }) - - assert.equal(stream._readableState.highWaterMark, 88) - }) - - it('defaults to 100 for highWaterMark', () => { - var stream = new QueryStream('SELECT NOW()', []) - - assert.equal(stream._readableState.highWaterMark, 100) - }) -}) diff --git a/packages/pg-query-stream/test/config.ts b/packages/pg-query-stream/test/config.ts new file mode 100644 index 000000000..024b3d129 --- /dev/null +++ b/packages/pg-query-stream/test/config.ts @@ -0,0 +1,26 @@ +import assert from 'assert' +import QueryStream from '../src' + +describe('stream config options', () => { + // this is mostly for backwards compatibility. + it('sets readable.highWaterMark based on batch size', () => { + const stream = new QueryStream('SELECT NOW()', [], { + batchSize: 88, + }) + assert.equal(stream.readableHighWaterMark, 88) + }) + + it('sets readable.highWaterMark based on highWaterMark config', () => { + const stream = new QueryStream('SELECT NOW()', [], { + highWaterMark: 88, + }) + + assert.equal(stream.readableHighWaterMark, 88) + }) + + it('defaults to 100 for highWaterMark', () => { + const stream = new QueryStream('SELECT NOW()', []) + + assert.equal(stream.readableHighWaterMark, 100) + }) +}) diff --git a/packages/pg-query-stream/test/empty-query.js b/packages/pg-query-stream/test/empty-query.ts similarity index 82% rename from packages/pg-query-stream/test/empty-query.js rename to packages/pg-query-stream/test/empty-query.ts index 25f7d6956..68f137fe0 100644 --- a/packages/pg-query-stream/test/empty-query.js +++ b/packages/pg-query-stream/test/empty-query.ts @@ -1,6 +1,5 @@ -const assert = require('assert') -const helper = require('./helper') -const QueryStream = require('../') +import helper from './helper' +import QueryStream from '../src' helper('empty-query', function (client) { it('handles empty query', function (done) { diff --git a/packages/pg-query-stream/test/error.js b/packages/pg-query-stream/test/error.ts similarity index 67% rename from packages/pg-query-stream/test/error.js rename to packages/pg-query-stream/test/error.ts index 0b732923d..c92cd0091 100644 --- a/packages/pg-query-stream/test/error.js +++ b/packages/pg-query-stream/test/error.ts @@ -1,12 +1,11 @@ -var assert = require('assert') -var helper = require('./helper') - -var QueryStream = require('../') +import assert from 'assert' +import helper from './helper' +import QueryStream from '../src' helper('error', function (client) { it('receives error on stream', function (done) { - var stream = new QueryStream('SELECT * FROM asdf num', []) - var query = client.query(stream) + const stream = new QueryStream('SELECT * FROM asdf num', []) + const query = client.query(stream) query .on('error', function (err) { assert(err) diff --git a/packages/pg-query-stream/test/fast-reader.js b/packages/pg-query-stream/test/fast-reader.ts similarity index 69% rename from packages/pg-query-stream/test/fast-reader.js rename to packages/pg-query-stream/test/fast-reader.ts index 4c6f31f95..5c0c0214a 100644 --- a/packages/pg-query-stream/test/fast-reader.js +++ b/packages/pg-query-stream/test/fast-reader.ts @@ -1,14 +1,14 @@ -var assert = require('assert') -var helper = require('./helper') -var QueryStream = require('../') +import assert from 'assert' +import helper from './helper' +import QueryStream from '../src' helper('fast reader', function (client) { it('works', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) - var query = client.query(stream) - var result = [] + const stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) + const query = client.query(stream) + const result = [] stream.on('readable', function () { - var res = stream.read() + let res = stream.read() while (res) { if (result.length !== 201) { assert(res, 'should not return null on evented reader') @@ -24,7 +24,7 @@ helper('fast reader', function (client) { } }) stream.on('end', function () { - var total = result.reduce(function (prev, cur) { + const total = result.reduce(function (prev, cur) { return prev + cur }) assert.equal(total, 20100) diff --git a/packages/pg-query-stream/test/helper.js b/packages/pg-query-stream/test/helper.ts similarity index 68% rename from packages/pg-query-stream/test/helper.js rename to packages/pg-query-stream/test/helper.ts index ad21d6ea2..9e9b63a94 100644 --- a/packages/pg-query-stream/test/helper.js +++ b/packages/pg-query-stream/test/helper.ts @@ -1,7 +1,8 @@ -var pg = require('pg') -module.exports = function (name, cb) { +import pg from 'pg' + +export default function (name, cb) { describe(name, function () { - var client = new pg.Client() + const client = new pg.Client() before(function (done) { client.connect(done) diff --git a/packages/pg-query-stream/test/instant.js b/packages/pg-query-stream/test/instant.js deleted file mode 100644 index 0939753bb..000000000 --- a/packages/pg-query-stream/test/instant.js +++ /dev/null @@ -1,17 +0,0 @@ -var assert = require('assert') -var concat = require('concat-stream') - -var QueryStream = require('../') - -require('./helper')('instant', function (client) { - it('instant', function (done) { - var query = new QueryStream('SELECT pg_sleep(1)', []) - var stream = client.query(query) - stream.pipe( - concat(function (res) { - assert.equal(res.length, 1) - done() - }) - ) - }) -}) diff --git a/packages/pg-query-stream/test/instant.ts b/packages/pg-query-stream/test/instant.ts new file mode 100644 index 000000000..da4fcad9e --- /dev/null +++ b/packages/pg-query-stream/test/instant.ts @@ -0,0 +1,17 @@ +import helper from './helper' +import assert from 'assert' +import concat from 'concat-stream' +import QueryStream from '../src' + +helper('instant', function (client) { + it('instant', function (done) { + const query = new QueryStream('SELECT pg_sleep(1)', []) + const stream = client.query(query) + stream.pipe( + concat(function (res) { + assert.equal(res.length, 1) + done() + }) + ) + }) +}) diff --git a/packages/pg-query-stream/test/issue-3.js b/packages/pg-query-stream/test/issue-3.ts similarity index 73% rename from packages/pg-query-stream/test/issue-3.js rename to packages/pg-query-stream/test/issue-3.ts index 7b467a3b3..8c2c04455 100644 --- a/packages/pg-query-stream/test/issue-3.js +++ b/packages/pg-query-stream/test/issue-3.ts @@ -1,8 +1,9 @@ -var pg = require('pg') -var QueryStream = require('../') +import pg from 'pg' +import QueryStream from '../src' + describe('end semantics race condition', function () { before(function (done) { - var client = new pg.Client() + const client = new pg.Client() client.connect() client.on('drain', client.end.bind(client)) client.on('end', done) @@ -10,14 +11,14 @@ describe('end semantics race condition', function () { client.query('create table IF NOT EXISTS c(id int primary key references p)') }) it('works', function (done) { - var client1 = new pg.Client() + const client1 = new pg.Client() client1.connect() - var client2 = new pg.Client() + const client2 = new pg.Client() client2.connect() - var qr = new QueryStream('INSERT INTO p DEFAULT VALUES RETURNING id') + const qr = new QueryStream('INSERT INTO p DEFAULT VALUES RETURNING id') client1.query(qr) - var id = null + let id = null qr.on('data', function (row) { id = row.id }) diff --git a/packages/pg-query-stream/test/passing-options.js b/packages/pg-query-stream/test/passing-options.ts similarity index 62% rename from packages/pg-query-stream/test/passing-options.js rename to packages/pg-query-stream/test/passing-options.ts index 858767de2..7aa924a04 100644 --- a/packages/pg-query-stream/test/passing-options.js +++ b/packages/pg-query-stream/test/passing-options.ts @@ -1,12 +1,12 @@ -var assert = require('assert') -var helper = require('./helper') -var QueryStream = require('../') +import assert from 'assert' +import helper from './helper' +import QueryStream from '../src' helper('passing options', function (client) { it('passes row mode array', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { rowMode: 'array' }) - var query = client.query(stream) - var result = [] + const stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { rowMode: 'array' }) + const query = client.query(stream) + const result = [] query.on('data', (datum) => { result.push(datum) }) @@ -21,9 +21,9 @@ helper('passing options', function (client) { const types = { getTypeParser: () => (string) => string, } - var stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { types }) - var query = client.query(stream) - var result = [] + const stream = new QueryStream('SELECT * FROM generate_series(0, 10) num', [], { types }) + const query = client.query(stream) + const result = [] query.on('data', (datum) => { result.push(datum) }) diff --git a/packages/pg-query-stream/test/pauses.js b/packages/pg-query-stream/test/pauses.js deleted file mode 100644 index 3da9a0b07..000000000 --- a/packages/pg-query-stream/test/pauses.js +++ /dev/null @@ -1,23 +0,0 @@ -var concat = require('concat-stream') -var tester = require('stream-tester') -var JSONStream = require('JSONStream') - -var QueryStream = require('../') - -require('./helper')('pauses', function (client) { - it('pauses', function (done) { - this.timeout(5000) - var stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], { batchSize: 2, highWaterMark: 2 }) - var query = client.query(stream) - var pauser = tester.createPauseStream(0.1, 100) - query - .pipe(JSONStream.stringify()) - .pipe(pauser) - .pipe( - concat(function (json) { - JSON.parse(json) - done() - }) - ) - }) -}) diff --git a/packages/pg-query-stream/test/pauses.ts b/packages/pg-query-stream/test/pauses.ts new file mode 100644 index 000000000..daf8347af --- /dev/null +++ b/packages/pg-query-stream/test/pauses.ts @@ -0,0 +1,26 @@ +import helper from './helper' +import concat from 'concat-stream' +import tester from 'stream-tester' +import JSONStream from 'JSONStream' +import QueryStream from '../src' + +helper('pauses', function (client) { + it('pauses', function (done) { + this.timeout(5000) + const stream = new QueryStream('SELECT * FROM generate_series(0, $1) num', [200], { + batchSize: 2, + highWaterMark: 2, + }) + const query = client.query(stream) + const pauser = tester.createPauseStream(0.1, 100) + query + .pipe(JSONStream.stringify()) + .pipe(pauser) + .pipe( + concat(function (json) { + JSON.parse(json) + done() + }) + ) + }) +}) diff --git a/packages/pg-query-stream/test/slow-reader.js b/packages/pg-query-stream/test/slow-reader.ts similarity index 61% rename from packages/pg-query-stream/test/slow-reader.js rename to packages/pg-query-stream/test/slow-reader.ts index 3978f3004..a62c0c20c 100644 --- a/packages/pg-query-stream/test/slow-reader.js +++ b/packages/pg-query-stream/test/slow-reader.ts @@ -1,10 +1,10 @@ -var helper = require('./helper') -var QueryStream = require('../') -var concat = require('concat-stream') +import helper from './helper' +import QueryStream from '../src' +import concat from 'concat-stream' -var Transform = require('stream').Transform +import { Transform } from 'stream' -var mapper = new Transform({ objectMode: true }) +const mapper = new Transform({ objectMode: true }) mapper._transform = function (obj, enc, cb) { this.push(obj) @@ -14,7 +14,7 @@ mapper._transform = function (obj, enc, cb) { helper('slow reader', function (client) { it('works', function (done) { this.timeout(50000) - var stream = new QueryStream('SELECT * FROM generate_series(0, 201) num', [], { + const stream = new QueryStream('SELECT * FROM generate_series(0, 201) num', [], { highWaterMark: 100, batchSize: 50, }) diff --git a/packages/pg-query-stream/test/stream-tester-timestamp.js b/packages/pg-query-stream/test/stream-tester-timestamp.js deleted file mode 100644 index ce989cc3f..000000000 --- a/packages/pg-query-stream/test/stream-tester-timestamp.js +++ /dev/null @@ -1,25 +0,0 @@ -var QueryStream = require('../') -var spec = require('stream-spec') -var assert = require('assert') - -require('./helper')('stream tester timestamp', function (client) { - it('should not warn about max listeners', function (done) { - var sql = "SELECT * FROM generate_series('1983-12-30 00:00'::timestamp, '2013-12-30 00:00', '1 years')" - var stream = new QueryStream(sql, []) - var ended = false - var query = client.query(stream) - query.on('end', function () { - ended = true - }) - spec(query).readable().pausable({ strict: true }).validateOnExit() - var checkListeners = function () { - assert(stream.listeners('end').length < 10) - if (!ended) { - setImmediate(checkListeners) - } else { - done() - } - } - checkListeners() - }) -}) diff --git a/packages/pg-query-stream/test/stream-tester-timestamp.ts b/packages/pg-query-stream/test/stream-tester-timestamp.ts new file mode 100644 index 000000000..9819ba491 --- /dev/null +++ b/packages/pg-query-stream/test/stream-tester-timestamp.ts @@ -0,0 +1,26 @@ +import helper from './helper' +import QueryStream from '../src' +import spec from 'stream-spec' +import assert from 'assert' + +helper('stream tester timestamp', function (client) { + it('should not warn about max listeners', function (done) { + const sql = "SELECT * FROM generate_series('1983-12-30 00:00'::timestamp, '2013-12-30 00:00', '1 years')" + const stream = new QueryStream(sql, []) + let ended = false + const query = client.query(stream) + query.on('end', function () { + ended = true + }) + spec(query).readable().pausable({ strict: true }).validateOnExit() + const checkListeners = function () { + assert(stream.listeners('end').length < 10) + if (!ended) { + setImmediate(checkListeners) + } else { + done() + } + } + checkListeners() + }) +}) diff --git a/packages/pg-query-stream/test/stream-tester.js b/packages/pg-query-stream/test/stream-tester.js deleted file mode 100644 index f5ab2e372..000000000 --- a/packages/pg-query-stream/test/stream-tester.js +++ /dev/null @@ -1,12 +0,0 @@ -var spec = require('stream-spec') - -var QueryStream = require('../') - -require('./helper')('stream tester', function (client) { - it('passes stream spec', function (done) { - var stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) - var query = client.query(stream) - spec(query).readable().pausable({ strict: true }).validateOnExit() - stream.on('end', done) - }) -}) diff --git a/packages/pg-query-stream/test/stream-tester.ts b/packages/pg-query-stream/test/stream-tester.ts new file mode 100644 index 000000000..01c68275c --- /dev/null +++ b/packages/pg-query-stream/test/stream-tester.ts @@ -0,0 +1,12 @@ +import spec from 'stream-spec' +import helper from './helper' +import QueryStream from '../src' + +helper('stream tester', function (client) { + it('passes stream spec', function (done) { + const stream = new QueryStream('SELECT * FROM generate_series(0, 200) num', []) + const query = client.query(stream) + spec(query).readable().pausable({ strict: true }).validateOnExit() + stream.on('end', done) + }) +}) diff --git a/packages/pg-query-stream/tsconfig.json b/packages/pg-query-stream/tsconfig.json new file mode 100644 index 000000000..15b962dd9 --- /dev/null +++ b/packages/pg-query-stream/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "module": "commonjs", + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "strict": false, + "target": "es6", + "noImplicitAny": false, + "moduleResolution": "node", + "sourceMap": true, + "pretty": true, + "outDir": "dist", + "incremental": true, + "baseUrl": ".", + "declaration": true, + "types": [ + "node", + "pg", + "mocha", + "chai" + ] + }, + "include": [ + "src/**/*" + ] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 000000000..53fb70c6e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "strict": true, + "incremental": true, + "composite": true + }, + "include": [], + "references": [ + {"path": "./packages/pg-query-stream"}, + {"path": "./packages/pg-protocol"} + ] +} diff --git a/yarn.lock b/yarn.lock index 04b915afa..a9273e00c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -941,7 +941,7 @@ dependencies: "@types/node" ">= 8" -"@types/chai@^4.2.7": +"@types/chai@^4.2.13", "@types/chai@^4.2.7": version "4.2.13" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.13.tgz#8a3801f6655179d1803d81e94a2e4aaf317abd16" integrity sha512-o3SGYRlOpvLFpwJA6Sl1UPOwKFEvE4FxTEB/c9XHI2whdnd4kmPVkNLL8gY4vWGBxWWDumzLbKsAhEH5SKn37Q== @@ -974,21 +974,44 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== +"@types/mocha@^8.0.3": + version "8.0.3" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.0.3.tgz#51b21b6acb6d1b923bbdc7725c38f9f455166402" + integrity sha512-vyxR57nv8NfcU0GZu8EUXZLTbCMupIUwy95LJ6lllN+JRPG25CwMHoB1q5xKh8YKhQnHYRAn4yW2yuHbf/5xgg== + "@types/node@*", "@types/node@>= 8": - version "14.11.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.8.tgz#fe2012f2355e4ce08bca44aeb3abbb21cf88d33f" - integrity sha512-KPcKqKm5UKDkaYPTuXSx8wEP7vE9GnuaXIZKijwRYcePpZFDVuy2a57LarFKiORbHOuTOOwYzxVxcUzsh2P2Pw== + version "12.12.21" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.21.tgz#aa44a6363291c7037111c47e4661ad210aded23f" + integrity sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA== "@types/node@^12.12.21": version "12.12.67" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.67.tgz#4f86badb292e822e3b13730a1f9713ed2377f789" integrity sha512-R48tgL2izApf+9rYNH+3RBMbRpPeW3N8f0I9HMhggeq4UXwBDqumJ14SDs4ctTMhG11pIOduZ4z3QWGOiMc9Vg== +"@types/node@^14.0.0": + version "14.11.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.11.8.tgz#fe2012f2355e4ce08bca44aeb3abbb21cf88d33f" + integrity sha512-KPcKqKm5UKDkaYPTuXSx8wEP7vE9GnuaXIZKijwRYcePpZFDVuy2a57LarFKiORbHOuTOOwYzxVxcUzsh2P2Pw== + "@types/normalize-package-data@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== +"@types/pg-types@*": + version "1.11.5" + resolved "https://registry.yarnpkg.com/@types/pg-types/-/pg-types-1.11.5.tgz#1eebbe62b6772fcc75c18957a90f933d155e005b" + integrity sha512-L8ogeT6vDzT1vxlW3KITTCt+BVXXVkLXfZ/XNm6UqbcJgxf+KPO7yjWx7dQQE8RW07KopL10x2gNMs41+IkMGQ== + +"@types/pg@^7.14.5": + version "7.14.5" + resolved "https://registry.yarnpkg.com/@types/pg/-/pg-7.14.5.tgz#07638c7aa69061abe4be31267028cc5c3fc35f98" + integrity sha512-wqTKZmqkqXd1YiVRBT2poRrMIojwEi2bKTAAjUX6nEbzr98jc3cfR/7o7ZtubhH5xT7YJ6LRdRr1GZOgs8OUjg== + dependencies: + "@types/node" "*" + "@types/pg-types" "*" + "@typescript-eslint/eslint-plugin@^4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.4.0.tgz#0321684dd2b902c89128405cf0385e9fe8561934" @@ -6096,10 +6119,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^3.7.3: - version "3.9.7" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" - integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== +typescript@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.3.tgz#153bbd468ef07725c1df9c77e8b453f8d36abba5" + integrity sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg== uglify-js@^3.1.4: version "3.11.1" From 07988f985a492c85195c6cdc928f79816af94c66 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 4 Nov 2020 08:27:40 -0600 Subject: [PATCH 0736/1037] Speed up `bind` functionality (#2286) Move from 3 loops (prepareValue, check for buffers, write param types, write param values) to a single loop. This speeds up the insert benchmark by around 100 queries per second. Performance improvement depends on number of parameters being bound. --- packages/pg-protocol/src/buffer-writer.ts | 4 +- .../src/outbound-serializer.test.ts | 29 +++++++ packages/pg-protocol/src/serializer.ts | 80 +++++++++++-------- packages/pg/bench.js | 59 +++++++------- packages/pg/lib/query.js | 28 +++---- packages/pg/lib/utils.js | 7 +- 6 files changed, 125 insertions(+), 82 deletions(-) diff --git a/packages/pg-protocol/src/buffer-writer.ts b/packages/pg-protocol/src/buffer-writer.ts index 3a8d80b30..756cdc9f3 100644 --- a/packages/pg-protocol/src/buffer-writer.ts +++ b/packages/pg-protocol/src/buffer-writer.ts @@ -5,7 +5,7 @@ export class Writer { private offset: number = 5 private headerPosition: number = 0 constructor(private size = 256) { - this.buffer = Buffer.alloc(size) + this.buffer = Buffer.allocUnsafe(size) } private ensure(size: number): void { @@ -15,7 +15,7 @@ export class Writer { // exponential growth factor of around ~ 1.5 // https://stackoverflow.com/questions/2269063/buffer-growth-strategy var newSize = oldBuffer.length + (oldBuffer.length >> 1) + size - this.buffer = Buffer.alloc(newSize) + this.buffer = Buffer.allocUnsafe(newSize) oldBuffer.copy(this.buffer) } } diff --git a/packages/pg-protocol/src/outbound-serializer.test.ts b/packages/pg-protocol/src/outbound-serializer.test.ts index 06f20cf9c..f6669becd 100644 --- a/packages/pg-protocol/src/outbound-serializer.test.ts +++ b/packages/pg-protocol/src/outbound-serializer.test.ts @@ -110,6 +110,10 @@ describe('serializer', () => { var expectedBuffer = new BufferList() .addCString('bang') // portal name .addCString('woo') // statement name + .addInt16(4) + .addInt16(0) + .addInt16(0) + .addInt16(0) .addInt16(0) .addInt16(4) .addInt32(1) @@ -125,6 +129,31 @@ describe('serializer', () => { }) }) + it('with custom valueMapper', function () { + const actual = serialize.bind({ + portal: 'bang', + statement: 'woo', + values: ['1', 'hi', null, 'zing'], + valueMapper: () => null, + }) + var expectedBuffer = new BufferList() + .addCString('bang') // portal name + .addCString('woo') // statement name + .addInt16(4) + .addInt16(0) + .addInt16(0) + .addInt16(0) + .addInt16(0) + .addInt16(4) + .addInt32(-1) + .addInt32(-1) + .addInt32(-1) + .addInt32(-1) + .addInt16(0) + .join(true, 'B') + assert.deepEqual(actual, expectedBuffer) + }) + it('with named statement, portal, and buffer value', function () { const actual = serialize.bind({ portal: 'bang', diff --git a/packages/pg-protocol/src/serializer.ts b/packages/pg-protocol/src/serializer.ts index bff2fd332..07e2fe498 100644 --- a/packages/pg-protocol/src/serializer.ts +++ b/packages/pg-protocol/src/serializer.ts @@ -101,11 +101,46 @@ const parse = (query: ParseOpts): Buffer => { return writer.flush(code.parse) } +type ValueMapper = (param: any, index: number) => any + type BindOpts = { portal?: string binary?: boolean statement?: string values?: any[] + // optional map from JS value to postgres value per parameter + valueMapper?: ValueMapper +} + +const paramWriter = new Writer() + +// make this a const enum so typescript will inline the value +const enum ParamType { + STRING = 0, + BINARY = 1, +} + +const writeValues = function (values: any[], valueMapper?: ValueMapper): void { + for (let i = 0; i < values.length; i++) { + const mappedVal = valueMapper ? valueMapper(values[i], i) : values[i] + if (mappedVal == null) { + // add the param type (string) to the writer + writer.addInt16(ParamType.STRING) + // write -1 to the param writer to indicate null + paramWriter.addInt32(-1) + } else if (mappedVal instanceof Buffer) { + // add the param type (binary) to the writer + writer.addInt16(ParamType.BINARY) + // add the buffer to the param writer + paramWriter.addInt32(mappedVal.length) + paramWriter.add(mappedVal) + } else { + // add the param type (string) to the writer + writer.addInt16(ParamType.STRING) + paramWriter.addInt32(Buffer.byteLength(mappedVal)) + paramWriter.addString(mappedVal) + } + } } const bind = (config: BindOpts = {}): Buffer => { @@ -113,44 +148,19 @@ const bind = (config: BindOpts = {}): Buffer => { const portal = config.portal || '' const statement = config.statement || '' const binary = config.binary || false - var values = config.values || emptyArray - var len = values.length + const values = config.values || emptyArray + const len = values.length - var useBinary = false - // TODO(bmc): all the loops in here aren't nice, we can do better - for (var j = 0; j < len; j++) { - useBinary = useBinary || values[j] instanceof Buffer - } + writer.addCString(portal).addCString(statement) + writer.addInt16(len) - var buffer = writer.addCString(portal).addCString(statement) - if (!useBinary) { - buffer.addInt16(0) - } else { - buffer.addInt16(len) - for (j = 0; j < len; j++) { - buffer.addInt16(values[j] instanceof Buffer ? 1 : 0) - } - } - buffer.addInt16(len) - for (var i = 0; i < len; i++) { - var val = values[i] - if (val === null || typeof val === 'undefined') { - buffer.addInt32(-1) - } else if (val instanceof Buffer) { - buffer.addInt32(val.length) - buffer.add(val) - } else { - buffer.addInt32(Buffer.byteLength(val)) - buffer.addString(val) - } - } + writeValues(values, config.valueMapper) - if (binary) { - buffer.addInt16(1) // format codes to use binary - buffer.addInt16(1) - } else { - buffer.addInt16(0) // format codes to use text - } + writer.addInt16(len) + writer.add(paramWriter.flush()) + + // format code + writer.addInt16(binary ? ParamType.BINARY : ParamType.STRING) return writer.flush(code.bind) } diff --git a/packages/pg/bench.js b/packages/pg/bench.js index a668aa85f..5cb42ac78 100644 --- a/packages/pg/bench.js +++ b/packages/pg/bench.js @@ -45,37 +45,40 @@ const run = async () => { console.log('warmup done') const seconds = 5 - let queries = await bench(client, params, seconds * 1000) - console.log('') - console.log('little queries:', queries) - console.log('qps', queries / seconds) - console.log('on my laptop best so far seen 733 qps') + for (let i = 0; i < 4; i++) { + let queries = await bench(client, params, seconds * 1000) + console.log('') + console.log('little queries:', queries) + console.log('qps', queries / seconds) + console.log('on my laptop best so far seen 733 qps') - console.log('') - queries = await bench(client, seq, seconds * 1000) - console.log('sequence queries:', queries) - console.log('qps', queries / seconds) - console.log('on my laptop best so far seen 1309 qps') + console.log('') + queries = await bench(client, seq, seconds * 1000) + console.log('sequence queries:', queries) + console.log('qps', queries / seconds) + console.log('on my laptop best so far seen 1309 qps') - console.log('') - queries = await bench(client, insert, seconds * 1000) - console.log('insert queries:', queries) - console.log('qps', queries / seconds) - console.log('on my laptop best so far seen 6303 qps') + console.log('') + queries = await bench(client, insert, seconds * 1000) + console.log('insert queries:', queries) + console.log('qps', queries / seconds) + console.log('on my laptop best so far seen 6445 qps') - console.log('') - console.log('Warming up bytea test') - await client.query({ - text: 'INSERT INTO buf(name, data) VALUES ($1, $2)', - values: ['test', Buffer.allocUnsafe(104857600)], - }) - console.log('bytea warmup done') - const start = Date.now() - const results = await client.query('SELECT * FROM buf') - const time = Date.now() - start - console.log('bytea time:', time, 'ms') - console.log('bytea length:', results.rows[0].data.byteLength, 'bytes') - console.log('on my laptop best so far seen 1107ms and 104857600 bytes') + console.log('') + console.log('Warming up bytea test') + await client.query({ + text: 'INSERT INTO buf(name, data) VALUES ($1, $2)', + values: ['test', Buffer.allocUnsafe(104857600)], + }) + console.log('bytea warmup done') + const start = Date.now() + const results = await client.query('SELECT * FROM buf') + const time = Date.now() - start + console.log('bytea time:', time, 'ms') + console.log('bytea length:', results.rows[0].data.byteLength, 'bytes') + console.log('on my laptop best so far seen 1107ms and 104857600 bytes') + await new Promise((resolve) => setTimeout(resolve, 250)) + } await client.end() await client.end() diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index 3e3c5a640..c0dfedd1e 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -197,22 +197,22 @@ class Query extends EventEmitter { }) } - if (this.values) { - try { - this.values = this.values.map(utils.prepareValue) - } catch (err) { - this.handleError(err, connection) - return - } + // because we're mapping user supplied values to + // postgres wire protocol compatible values it could + // throw an exception, so try/catch this section + try { + connection.bind({ + portal: this.portal, + statement: this.name, + values: this.values, + binary: this.binary, + valueMapper: utils.prepareValue, + }) + } catch (err) { + this.handleError(err, connection) + return } - connection.bind({ - portal: this.portal, - statement: this.name, - values: this.values, - binary: this.binary, - }) - connection.describe({ type: 'P', name: this.portal || '', diff --git a/packages/pg/lib/utils.js b/packages/pg/lib/utils.js index b3b4ff4c1..d63fe68f1 100644 --- a/packages/pg/lib/utils.js +++ b/packages/pg/lib/utils.js @@ -38,6 +38,10 @@ function arrayString(val) { // note: you can override this function to provide your own conversion mechanism // for complex types, etc... var prepareValue = function (val, seen) { + // null and undefined are both null for postgres + if (val == null) { + return null + } if (val instanceof Buffer) { return val } @@ -58,9 +62,6 @@ var prepareValue = function (val, seen) { if (Array.isArray(val)) { return arrayString(val) } - if (val === null || typeof val === 'undefined') { - return null - } if (typeof val === 'object') { return prepareObject(val, seen) } From 8bed670aee111a92dc010b8e661778c6c815a241 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Thu, 5 Nov 2020 16:07:49 -0800 Subject: [PATCH 0737/1037] Add more error handling to error handling tests --- .../client/error-handling-tests.js | 39 ++++++++++++------- packages/pg/test/test-helper.js | 9 +++++ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/packages/pg/test/integration/client/error-handling-tests.js b/packages/pg/test/integration/client/error-handling-tests.js index 93959e02b..88e6d39f7 100644 --- a/packages/pg/test/integration/client/error-handling-tests.js +++ b/packages/pg/test/integration/client/error-handling-tests.js @@ -19,7 +19,10 @@ const suite = new helper.Suite('error handling') suite.test('sending non-array argument as values causes an error callback', (done) => { const client = new Client() - client.connect(() => { + client.connect((err) => { + if (err) { + return done(err) + } client.query('select $1::text as name', 'foo', (err) => { assert(err instanceof Error) client.query('SELECT $1::text as name', ['foo'], (err, res) => { @@ -32,7 +35,10 @@ suite.test('sending non-array argument as values causes an error callback', (don suite.test('re-using connections results in error callback', (done) => { const client = new Client() - client.connect(() => { + client.connect((err) => { + if (err) { + return done(err) + } client.connect((err) => { assert(err instanceof Error) client.end(done) @@ -40,19 +46,22 @@ suite.test('re-using connections results in error callback', (done) => { }) }) -suite.test('re-using connections results in promise rejection', (done) => { +suite.testAsync('re-using connections results in promise rejection', () => { const client = new Client() - client.connect().then(() => { - client.connect().catch((err) => { + return client.connect().then(() => { + return helper.rejection(client.connect()).then((err) => { assert(err instanceof Error) - client.end().then(done) + return client.end() }) }) }) suite.test('using a client after closing it results in error', (done) => { const client = new Client() - client.connect(() => { + client.connect((err) => { + if (err) { + return done(err) + } client.end( assert.calls(() => { client.query( @@ -227,12 +236,16 @@ suite.test('connected, idle client error', (done) => { suite.test('cannot pass non-string values to query as text', (done) => { const client = new Client() - client.connect() - client.query({ text: {} }, (err) => { - assert(err) - client.query({}, (err) => { - client.on('drain', () => { - client.end(done) + client.connect((err) => { + if (err) { + return done(err) + } + client.query({ text: {} }, (err) => { + assert(err) + client.query({}, (err) => { + client.on('drain', () => { + client.end(done) + }) }) }) }) diff --git a/packages/pg/test/test-helper.js b/packages/pg/test/test-helper.js index 4ca9da1b3..319b8ee79 100644 --- a/packages/pg/test/test-helper.js +++ b/packages/pg/test/test-helper.js @@ -232,6 +232,14 @@ var resetTimezoneOffset = function () { Date.prototype.getTimezoneOffset = getTimezoneOffset } +const rejection = (promise) => + promise.then( + (value) => { + throw new Error(`Promise resolved when rejection was expected; value: ${sys.inspect(value)}`) + }, + (error) => error + ) + module.exports = { Sink: Sink, Suite: Suite, @@ -242,4 +250,5 @@ module.exports = { Client: Client, setTimezoneOffset: setTimezoneOffset, resetTimezoneOffset: resetTimezoneOffset, + rejection: rejection, } From 0012a43d956b1b47fc5ddf1eca5894b64f7ccf24 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Mon, 9 Nov 2020 17:30:40 +0000 Subject: [PATCH 0738/1037] =?UTF-8?q?Forward=20options=E2=80=99=20ssl.key?= =?UTF-8?q?=20even=20when=20non-enumerable=20(#2394)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Test client certificate authentication * Forward options’ ssl.key even when non-enumerable --- .travis.yml | 32 +++++++++ packages/pg/lib/connection.js | 18 +++-- .../integration/connection-pool/tls-tests.js | 23 ++++++ packages/pg/test/tls/GNUmakefile | 71 +++++++++++++++++++ packages/pg/test/tls/test-client-ca.crt | 11 +++ packages/pg/test/tls/test-client-ca.key | 5 ++ packages/pg/test/tls/test-client.crt | 9 +++ packages/pg/test/tls/test-client.key | 5 ++ packages/pg/test/tls/test-server-ca.crt | 11 +++ packages/pg/test/tls/test-server-ca.key | 5 ++ packages/pg/test/tls/test-server.crt | 9 +++ packages/pg/test/tls/test-server.key | 5 ++ 12 files changed, 198 insertions(+), 6 deletions(-) create mode 100644 packages/pg/test/integration/connection-pool/tls-tests.js create mode 100644 packages/pg/test/tls/GNUmakefile create mode 100644 packages/pg/test/tls/test-client-ca.crt create mode 100644 packages/pg/test/tls/test-client-ca.key create mode 100644 packages/pg/test/tls/test-client.crt create mode 100644 packages/pg/test/tls/test-client.key create mode 100644 packages/pg/test/tls/test-server-ca.crt create mode 100644 packages/pg/test/tls/test-server-ca.key create mode 100644 packages/pg/test/tls/test-server.crt create mode 100644 packages/pg/test/tls/test-server.key diff --git a/.travis.yml b/.travis.yml index 8adb26836..011bd9e01 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,6 +43,38 @@ matrix: postgresql: '9.5' dist: precise + # Run tests/paths with client certificate authentication + - node_js: lts/* + env: + - CC=clang CXX=clang++ npm_config_clang=1 PGUSER=postgres PGDATABASE=postgres + PGSSLMODE=verify-full + PGSSLROOTCERT=$TRAVIS_BUILD_DIR/packages/pg/test/tls/test-server-ca.crt + PGSSLCERT=$TRAVIS_BUILD_DIR/packages/pg/test/tls/test-client.crt + PGSSLKEY=$TRAVIS_BUILD_DIR/packages/pg/test/tls/test-client.key + PG_CLIENT_CERT_TEST=1 + before_script: + - chmod go= packages/pg/test/tls/test-client.key + - | + sudo sed -i \ + -e '/^ssl_cert_file =/d' \ + -e '/^ssl_key_file =/d' \ + /etc/postgresql/10/main/postgresql.conf + + cat <<'travis ci breaks heredoc' | sudo tee -a /etc/postgresql/10/main/postgresql.conf > /dev/null + ssl_cert_file = 'test-server.crt' + ssl_key_file = 'test-server.key' + ssl_ca_file = 'test-client-ca.crt' + + - printf 'hostssl all all %s cert\n' 127.0.0.1/32 ::1/128 | sudo tee /etc/postgresql/10/main/pg_hba.conf > /dev/null + - sudo make -C packages/pg/test/tls install DESTDIR=/var/ramfs/postgresql/10/main + - sudo systemctl restart postgresql@10-main + - yarn build + script: + - cd packages/pg + - node test/integration/connection-pool/tls-tests.js + - npm install --no-save pg-native + - node test/integration/connection-pool/tls-tests.js native + # different PostgreSQL versions on Node LTS - node_js: lts/erbium addons: diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 6bc0952e0..ccb6742c5 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -76,12 +76,18 @@ class Connection extends EventEmitter { return self.emit('error', new Error('There was an error establishing an SSL connection')) } var tls = require('tls') - const options = Object.assign( - { - socket: self.stream, - }, - self.ssl - ) + const options = { + socket: self.stream, + } + + if (self.ssl !== true) { + Object.assign(options, self.ssl) + + if ('key' in self.ssl) { + options.key = self.ssl.key + } + } + if (net.isIP(host) === 0) { options.servername = host } diff --git a/packages/pg/test/integration/connection-pool/tls-tests.js b/packages/pg/test/integration/connection-pool/tls-tests.js new file mode 100644 index 000000000..f85941d45 --- /dev/null +++ b/packages/pg/test/integration/connection-pool/tls-tests.js @@ -0,0 +1,23 @@ +'use strict' + +const fs = require('fs') + +const helper = require('./test-helper') +const pg = helper.pg + +const suite = new helper.Suite() + +if (process.env.PG_CLIENT_CERT_TEST) { + suite.testAsync('client certificate', async () => { + const pool = new pg.Pool({ + ssl: { + ca: fs.readFileSync(process.env.PGSSLROOTCERT), + cert: fs.readFileSync(process.env.PGSSLCERT), + key: fs.readFileSync(process.env.PGSSLKEY), + }, + }) + + await pool.query('SELECT 1') + await pool.end() + }) +} diff --git a/packages/pg/test/tls/GNUmakefile b/packages/pg/test/tls/GNUmakefile new file mode 100644 index 000000000..12d8f49fd --- /dev/null +++ b/packages/pg/test/tls/GNUmakefile @@ -0,0 +1,71 @@ +DESTDIR ::= /var/lib/postgres/data +POSTGRES_USER ::= postgres +POSTGRES_GROUP ::= postgres +DATABASE_HOST ::= localhost +DATABASE_USER ::= postgres + +all: \ + test-server-ca.crt \ + test-client-ca.crt \ + test-server.key \ + test-server.crt \ + test-client.key \ + test-client.crt + +clean: + rm -f \ + test-server-ca.key \ + test-client-ca.key \ + test-server-ca.crt \ + test-client-ca.crt \ + test-server.key \ + test-server.crt \ + test-client.key \ + test-client.crt + +install: test-server.crt test-server.key test-client-ca.crt + install \ + --owner=$(POSTGRES_USER) \ + --group=$(POSTGRES_GROUP) \ + --mode=0600 \ + -t $(DESTDIR) \ + $^ + +test-%-ca.crt: test-%-ca.key + openssl req -new -x509 \ + -subj '/CN=node-postgres test $* CA' \ + -days 3650 \ + -key $< \ + -out $@ + +test-server.csr: test-server.key + openssl req -new \ + -subj '/CN=$(DATABASE_HOST)' \ + -key $< \ + -out $@ + +test-client.csr: test-client.key + openssl req -new \ + -subj '/CN=$(DATABASE_USER)' \ + -key $< \ + -out $@ + +test-%.crt: test-%.csr test-%-ca.crt test-%-ca.key + openssl x509 -req \ + -CA test-$*-ca.crt \ + -CAkey test-$*-ca.key \ + -set_serial 1 \ + -days 3650 \ + -in $< \ + -out $@ + +%.key: + openssl genpkey \ + -algorithm EC \ + -pkeyopt ec_paramgen_curve:prime256v1 \ + -out $@ + +.PHONY: all clean install +.SECONDARY: test-server-ca.key test-client-ca.key +.INTERMEDIATE: test-server.csr test-client.csr +.POSIX: diff --git a/packages/pg/test/tls/test-client-ca.crt b/packages/pg/test/tls/test-client-ca.crt new file mode 100644 index 000000000..c2c5c040a --- /dev/null +++ b/packages/pg/test/tls/test-client-ca.crt @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBozCCAUmgAwIBAgIUNYMF06PrmjsMR6x+C8k5YZn9heAwCgYIKoZIzj0EAwIw +JzElMCMGA1UEAwwcbm9kZS1wb3N0Z3JlcyB0ZXN0IGNsaWVudCBDQTAeFw0yMDEw +MzExOTI1NDdaFw0zMDEwMjkxOTI1NDdaMCcxJTAjBgNVBAMMHG5vZGUtcG9zdGdy +ZXMgdGVzdCBjbGllbnQgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASI/Efx +Pq0P54VKPkTUOTwBH1iuYbnLpd4kAGjb1E334/p9CEBbDREVSqDjYjWswFybxKIF +ooKXtMpEMJfymJAUo1MwUTAdBgNVHQ4EFgQU/b/FRwYZ5/VMjdesIolksiqNYK4w +HwYDVR0jBBgwFoAU/b/FRwYZ5/VMjdesIolksiqNYK4wDwYDVR0TAQH/BAUwAwEB +/zAKBggqhkjOPQQDAgNIADBFAiEApHFCAWGbRGqYkyiBO+gMyX6gF5oFJywUupZP +LfgIRDACIDBZotzPe6+BIl2fU9Xgm7CxV6cCoX8bPEJKveKMnOaN +-----END CERTIFICATE----- diff --git a/packages/pg/test/tls/test-client-ca.key b/packages/pg/test/tls/test-client-ca.key new file mode 100644 index 000000000..86a4cb4a0 --- /dev/null +++ b/packages/pg/test/tls/test-client-ca.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgKsipfQWM+41FriF7 +kRxVaiNi8qY1fzLx6Dp/gUQQPG6hRANCAASI/EfxPq0P54VKPkTUOTwBH1iuYbnL +pd4kAGjb1E334/p9CEBbDREVSqDjYjWswFybxKIFooKXtMpEMJfymJAU +-----END PRIVATE KEY----- diff --git a/packages/pg/test/tls/test-client.crt b/packages/pg/test/tls/test-client.crt new file mode 100644 index 000000000..2d2a8996d --- /dev/null +++ b/packages/pg/test/tls/test-client.crt @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE----- +MIIBITCByAIBATAKBggqhkjOPQQDAjAnMSUwIwYDVQQDDBxub2RlLXBvc3RncmVz +IHRlc3QgY2xpZW50IENBMB4XDTIwMTAzMTE5MjU0N1oXDTMwMTAyOTE5MjU0N1ow +EzERMA8GA1UEAwwIcG9zdGdyZXMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARY +4j5AgTLi/O/UTB8l1mX+nD9u3SW9RwN1mekcqEZqCpOPMsQEQ/HLxaKnoSTD6w/G +NqrBnHlbMGPwEdKvV96bMAoGCCqGSM49BAMCA0gAMEUCIQDzfjm+BzmjrsIO4QRu +Et0ShHBK3Kley3oqnzoJHCUSmAIgdF5gELQ5mlJVX3bAI8h1cKiC/L6awwg7eBDU +S1gBTaI= +-----END CERTIFICATE----- diff --git a/packages/pg/test/tls/test-client.key b/packages/pg/test/tls/test-client.key new file mode 100644 index 000000000..662f35532 --- /dev/null +++ b/packages/pg/test/tls/test-client.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgL9jW07+fXy/74Ub3 +579RXm0Xpo7lnNnQleSzkTEXCrmhRANCAARY4j5AgTLi/O/UTB8l1mX+nD9u3SW9 +RwN1mekcqEZqCpOPMsQEQ/HLxaKnoSTD6w/GNqrBnHlbMGPwEdKvV96b +-----END PRIVATE KEY----- diff --git a/packages/pg/test/tls/test-server-ca.crt b/packages/pg/test/tls/test-server-ca.crt new file mode 100644 index 000000000..ac3427561 --- /dev/null +++ b/packages/pg/test/tls/test-server-ca.crt @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBozCCAUmgAwIBAgIUD582G2ou0Lg9q7AJeAMpiQVaiPQwCgYIKoZIzj0EAwIw +JzElMCMGA1UEAwwcbm9kZS1wb3N0Z3JlcyB0ZXN0IHNlcnZlciBDQTAeFw0yMDEw +MzExOTI1NDdaFw0zMDEwMjkxOTI1NDdaMCcxJTAjBgNVBAMMHG5vZGUtcG9zdGdy +ZXMgdGVzdCBzZXJ2ZXIgQ0EwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAT/jGRh +FiZu96o0hfgIkep4PusTwI6P1ASFh8LgnUu2bMcIlYakQK0ap2XvCaSl9675+Lu9 +yNZaSZVA5LpFICXto1MwUTAdBgNVHQ4EFgQUHI1BK+6u7r9r1XhighuP2/eGcQUw +HwYDVR0jBBgwFoAUHI1BK+6u7r9r1XhighuP2/eGcQUwDwYDVR0TAQH/BAUwAwEB +/zAKBggqhkjOPQQDAgNIADBFAiALwBWN9pRpaGQ12G9ERACn8/6RtAoO4lI5RmaR +rsTHtAIhAJxMfzNIgBAgX7vBSjHaqA08CozIctDSVag/rDlAzgy0 +-----END CERTIFICATE----- diff --git a/packages/pg/test/tls/test-server-ca.key b/packages/pg/test/tls/test-server-ca.key new file mode 100644 index 000000000..bfc4925ec --- /dev/null +++ b/packages/pg/test/tls/test-server-ca.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgyUd4vHDNrEFzfttP +z+AFp3Tbyui+b3i9YDW7VqpMOIKhRANCAAT/jGRhFiZu96o0hfgIkep4PusTwI6P +1ASFh8LgnUu2bMcIlYakQK0ap2XvCaSl9675+Lu9yNZaSZVA5LpFICXt +-----END PRIVATE KEY----- diff --git a/packages/pg/test/tls/test-server.crt b/packages/pg/test/tls/test-server.crt new file mode 100644 index 000000000..171700d5d --- /dev/null +++ b/packages/pg/test/tls/test-server.crt @@ -0,0 +1,9 @@ +-----BEGIN CERTIFICATE----- +MIIBITCByQIBATAKBggqhkjOPQQDAjAnMSUwIwYDVQQDDBxub2RlLXBvc3RncmVz +IHRlc3Qgc2VydmVyIENBMB4XDTIwMTAzMTE5MjU0N1oXDTMwMTAyOTE5MjU0N1ow +FDESMBAGA1UEAwwJbG9jYWxob3N0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE +4Mwi6dHeWRZ2QU19a5ykq6gJfIVJDEaJqNlWXk/5/laiGy8ScBV0YAlvk9xsfAyU +YDxcQTjQkeC0bbzhdEPjNjAKBggqhkjOPQQDAgNHADBEAiB+DW/8Kg3tuoovAE+8 +1Pv/8OkF3MD4A1ztULkW3KJ4PwIgMn7ea3HrEQJoeSKFe1kKIgNrHftdC5kZQYj5 +uNXYpLo= +-----END CERTIFICATE----- diff --git a/packages/pg/test/tls/test-server.key b/packages/pg/test/tls/test-server.key new file mode 100644 index 000000000..1ce884e2f --- /dev/null +++ b/packages/pg/test/tls/test-server.key @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgBoW9xxWBH2tHiPFk +9ajPALHyw0lHAY1DF8WvHQNodx2hRANCAATgzCLp0d5ZFnZBTX1rnKSrqAl8hUkM +Romo2VZeT/n+VqIbLxJwFXRgCW+T3Gx8DJRgPFxBONCR4LRtvOF0Q+M2 +-----END PRIVATE KEY----- From dce02e8d777037926ab6d2265b653242d0afc381 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 10 Nov 2020 11:00:41 -0600 Subject: [PATCH 0739/1037] Update sponsors & changelog --- CHANGELOG.md | 6 ++++++ SPONSORS.md | 2 ++ 2 files changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b62cc0084..51ca3426e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### pg@8.5.0 + +- Fix bug forwarding [ssl key](https://github.com/brianc/node-postgres/pull/2394). +- Convert pg-query-stream internals to [typescript](https://github.com/brianc/node-postgres/pull/2376). +- Performance [improvements](https://github.com/brianc/node-postgres/pull/2286). + ### pg@8.4.0 - Switch to optional peer dependencies & remove [semver](https://github.com/brianc/node-postgres/commit/a02dfac5ad2e2abf0dc3a9817f953938acdc19b1) package which has been a small thorn in the side of a few users. diff --git a/SPONSORS.md b/SPONSORS.md index a11b2b55d..1bc13bf73 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -8,6 +8,7 @@ node-postgres is made possible by the helpful contributors from the community as - [Nafundi](https://nafundi.com) - [CrateDB](https://crate.io/) - [BitMEX](https://www.bitmex.com/app/trade/XBTUSD) +- [Dataform](https://dataform.co/) # Supporters @@ -32,3 +33,4 @@ node-postgres is made possible by the helpful contributors from the community as - Simple Analytics - Trevor Linton - Ian Walter +- @Guido4000 From ec1dcab966ecb03080e75112f6d3623d1360b634 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 10 Nov 2020 11:01:03 -0600 Subject: [PATCH 0740/1037] Publish - pg-cursor@2.5.0 - pg-protocol@1.4.0 - pg-query-stream@3.4.0 - pg@8.5.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 10 +++++----- packages/pg/package.json | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index aa4ff624b..74d029e0b 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.4.2", + "version": "2.5.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -17,6 +17,6 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.4.2" + "pg": "^8.5.0" } } diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 7fc1eb8ac..05f74ae10 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.3.0", + "version": "1.4.0", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 94f9f02d0..ea3b6ad4c 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.3.2", + "version": "3.4.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -27,15 +27,15 @@ "url": "https://github.com/brianc/node-postgres/issues" }, "devDependencies": { - "@types/node": "^14.0.0", - "@types/pg": "^7.14.5", "@types/chai": "^4.2.13", "@types/mocha": "^8.0.3", + "@types/node": "^14.0.0", + "@types/pg": "^7.14.5", "JSONStream": "~0.7.1", "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.4.2", + "pg": "^8.5.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4", @@ -43,6 +43,6 @@ "typescript": "^4.0.3" }, "dependencies": { - "pg-cursor": "^2.4.2" + "pg-cursor": "^2.5.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index da38ab5c6..ca3404e5a 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.4.2", + "version": "8.5.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "packet-reader": "1.0.0", "pg-connection-string": "^2.4.0", "pg-pool": "^3.2.2", - "pg-protocol": "^1.3.0", + "pg-protocol": "^1.4.0", "pg-types": "^2.1.0", "pgpass": "1.x" }, From 897d774509a37870b1ee057bfa5186e7a2b018b2 Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 10 Nov 2020 16:01:44 -0600 Subject: [PATCH 0741/1037] Run build before publish (#2409) --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index d87548d6d..3de85d252 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "build": "tsc --build", "build:watch": "tsc --build --watch", "pretest": "yarn build", + "prepublish": "yarn build", "lint": "eslint '*/**/*.{js,ts,tsx}'" }, "devDependencies": { From 3d0f68aa7b5bf2153694dd7bc00e3f06ad5be06a Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 10 Nov 2020 16:04:12 -0600 Subject: [PATCH 0742/1037] Update keyword to force patch apply --- packages/pg-query-stream/package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index ea3b6ad4c..12c9b2c89 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -13,6 +13,7 @@ }, "keywords": [ "postgres", + "query-stream", "pg", "query", "stream" From 4d203aedeef0064c2adf649ccdb7ffd995e4f044 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 10 Nov 2020 16:04:19 -0600 Subject: [PATCH 0743/1037] Publish - pg-query-stream@3.4.1 --- packages/pg-query-stream/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 12c9b2c89..e75fe60f7 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.4.0", + "version": "3.4.1", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", From ebe412cf243be35d21ead496d736755217933266 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 11 Nov 2020 10:41:20 -0600 Subject: [PATCH 0744/1037] Support "true" as string for ssl (#2407) Fixes 2406 --- packages/pg/lib/connection-parameters.js | 5 +++++ .../pg/test/unit/connection-parameters/creation-tests.js | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index 62bee8c85..165e6d5d3 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -80,6 +80,11 @@ class ConnectionParameters { this.ssl = typeof config.ssl === 'undefined' ? readSSLConfigFromEnvironment() : config.ssl + if (typeof this.ssl === 'string') { + if (this.ssl === 'true') { + this.ssl = true + } + } // support passing in ssl=no-verify via connection string if (this.ssl === 'no-verify') { this.ssl = { rejectUnauthorized: false } diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index e4dd1af72..633b0eaf4 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -257,7 +257,6 @@ test('libpq connection string building', function () { }) test('password contains < and/or > characters', function () { - return false var sourceConfig = { user: 'brian', password: 'helloe', @@ -308,6 +307,11 @@ test('libpq connection string building', function () { assert(c.ssl, 'Client should have ssl enabled via defaults') }) + test('coercing string "true" to boolean', function () { + const subject = new ConnectionParameters({ ssl: 'true' }) + assert.strictEqual(subject.ssl, true) + }) + test('ssl is set on client', function () { var sourceConfig = { user: 'brian', From 0b9bb349dcb10f6473737001062082b65efc74be Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Fri, 13 Nov 2020 08:59:48 -0600 Subject: [PATCH 0745/1037] Publish - pg-cursor@2.5.1 - pg-query-stream@3.4.2 - pg@8.5.1 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 74d029e0b..ff92dfedd 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.5.0", + "version": "2.5.1", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -17,6 +17,6 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.5.0" + "pg": "^8.5.1" } } diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index e75fe60f7..384ff18c3 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.4.1", + "version": "3.4.2", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -36,7 +36,7 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.5.0", + "pg": "^8.5.1", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "through": "~2.3.4", @@ -44,6 +44,6 @@ "typescript": "^4.0.3" }, "dependencies": { - "pg-cursor": "^2.5.0" + "pg-cursor": "^2.5.1" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index ca3404e5a..32439f61b 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.5.0", + "version": "8.5.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", From c6aa29ade9149be7378a559374f3d578153d01c5 Mon Sep 17 00:00:00 2001 From: Jakob Krigovsky Date: Fri, 27 Nov 2020 22:44:37 +0100 Subject: [PATCH 0746/1037] Fix typo (#2422) Co-authored-by: Wolfgang Walther --- packages/pg-connection-string/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg-connection-string/README.md b/packages/pg-connection-string/README.md index d5b45ab9e..b591d0661 100644 --- a/packages/pg-connection-string/README.md +++ b/packages/pg-connection-string/README.md @@ -22,7 +22,7 @@ var config = parse('postgres://someuser:somepassword@somehost:381/somedatabase') The resulting config contains a subset of the following properties: -* `host` - Postgres server hostname or, for UNIX doamain sockets, the socket filename +* `host` - Postgres server hostname or, for UNIX domain sockets, the socket filename * `port` - port on which to connect * `user` - User with which to authenticate to the server * `password` - Corresponding password From 4fde8b78f17b8b227a4bc9dd1f790035df224a2c Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 30 Nov 2020 09:25:01 -0600 Subject: [PATCH 0747/1037] Fix double readyForQuery (#2420) This is fixing a double readyForQuery message being sent from the backend (because we were calling sync after an error, which I already fixed in the main driver). Also closes #2333 --- packages/pg-cursor/index.js | 27 +++++++--- packages/pg-query-stream/test/error.ts | 69 ++++++++++++++++++++++++++ 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index 9d672dbff..d26e77bdc 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -37,6 +37,7 @@ Cursor.prototype._rowDescription = function () { } Cursor.prototype.submit = function (connection) { + this.state = 'submitted' this.connection = connection this._portal = 'C_' + nextUniqueID++ @@ -87,7 +88,12 @@ Cursor.prototype._closePortal = function () { // open can lock tables for modification if inside a transaction. // see https://github.com/brianc/node-pg-cursor/issues/56 this.connection.close({ type: 'P', name: this._portal }) - this.connection.sync() + + // If we've received an error we already sent a sync message. + // do not send another sync as it triggers another readyForQuery message. + if (this.state !== 'error') { + this.connection.sync() + } } Cursor.prototype.handleRowDescription = function (msg) { @@ -138,8 +144,18 @@ Cursor.prototype.handleEmptyQuery = function () { } Cursor.prototype.handleError = function (msg) { - this.connection.removeListener('noData', this._ifNoData) - this.connection.removeListener('rowDescription', this._rowDescription) + // If we're in an initialized state we've never been submitted + // and don't have a connection instance reference yet. + // This can happen if you queue a stream and close the client before + // the client has submitted the stream. In this scenario we don't have + // a connection so there's nothing to unsubscribe from. + if (this.state !== 'initialized') { + this.connection.removeListener('noData', this._ifNoData) + this.connection.removeListener('rowDescription', this._rowDescription) + // call sync to trigger a readyForQuery + this.connection.sync() + } + this.state = 'error' this._error = msg // satisfy any waiting callback @@ -155,8 +171,6 @@ Cursor.prototype.handleError = function (msg) { // only dispatch error events if we have a listener this.emit('error', msg) } - // call sync to keep this connection from hanging - this.connection.sync() } Cursor.prototype._getRows = function (rows, cb) { @@ -189,6 +203,7 @@ Cursor.prototype.close = function (cb) { return } } + this._closePortal() this.state = 'done' if (cb) { @@ -199,7 +214,7 @@ Cursor.prototype.close = function (cb) { } Cursor.prototype.read = function (rows, cb) { - if (this.state === 'idle') { + if (this.state === 'idle' || this.state === 'submitted') { return this._getRows(rows, cb) } if (this.state === 'busy' || this.state === 'initialized') { diff --git a/packages/pg-query-stream/test/error.ts b/packages/pg-query-stream/test/error.ts index c92cd0091..220a52485 100644 --- a/packages/pg-query-stream/test/error.ts +++ b/packages/pg-query-stream/test/error.ts @@ -1,6 +1,7 @@ import assert from 'assert' import helper from './helper' import QueryStream from '../src' +import { Pool, Client } from 'pg' helper('error', function (client) { it('receives error on stream', function (done) { @@ -21,3 +22,71 @@ helper('error', function (client) { client.query('SELECT NOW()', done) }) }) + +describe('error recovery', () => { + // created from https://github.com/chrisdickinson/pg-test-case + it('recovers from a streaming error in a transaction', async () => { + const pool = new Pool() + const client = await pool.connect() + await client.query(`CREATE TEMP TABLE frobnicators ( + id serial primary key, + updated timestamp + )`) + await client.query(`BEGIN;`) + const query = new QueryStream(`INSERT INTO frobnicators ("updated") VALUES ($1) RETURNING "id"`, [Date.now()]) + let error: Error | undefined = undefined + query.on('data', console.log).on('error', (e) => { + error = e + }) + client.query(query) // useless callback necessitated by an older version of honeycomb-beeline + + await client.query(`ROLLBACK`) + assert(error, 'Error should not be undefined') + const { rows } = await client.query('SELECT NOW()') + assert.strictEqual(rows.length, 1) + client.release() + const client2 = await pool.connect() + await client2.query(`BEGIN`) + client2.release() + pool.end() + }) + + // created from https://github.com/brianc/node-postgres/pull/2333 + it('handles an error on a stream after a plain text non-stream error', async () => { + const client = new Client() + const stmt = 'SELECT * FROM goose;' + await client.connect() + return new Promise((resolve, reject) => { + client.query(stmt).catch((e) => { + assert(e, 'Query should have rejected with an error') + const stream = new QueryStream('SELECT * FROM duck') + client.query(stream) + stream.on('data', () => {}) + stream.on('error', () => { + client.end((err) => { + err ? reject(err) : resolve() + }) + }) + }) + }) + }) + + it('does not crash when closing a connection with a queued stream', async () => { + const client = new Client() + const stmt = 'SELECT * FROM goose;' + await client.connect() + return new Promise(async (resolve) => { + let queryError: Error | undefined + client.query(stmt).catch((e) => { + queryError = e + }) + const stream = client.query(new QueryStream(stmt)) + stream.on('data', () => {}) + stream.on('error', () => { + assert(queryError, 'query should have errored due to client ending') + resolve() + }) + await client.end() + }) + }) +}) From 5de36c7f7f8776d7e80a0492528f475db550f96e Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 30 Nov 2020 10:57:40 -0600 Subject: [PATCH 0748/1037] Update sponsors & readme --- README.md | 4 ++++ SPONSORS.md | 3 +++ packages/pg/README.md | 5 +++++ 3 files changed, 12 insertions(+) diff --git a/README.md b/README.md index 695b44f48..549eb0e60 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,10 @@ node-postgres's continued development has been made possible in part by generous + + + +
If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable [please consider supporting](https://github.com/sponsors/brianc) its development. diff --git a/SPONSORS.md b/SPONSORS.md index 1bc13bf73..1188ccedb 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -9,6 +9,7 @@ node-postgres is made possible by the helpful contributors from the community as - [CrateDB](https://crate.io/) - [BitMEX](https://www.bitmex.com/app/trade/XBTUSD) - [Dataform](https://dataform.co/) +- [Eaze](https://www.eaze.com/) # Supporters @@ -34,3 +35,5 @@ node-postgres is made possible by the helpful contributors from the community as - Trevor Linton - Ian Walter - @Guido4000 +- [Martti Laine](https://github.com/codeclown) +- [Tim Nolet](https://github.com/tnolet) diff --git a/packages/pg/README.md b/packages/pg/README.md index ed4d7a626..e5fcf02c4 100644 --- a/packages/pg/README.md +++ b/packages/pg/README.md @@ -53,6 +53,11 @@ node-postgres's continued development has been made possible in part by generous + + + + +
If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable [please consider supporting](https://github.com/sponsors/brianc) its development. From fa4549af4fc8d1ffdc121c696faa72fc02459f4b Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 30 Nov 2020 10:58:10 -0600 Subject: [PATCH 0749/1037] Publish - pg-cursor@2.5.2 - pg-query-stream@4.0.0 --- packages/pg-cursor/package.json | 2 +- packages/pg-query-stream/package.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index ff92dfedd..4da335568 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.5.1", + "version": "2.5.2", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 384ff18c3..0b3012265 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "3.4.2", + "version": "4.0.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -44,6 +44,6 @@ "typescript": "^4.0.3" }, "dependencies": { - "pg-cursor": "^2.5.1" + "pg-cursor": "^2.5.2" } } From 54b87523e29ea53379d7b9a26e45f83886f371af Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Mon, 30 Nov 2020 11:01:54 -0600 Subject: [PATCH 0750/1037] Update changelog for pg-query-stream Document the conversion to typescript as a semver major change. Closes #2412. --- CHANGELOG.md | 4 ++++ packages/pg-query-stream/README.md | 10 +++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51ca3426e..470f8f976 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### pg-query-stream@4.0.0 + +- Library has been [converted](https://github.com/brianc/node-postgres/pull/2376) to Typescript. The behavior is identical, but there could be subtle breaking changes due to class names changing or other small inconsistencies introduced by the conversion. + ### pg@8.5.0 - Fix bug forwarding [ssl key](https://github.com/brianc/node-postgres/pull/2394). diff --git a/packages/pg-query-stream/README.md b/packages/pg-query-stream/README.md index 043928ad5..d5b2802bd 100644 --- a/packages/pg-query-stream/README.md +++ b/packages/pg-query-stream/README.md @@ -1,10 +1,7 @@ # pg-query-stream -[![Build Status](https://travis-ci.org/brianc/node-pg-query-stream.svg)](https://travis-ci.org/brianc/node-pg-query-stream) - Receive result rows from [pg](https://github.com/brianc/node-postgres) as a readable (object) stream. - ## installation ```bash @@ -14,7 +11,6 @@ $ npm install pg-query-stream --save _requires pg>=2.8.1_ - ## use ```js @@ -24,7 +20,7 @@ const JSONStream = require('JSONStream') //pipe 1,000,000 rows to stdout without blowing up your memory usage pg.connect((err, client, done) => { - if (err) throw err; + if (err) throw err const query = new QueryStream('SELECT * FROM generate_series(0, $1) num', [1000000]) const stream = client.query(query) //release the client when the stream is finished @@ -35,13 +31,13 @@ pg.connect((err, client, done) => { The stream uses a cursor on the server so it efficiently keeps only a low number of rows in memory. -This is especially useful when doing [ETL](http://en.wikipedia.org/wiki/Extract,_transform,_load) on a huge table. Using manual `limit` and `offset` queries to fake out async itteration through your data is cumbersome, and _way way way_ slower than using a cursor. +This is especially useful when doing [ETL](http://en.wikipedia.org/wiki/Extract,_transform,_load) on a huge table. Using manual `limit` and `offset` queries to fake out async itteration through your data is cumbersome, and _way way way_ slower than using a cursor. _note: this module only works with the JavaScript client, and does not work with the native bindings. libpq doesn't expose the protocol at a level where a cursor can be manipulated directly_ ## contribution -I'm very open to contribution! Open a pull request with your code or idea and we'll talk about it. If it's not way insane we'll merge it in too: isn't open source awesome? +I'm very open to contribution! Open a pull request with your code or idea and we'll talk about it. If it's not way insane we'll merge it in too: isn't open source awesome? ## license From afb3bf3d4363d0696f843a008a78576434496eee Mon Sep 17 00:00:00 2001 From: Jakob Krigovsky Date: Thu, 3 Dec 2020 16:44:28 +0100 Subject: [PATCH 0751/1037] Document sslmode connection string parameter (#2421) --- packages/pg-connection-string/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/pg-connection-string/README.md b/packages/pg-connection-string/README.md index b591d0661..360505e0d 100644 --- a/packages/pg-connection-string/README.md +++ b/packages/pg-connection-string/README.md @@ -29,6 +29,7 @@ The resulting config contains a subset of the following properties: * `database` - Database name within the server * `client_encoding` - string encoding the client will use * `ssl`, either a boolean or an object with properties + * `rejectUnauthorized` * `cert` * `key` * `ca` @@ -65,6 +66,10 @@ Query parameters follow a `?` character, including the following special query p * `host=` - sets `host` property, overriding the URL's host * `encoding=` - sets the `client_encoding` property * `ssl=1`, `ssl=true`, `ssl=0`, `ssl=false` - sets `ssl` to true or false, accordingly + * `sslmode=` + * `sslmode=disable` - sets `ssl` to false + * `sslmode=no-verify` - sets `ssl` to `{ rejectUnauthorized: false }` + * `sslmode=prefer`, `sslmode=require`, `sslmode=verify-ca`, `sslmode=verify-full` - sets `ssl` to true * `sslcert=` - reads data from the given file and includes the result as `ssl.cert` * `sslkey=` - reads data from the given file and includes the result as `ssl.key` * `sslrootcert=` - reads data from the given file and includes the result as `ssl.ca` From a109e8c6d24ab057843ff40385650b4a6f74d015 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Wed, 30 Dec 2020 05:19:27 -0500 Subject: [PATCH 0752/1037] Add more SASL validation and fix tests (#2436) * Add sha256 SASL helper * Rename internal createHMAC(...) to hmacSha256(...) * Add parseAttributePairs(...) helper for SASL * Tighten arg checks in SASL xorBuffers(...) * Add SASL nonce check for printable chars * Add SASL server salt and server signature base64 validation * Add check for non-empty SASL server nonce * Rename SASL helper to parseServerFirstMessage(...) * Add parameter validation to SASL continueSession(...) * Split out SASL final message parsing into parseServerFinalMessage(...) * Fix SCRAM tests Removes custom assert.throws(...) so that the real one from the assert package is used and fixes the SCRAM tests to reflect the updated error messages and actual checking of errors. Previously the custom assert.throws(...) was ignoring the error signature validation. --- packages/pg/lib/sasl.js | 162 ++++++++++++------ packages/pg/test/test-helper.js | 10 -- .../pg/test/unit/client/sasl-scram-tests.js | 41 +++-- 3 files changed, 141 insertions(+), 72 deletions(-) diff --git a/packages/pg/lib/sasl.js b/packages/pg/lib/sasl.js index 22abf5c4a..c61804750 100644 --- a/packages/pg/lib/sasl.js +++ b/packages/pg/lib/sasl.js @@ -20,19 +20,27 @@ function continueSession(session, password, serverData) { if (session.message !== 'SASLInitialResponse') { throw new Error('SASL: Last message was not SASLInitialResponse') } + if (typeof password !== 'string') { + throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string') + } + if (typeof serverData !== 'string') { + throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: serverData must be a string') + } - const sv = extractVariablesFromFirstServerMessage(serverData) + const sv = parseServerFirstMessage(serverData) if (!sv.nonce.startsWith(session.clientNonce)) { throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce does not start with client nonce') + } else if (sv.nonce.length === session.clientNonce.length) { + throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: server nonce is too short') } var saltBytes = Buffer.from(sv.salt, 'base64') var saltedPassword = Hi(password, saltBytes, sv.iteration) - var clientKey = createHMAC(saltedPassword, 'Client Key') - var storedKey = crypto.createHash('sha256').update(clientKey).digest() + var clientKey = hmacSha256(saltedPassword, 'Client Key') + var storedKey = sha256(clientKey) var clientFirstMessageBare = 'n=*,r=' + session.clientNonce var serverFirstMessage = 'r=' + sv.nonce + ',s=' + sv.salt + ',i=' + sv.iteration @@ -41,12 +49,12 @@ function continueSession(session, password, serverData) { var authMessage = clientFirstMessageBare + ',' + serverFirstMessage + ',' + clientFinalMessageWithoutProof - var clientSignature = createHMAC(storedKey, authMessage) + var clientSignature = hmacSha256(storedKey, authMessage) var clientProofBytes = xorBuffers(clientKey, clientSignature) var clientProof = clientProofBytes.toString('base64') - var serverKey = createHMAC(saltedPassword, 'Server Key') - var serverSignatureBytes = createHMAC(serverKey, authMessage) + var serverKey = hmacSha256(saltedPassword, 'Server Key') + var serverSignatureBytes = hmacSha256(serverKey, authMessage) session.message = 'SASLResponse' session.serverSignature = serverSignatureBytes.toString('base64') @@ -57,54 +65,87 @@ function finalizeSession(session, serverData) { if (session.message !== 'SASLResponse') { throw new Error('SASL: Last message was not SASLResponse') } + if (typeof serverData !== 'string') { + throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: serverData must be a string') + } - var serverSignature - - String(serverData) - .split(',') - .forEach(function (part) { - switch (part[0]) { - case 'v': - serverSignature = part.substr(2) - break - } - }) + const { serverSignature } = parseServerFinalMessage(serverData) if (serverSignature !== session.serverSignature) { throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature does not match') } } -function extractVariablesFromFirstServerMessage(data) { - var nonce, salt, iteration - - String(data) - .split(',') - .forEach(function (part) { - switch (part[0]) { - case 'r': - nonce = part.substr(2) - break - case 's': - salt = part.substr(2) - break - case 'i': - iteration = parseInt(part.substr(2), 10) - break +/** + * printable = %x21-2B / %x2D-7E + * ;; Printable ASCII except ",". + * ;; Note that any "printable" is also + * ;; a valid "value". + */ +function isPrintableChars(text) { + if (typeof text !== 'string') { + throw new TypeError('SASL: text must be a string') + } + return text + .split('') + .map((_, i) => text.charCodeAt(i)) + .every((c) => (c >= 0x21 && c <= 0x2b) || (c >= 0x2d && c <= 0x7e)) +} + +/** + * base64-char = ALPHA / DIGIT / "/" / "+" + * + * base64-4 = 4base64-char + * + * base64-3 = 3base64-char "=" + * + * base64-2 = 2base64-char "==" + * + * base64 = *base64-4 [base64-3 / base64-2] + */ +function isBase64(text) { + return /^(?:[a-zA-Z0-9+/]{4})*(?:[a-zA-Z0-9+/]{2}==|[a-zA-Z0-9+/]{3}=)?$/.test(text) +} + +function parseAttributePairs(text) { + if (typeof text !== 'string') { + throw new TypeError('SASL: attribute pairs text must be a string') + } + + return new Map( + text.split(',').map((attrValue) => { + if (!/^.=/.test(attrValue)) { + throw new Error('SASL: Invalid attribute pair entry') } + const name = attrValue[0] + const value = attrValue.substring(2) + return [name, value] }) + ) +} +function parseServerFirstMessage(data) { + const attrPairs = parseAttributePairs(data) + + const nonce = attrPairs.get('r') if (!nonce) { throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce missing') + } else if (!isPrintableChars(nonce)) { + throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: nonce must only contain printable characters') } - + const salt = attrPairs.get('s') if (!salt) { throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: salt missing') + } else if (!isBase64(salt)) { + throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: salt must be base64') } - - if (!iteration) { + const iterationText = attrPairs.get('i') + if (!iterationText) { throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: iteration missing') + } else if (!/^[1-9][0-9]*$/.test(iterationText)) { + throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: invalid iteration count') } + const iteration = parseInt(iterationText, 10) return { nonce, @@ -113,31 +154,48 @@ function extractVariablesFromFirstServerMessage(data) { } } +function parseServerFinalMessage(serverData) { + const attrPairs = parseAttributePairs(serverData) + const serverSignature = attrPairs.get('v') + if (!serverSignature) { + throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature is missing') + } else if (!isBase64(serverSignature)) { + throw new Error('SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature must be base64') + } + return { + serverSignature, + } +} + function xorBuffers(a, b) { - if (!Buffer.isBuffer(a)) a = Buffer.from(a) - if (!Buffer.isBuffer(b)) b = Buffer.from(b) - var res = [] - if (a.length > b.length) { - for (var i = 0; i < b.length; i++) { - res.push(a[i] ^ b[i]) - } - } else { - for (var j = 0; j < a.length; j++) { - res.push(a[j] ^ b[j]) - } - } - return Buffer.from(res) + if (!Buffer.isBuffer(a)) { + throw new TypeError('first argument must be a Buffer') + } + if (!Buffer.isBuffer(b)) { + throw new TypeError('second argument must be a Buffer') + } + if (a.length !== b.length) { + throw new Error('Buffer lengths must match') + } + if (a.length === 0) { + throw new Error('Buffers cannot be empty') + } + return Buffer.from(a.map((_, i) => a[i] ^ b[i])) +} + +function sha256(text) { + return crypto.createHash('sha256').update(text).digest() } -function createHMAC(key, msg) { +function hmacSha256(key, msg) { return crypto.createHmac('sha256', key).update(msg).digest() } function Hi(password, saltBytes, iterations) { - var ui1 = createHMAC(password, Buffer.concat([saltBytes, Buffer.from([0, 0, 0, 1])])) + var ui1 = hmacSha256(password, Buffer.concat([saltBytes, Buffer.from([0, 0, 0, 1])])) var ui = ui1 for (var i = 0; i < iterations - 1; i++) { - ui1 = createHMAC(password, ui1) + ui1 = hmacSha256(password, ui1) ui = xorBuffers(ui, ui1) } diff --git a/packages/pg/test/test-helper.js b/packages/pg/test/test-helper.js index 319b8ee79..5999ea98f 100644 --- a/packages/pg/test/test-helper.js +++ b/packages/pg/test/test-helper.js @@ -111,16 +111,6 @@ assert.success = function (callback) { } } -assert.throws = function (offender) { - try { - offender() - } catch (e) { - assert.ok(e instanceof Error, 'Expected ' + offender + ' to throw instances of Error') - return - } - assert.ok(false, 'Expected ' + offender + ' to throw exception') -} - assert.lengthIs = function (actual, expectedLength) { assert.equal(actual.length, expectedLength) } diff --git a/packages/pg/test/unit/client/sasl-scram-tests.js b/packages/pg/test/unit/client/sasl-scram-tests.js index f60c8c4c9..e53448bdf 100644 --- a/packages/pg/test/unit/client/sasl-scram-tests.js +++ b/packages/pg/test/unit/client/sasl-scram-tests.js @@ -38,7 +38,7 @@ test('sasl/scram', function () { test('fails when last session message was not SASLInitialResponse', function () { assert.throws( function () { - sasl.continueSession({}) + sasl.continueSession({}, '', '') }, { message: 'SASL: Last message was not SASLInitialResponse', @@ -53,6 +53,7 @@ test('sasl/scram', function () { { message: 'SASLInitialResponse', }, + 'bad-password', 's=1,i=1' ) }, @@ -69,6 +70,7 @@ test('sasl/scram', function () { { message: 'SASLInitialResponse', }, + 'bad-password', 'r=1,i=1' ) }, @@ -85,7 +87,8 @@ test('sasl/scram', function () { { message: 'SASLInitialResponse', }, - 'r=1,s=1' + 'bad-password', + 'r=1,s=abcd' ) }, { @@ -102,7 +105,8 @@ test('sasl/scram', function () { message: 'SASLInitialResponse', clientNonce: '2', }, - 'r=1,s=1,i=1' + 'bad-password', + 'r=1,s=abcd,i=1' ) }, { @@ -117,12 +121,12 @@ test('sasl/scram', function () { clientNonce: 'a', } - sasl.continueSession(session, 'password', 'r=ab,s=x,i=1') + sasl.continueSession(session, 'password', 'r=ab,s=abcd,i=1') assert.equal(session.message, 'SASLResponse') - assert.equal(session.serverSignature, 'TtywIrpWDJ0tCSXM2mjkyiaa8iGZsZG7HllQxr8fYAo=') + assert.equal(session.serverSignature, 'jwt97IHWFn7FEqHykPTxsoQrKGOMXJl/PJyJ1JXTBKc=') - assert.equal(session.response, 'c=biws,r=ab,p=KAEPBUTjjofB0IM5UWcZApK1dSzFE0o5vnbWjBbvFHA=') + assert.equal(session.response, 'c=biws,r=ab,p=mU8grLfTjDrJer9ITsdHk0igMRDejG10EJPFbIBL3D0=') }) }) @@ -138,15 +142,32 @@ test('sasl/scram', function () { ) }) + test('fails when server signature is not valid base64', function () { + assert.throws( + function () { + sasl.finalizeSession( + { + message: 'SASLResponse', + serverSignature: 'abcd', + }, + 'v=x1' // Purposefully invalid base64 + ) + }, + { + message: 'SASL: SCRAM-SERVER-FINAL-MESSAGE: server signature must be base64', + } + ) + }) + test('fails when server signature does not match', function () { assert.throws( function () { sasl.finalizeSession( { message: 'SASLResponse', - serverSignature: '3', + serverSignature: 'abcd', }, - 'v=4' + 'v=xyzq' ) }, { @@ -159,9 +180,9 @@ test('sasl/scram', function () { sasl.finalizeSession( { message: 'SASLResponse', - serverSignature: '5', + serverSignature: 'abcd', }, - 'v=5' + 'v=abcd' ) }) }) From daeafe82b4e4053de69ad75ddacde3c572e38402 Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 30 Dec 2020 04:20:20 -0600 Subject: [PATCH 0753/1037] Make tests pass in github codespaces (#2437) * Make tests pass in github codespaces There were a few tests which didn't specify a host or port which wasn't working well inside the codespaces docker environment. Added host & port where required. Also noticed one test wasn't actually _testing_, it was just `console.log`-ing its output, so I added proper assertions there. Finally set `PGTESTNOSSL: true` in the codespaces environment until I can get the postgres docker container configured w/ SSL...which I will do l8r. * lint --- .devcontainer/docker-compose.yml | 3 +++ .../pg/test/integration/client/connection-parameter-tests.js | 4 +++- packages/pg/test/integration/client/promise-api-tests.js | 2 +- packages/pg/test/integration/gh-issues/2079-tests.js | 4 ++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 184aff0ed..11c8c9f3b 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -25,6 +25,9 @@ services: PGUSER: user PGDATABASE: data PGHOST: db + # set this to true in the development environment until I can get SSL setup on the + # docker postgres instance + PGTESTNOSSL: true # Overrides default command so things don't shut down after the process ends. command: sleep infinity diff --git a/packages/pg/test/integration/client/connection-parameter-tests.js b/packages/pg/test/integration/client/connection-parameter-tests.js index b3bf74c36..45b5eba55 100644 --- a/packages/pg/test/integration/client/connection-parameter-tests.js +++ b/packages/pg/test/integration/client/connection-parameter-tests.js @@ -1,3 +1,4 @@ +const assert = require('assert') const helper = require('../test-helper') const suite = new helper.Suite() const { Client } = helper.pg @@ -8,6 +9,7 @@ suite.test('it sends options', async () => { }) await client.connect() const { rows } = await client.query('SHOW default_transaction_isolation') - console.log(rows) + assert.strictEqual(rows.length, 1) + assert.strictEqual(rows[0].default_transaction_isolation, 'serializable') await client.end() }) diff --git a/packages/pg/test/integration/client/promise-api-tests.js b/packages/pg/test/integration/client/promise-api-tests.js index 1d6e504f2..d8128cf8b 100644 --- a/packages/pg/test/integration/client/promise-api-tests.js +++ b/packages/pg/test/integration/client/promise-api-tests.js @@ -20,7 +20,7 @@ suite.test('valid connection completes promise', () => { }) suite.test('invalid connection rejects promise', (done) => { - const client = new pg.Client({ host: 'alksdjflaskdfj' }) + const client = new pg.Client({ host: 'alksdjflaskdfj', port: 1234 }) return client.connect().catch((e) => { assert(e instanceof Error) done() diff --git a/packages/pg/test/integration/gh-issues/2079-tests.js b/packages/pg/test/integration/gh-issues/2079-tests.js index be2485794..ad1c82aac 100644 --- a/packages/pg/test/integration/gh-issues/2079-tests.js +++ b/packages/pg/test/integration/gh-issues/2079-tests.js @@ -32,7 +32,7 @@ let makeTerminatingBackend = (byte) => { suite.test('SSL connection error allows event loop to exit', (done) => { const port = makeTerminatingBackend('N') - const client = new helper.pg.Client({ ssl: 'require', port }) + const client = new helper.pg.Client({ ssl: 'require', port, host: 'localhost' }) // since there was a connection error the client's socket should be closed // and the event loop will have no refs and exit cleanly client.connect((err) => { @@ -43,7 +43,7 @@ suite.test('SSL connection error allows event loop to exit', (done) => { suite.test('Non "S" response code allows event loop to exit', (done) => { const port = makeTerminatingBackend('X') - const client = new helper.pg.Client({ ssl: 'require', port }) + const client = new helper.pg.Client({ ssl: 'require', host: 'localhost', port }) // since there was a connection error the client's socket should be closed // and the event loop will have no refs and exit cleanly client.connect((err) => { From 3f3f1a77c3a87e42df64c5baaa7d42193b0d8529 Mon Sep 17 00:00:00 2001 From: Andy Edwards Date: Wed, 30 Dec 2020 04:20:46 -0600 Subject: [PATCH 0754/1037] docs(README.md): add link to documentation repo (#2434) since it's currently the only way to look up documentation for old versions --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 549eb0e60..dcd89d8d9 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ Each package in this repo should have its own readme more focused on how to deve ### :star: [Documentation](https://node-postgres.com) :star: +The source repo for the documentation is https://github.com/brianc/node-postgres-docs. + ### Features - Pure JavaScript client and native libpq bindings share _the same API_ From fae2c988700ca98c46a91313b4977dc751cf0b26 Mon Sep 17 00:00:00 2001 From: Jumpaku Date: Wed, 20 Jan 2021 08:24:44 +0900 Subject: [PATCH 0755/1037] Fix typo (#2444) --- packages/pg-protocol/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg-protocol/README.md b/packages/pg-protocol/README.md index 905dfb522..8c52e40ec 100644 --- a/packages/pg-protocol/README.md +++ b/packages/pg-protocol/README.md @@ -1,3 +1,3 @@ # pg-protocol -Low level postgres wire protocol parser and serailizer written in Typescript. Used by node-postgres. Needs more documentation. :smile: +Low level postgres wire protocol parser and serializer written in Typescript. Used by node-postgres. Needs more documentation. :smile: From 4bc55834b93f945e3b60378db121e739e0950f92 Mon Sep 17 00:00:00 2001 From: Jakob Krigovsky Date: Sat, 23 Jan 2021 22:53:46 +0100 Subject: [PATCH 0756/1037] Fix typo (#2442) 6be3b9022f83efc721596cc41165afaa07bfceb0 added support for the `sslmode` parameter, not `ssl-mode`. --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 470f8f976..8032fff61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ We do not include break-fix version release in this file. - Switch to optional peer dependencies & remove [semver](https://github.com/brianc/node-postgres/commit/a02dfac5ad2e2abf0dc3a9817f953938acdc19b1) package which has been a small thorn in the side of a few users. - Export `DatabaseError` from [pg-protocol](https://github.com/brianc/node-postgres/commit/58258430d52ee446721cc3e6611e26f8bcaa67f5). -- Add support for `ssl-mode` in the [connection string](https://github.com/brianc/node-postgres/commit/6be3b9022f83efc721596cc41165afaa07bfceb0). +- Add support for `sslmode` in the [connection string](https://github.com/brianc/node-postgres/commit/6be3b9022f83efc721596cc41165afaa07bfceb0). ### pg@8.3.0 From b4f61ad4c0250f0dbeb5a748d3e1c0d37e99527c Mon Sep 17 00:00:00 2001 From: kaue Date: Tue, 26 Jan 2021 19:36:51 -0800 Subject: [PATCH 0757/1037] update license copyright year (#2450) updates license copyright year to 2021 --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index aa66489de..5c1405646 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2010 - 2020 Brian Carlson +Copyright (c) 2010 - 2021 Brian 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 From 4cb73ebc2c04cd039881a015d623436f26058608 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 26 Jan 2021 21:37:23 -0600 Subject: [PATCH 0758/1037] Bump ini from 1.3.5 to 1.3.8 (#2430) Bumps [ini](https://github.com/isaacs/ini) from 1.3.5 to 1.3.8. - [Release notes](https://github.com/isaacs/ini/releases) - [Commits](https://github.com/isaacs/ini/compare/v1.3.5...v1.3.8) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index a9273e00c..61f44b5dc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3306,9 +3306,9 @@ inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== ini@^1.3.2, ini@^1.3.4: - version "1.3.5" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" - integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== init-package-json@^1.10.3: version "1.10.3" From 25f658f227a1bcbe759423678a7ab4ba8e067994 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Fri, 29 Jan 2021 11:55:05 -0500 Subject: [PATCH 0759/1037] Fix README to separate sponsors onto separate lines (#2459) Splits sponsor listings onto multiple lines by putting them in list elements. Also removes hidden inline png that does not render on the README. --- README.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index dcd89d8d9..2e1ef3dbe 100644 --- a/README.md +++ b/README.md @@ -59,13 +59,16 @@ You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) and these featured sponsors:
- - - - - - - +

+ + + +

+

+ + + +

If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable [please consider supporting](https://github.com/sponsors/brianc) its development. From 5a41a568624bae71c03d35726bb3fc4084e0dd80 Mon Sep 17 00:00:00 2001 From: Emily Marigold Klassen Date: Fri, 12 Mar 2021 06:23:13 -0800 Subject: [PATCH 0760/1037] Add missing metadata to package.jsons (#2487) Co-authored-by: Emily Marigold Klassen --- packages/pg-connection-string/package.json | 3 ++- packages/pg-cursor/package.json | 3 ++- packages/pg-pool/package.json | 3 ++- packages/pg-protocol/package.json | 5 +++++ packages/pg-query-stream/package.json | 3 ++- packages/pg/package.json | 3 ++- 6 files changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index e8ea95a1f..9eb2191ef 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -11,7 +11,8 @@ }, "repository": { "type": "git", - "url": "git://github.com/brianc/node-postgres.git" + "url": "git://github.com/brianc/node-postgres.git", + "directory": "packages/pg-connection-string" }, "keywords": [ "pg", diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 4da335568..2d259580c 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -11,7 +11,8 @@ }, "repository": { "type": "git", - "url": "git://github.com/brianc/node-postgres.git" + "url": "git://github.com/brianc/node-postgres.git", + "directory": "packages/pg-cursor" }, "author": "Brian M. Carlson", "license": "MIT", diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 19ae81777..1488cd408 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -11,7 +11,8 @@ }, "repository": { "type": "git", - "url": "git://github.com/brianc/node-postgres.git" + "url": "git://github.com/brianc/node-postgres.git", + "directory": "packages/pg-pool" }, "keywords": [ "pg", diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 05f74ae10..8f196d4d1 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -22,6 +22,11 @@ "prepublish": "yarn build", "pretest": "yarn build" }, + "repository": { + "type": "git", + "url": "git://github.com/brianc/node-postgres.git", + "directory": "packages/pg-protocol" + }, "files": [ "/dist/*{js,ts,map}", "/src" diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 0b3012265..22532f931 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -9,7 +9,8 @@ }, "repository": { "type": "git", - "url": "git://github.com/brianc/node-postgres.git" + "url": "git://github.com/brianc/node-postgres.git", + "directory": "packages/pg-query-stream" }, "keywords": [ "postgres", diff --git a/packages/pg/package.json b/packages/pg/package.json index 32439f61b..b4cafdac2 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -14,7 +14,8 @@ "homepage": "https://github.com/brianc/node-postgres", "repository": { "type": "git", - "url": "git://github.com/brianc/node-postgres.git" + "url": "git://github.com/brianc/node-postgres.git", + "directory": "packages/pg" }, "author": "Brian Carlson ", "main": "./lib", From 2a7c614583f7b9eea7704de1982b11a0534b12e8 Mon Sep 17 00:00:00 2001 From: Edward O'Reilly Date: Fri, 12 Mar 2021 14:24:07 +0000 Subject: [PATCH 0761/1037] Adding pg to peerDependencies (#2471) * Adding pg to peerDependencies Yarn2 requires strict imports, I.E. all project dependencies need to exist in that project's package.json. * pg version should be locked on the major version Co-authored-by: Charmander <~@charmander.me> Co-authored-by: Charmander <~@charmander.me> --- packages/pg-cursor/package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 2d259580c..e360af46b 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -19,5 +19,8 @@ "devDependencies": { "mocha": "^7.1.2", "pg": "^8.5.1" + }, + "peerDependencies": { + "pg": "^8" } } From 61dfda7439212fbb6637036c3005c7906cd1025b Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 12 Mar 2021 08:40:22 -0600 Subject: [PATCH 0762/1037] Update SPONSORS.md --- SPONSORS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/SPONSORS.md b/SPONSORS.md index 1188ccedb..9d7d314dd 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -10,6 +10,8 @@ node-postgres is made possible by the helpful contributors from the community as - [BitMEX](https://www.bitmex.com/app/trade/XBTUSD) - [Dataform](https://dataform.co/) - [Eaze](https://www.eaze.com/) +- [simpleanalytics](https://simpleanalytics.com/) +- [n8n.io]https://n8n.io/ # Supporters @@ -37,3 +39,4 @@ node-postgres is made possible by the helpful contributors from the community as - @Guido4000 - [Martti Laine](https://github.com/codeclown) - [Tim Nolet](https://github.com/tnolet) +- [checkly](https://github.com/checkly) From 69af1cc9340a3b25eaabfeb7f4dbce1a34b955f5 Mon Sep 17 00:00:00 2001 From: Brian C Date: Fri, 12 Mar 2021 08:41:13 -0600 Subject: [PATCH 0763/1037] Remove dead badge from readme --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 2e1ef3dbe..bf3a7be82 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # node-postgres [![Build Status](https://secure.travis-ci.org/brianc/node-postgres.svg?branch=master)](http://travis-ci.org/brianc/node-postgres) -[![Dependency Status](https://david-dm.org/brianc/node-postgres.svg?path=packages/pg)](https://david-dm.org/brianc/node-postgres?path=packages/pg) NPM version NPM downloads From 45fa27ea4ae9a9a9cf78b50b325d8da871b1c796 Mon Sep 17 00:00:00 2001 From: Emily Marigold Klassen Date: Fri, 12 Mar 2021 09:01:51 -0800 Subject: [PATCH 0764/1037] [pg-protocol] use literals instead of const enum (#2490) Co-authored-by: Emily Marigold Klassen --- packages/pg-protocol/src/messages.ts | 91 ++++++++++++++-------------- packages/pg-protocol/src/parser.ts | 24 ++++---- 2 files changed, 56 insertions(+), 59 deletions(-) diff --git a/packages/pg-protocol/src/messages.ts b/packages/pg-protocol/src/messages.ts index 03c2f61ea..d2ea436df 100644 --- a/packages/pg-protocol/src/messages.ts +++ b/packages/pg-protocol/src/messages.ts @@ -1,33 +1,32 @@ export type Mode = 'text' | 'binary' -export const enum MessageName { - parseComplete = 'parseComplete', - bindComplete = 'bindComplete', - closeComplete = 'closeComplete', - noData = 'noData', - portalSuspended = 'portalSuspended', - replicationStart = 'replicationStart', - emptyQuery = 'emptyQuery', - copyDone = 'copyDone', - copyData = 'copyData', - rowDescription = 'rowDescription', - parameterStatus = 'parameterStatus', - backendKeyData = 'backendKeyData', - notification = 'notification', - readyForQuery = 'readyForQuery', - commandComplete = 'commandComplete', - dataRow = 'dataRow', - copyInResponse = 'copyInResponse', - copyOutResponse = 'copyOutResponse', - authenticationOk = 'authenticationOk', - authenticationMD5Password = 'authenticationMD5Password', - authenticationCleartextPassword = 'authenticationCleartextPassword', - authenticationSASL = 'authenticationSASL', - authenticationSASLContinue = 'authenticationSASLContinue', - authenticationSASLFinal = 'authenticationSASLFinal', - error = 'error', - notice = 'notice', -} +export type MessageName = + | 'parseComplete' + | 'bindComplete' + | 'closeComplete' + | 'noData' + | 'portalSuspended' + | 'replicationStart' + | 'emptyQuery' + | 'copyDone' + | 'copyData' + | 'rowDescription' + | 'parameterStatus' + | 'backendKeyData' + | 'notification' + | 'readyForQuery' + | 'commandComplete' + | 'dataRow' + | 'copyInResponse' + | 'copyOutResponse' + | 'authenticationOk' + | 'authenticationMD5Password' + | 'authenticationCleartextPassword' + | 'authenticationSASL' + | 'authenticationSASLContinue' + | 'authenticationSASLFinal' + | 'error' + | 'notice' export interface BackendMessage { name: MessageName @@ -35,42 +34,42 @@ export interface BackendMessage { } export const parseComplete: BackendMessage = { - name: MessageName.parseComplete, + name: 'parseComplete', length: 5, } export const bindComplete: BackendMessage = { - name: MessageName.bindComplete, + name: 'bindComplete', length: 5, } export const closeComplete: BackendMessage = { - name: MessageName.closeComplete, + name: 'closeComplete', length: 5, } export const noData: BackendMessage = { - name: MessageName.noData, + name: 'noData', length: 5, } export const portalSuspended: BackendMessage = { - name: MessageName.portalSuspended, + name: 'portalSuspended', length: 5, } export const replicationStart: BackendMessage = { - name: MessageName.replicationStart, + name: 'replicationStart', length: 4, } export const emptyQuery: BackendMessage = { - name: MessageName.emptyQuery, + name: 'emptyQuery', length: 4, } export const copyDone: BackendMessage = { - name: MessageName.copyDone, + name: 'copyDone', length: 4, } @@ -117,7 +116,7 @@ export class DatabaseError extends Error implements NoticeOrError { } export class CopyDataMessage { - public readonly name = MessageName.copyData + public readonly name = 'copyData' constructor(public readonly length: number, public readonly chunk: Buffer) {} } @@ -146,7 +145,7 @@ export class Field { } export class RowDescriptionMessage { - public readonly name: MessageName = MessageName.rowDescription + public readonly name: MessageName = 'rowDescription' public readonly fields: Field[] constructor(public readonly length: number, public readonly fieldCount: number) { this.fields = new Array(this.fieldCount) @@ -154,7 +153,7 @@ export class RowDescriptionMessage { } export class ParameterStatusMessage { - public readonly name: MessageName = MessageName.parameterStatus + public readonly name: MessageName = 'parameterStatus' constructor( public readonly length: number, public readonly parameterName: string, @@ -163,17 +162,17 @@ export class ParameterStatusMessage { } export class AuthenticationMD5Password implements BackendMessage { - public readonly name: MessageName = MessageName.authenticationMD5Password + public readonly name: MessageName = 'authenticationMD5Password' constructor(public readonly length: number, public readonly salt: Buffer) {} } export class BackendKeyDataMessage { - public readonly name: MessageName = MessageName.backendKeyData + public readonly name: MessageName = 'backendKeyData' constructor(public readonly length: number, public readonly processID: number, public readonly secretKey: number) {} } export class NotificationResponseMessage { - public readonly name: MessageName = MessageName.notification + public readonly name: MessageName = 'notification' constructor( public readonly length: number, public readonly processId: number, @@ -183,18 +182,18 @@ export class NotificationResponseMessage { } export class ReadyForQueryMessage { - public readonly name: MessageName = MessageName.readyForQuery + public readonly name: MessageName = 'readyForQuery' constructor(public readonly length: number, public readonly status: string) {} } export class CommandCompleteMessage { - public readonly name: MessageName = MessageName.commandComplete + public readonly name: MessageName = 'commandComplete' constructor(public readonly length: number, public readonly text: string) {} } export class DataRowMessage { public readonly fieldCount: number - public readonly name: MessageName = MessageName.dataRow + public readonly name: MessageName = 'dataRow' constructor(public length: number, public fields: any[]) { this.fieldCount = fields.length } @@ -202,7 +201,7 @@ export class DataRowMessage { export class NoticeMessage implements BackendMessage, NoticeOrError { constructor(public readonly length: number, public readonly message: string | undefined) {} - public readonly name = MessageName.notice + public readonly name = 'notice' public severity: string | undefined public code: string | undefined public detail: string | undefined diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index a00dabec9..804edebd4 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -183,9 +183,9 @@ export class Parser { case MessageCodes.BackendKeyData: return this.parseBackendKeyData(offset, length, bytes) case MessageCodes.ErrorMessage: - return this.parseErrorMessage(offset, length, bytes, MessageName.error) + return this.parseErrorMessage(offset, length, bytes, 'error') case MessageCodes.NoticeMessage: - return this.parseErrorMessage(offset, length, bytes, MessageName.notice) + return this.parseErrorMessage(offset, length, bytes, 'notice') case MessageCodes.RowDescriptionMessage: return this.parseRowDescriptionMessage(offset, length, bytes) case MessageCodes.CopyIn: @@ -217,11 +217,11 @@ export class Parser { } private parseCopyInMessage(offset: number, length: number, bytes: Buffer) { - return this.parseCopyMessage(offset, length, bytes, MessageName.copyInResponse) + return this.parseCopyMessage(offset, length, bytes, 'copyInResponse') } private parseCopyOutMessage(offset: number, length: number, bytes: Buffer) { - return this.parseCopyMessage(offset, length, bytes, MessageName.copyOutResponse) + return this.parseCopyMessage(offset, length, bytes, 'copyOutResponse') } private parseCopyMessage(offset: number, length: number, bytes: Buffer, messageName: MessageName) { @@ -295,7 +295,7 @@ export class Parser { const code = this.reader.int32() // TODO(bmc): maybe better types here const message: BackendMessage & any = { - name: MessageName.authenticationOk, + name: 'authenticationOk', length, } @@ -304,18 +304,18 @@ export class Parser { break case 3: // AuthenticationCleartextPassword if (message.length === 8) { - message.name = MessageName.authenticationCleartextPassword + message.name = 'authenticationCleartextPassword' } break case 5: // AuthenticationMD5Password if (message.length === 12) { - message.name = MessageName.authenticationMD5Password + message.name = 'authenticationMD5Password' const salt = this.reader.bytes(4) return new AuthenticationMD5Password(length, salt) } break case 10: // AuthenticationSASL - message.name = MessageName.authenticationSASL + message.name = 'authenticationSASL' message.mechanisms = [] let mechanism: string do { @@ -327,11 +327,11 @@ export class Parser { } while (mechanism) break case 11: // AuthenticationSASLContinue - message.name = MessageName.authenticationSASLContinue + message.name = 'authenticationSASLContinue' message.data = this.reader.string(length - 8) break case 12: // AuthenticationSASLFinal - message.name = MessageName.authenticationSASLFinal + message.name = 'authenticationSASLFinal' message.data = this.reader.string(length - 8) break default: @@ -352,9 +352,7 @@ export class Parser { const messageValue = fields.M const message = - name === MessageName.notice - ? new NoticeMessage(length, messageValue) - : new DatabaseError(messageValue, length, name) + name === 'notice' ? new NoticeMessage(length, messageValue) : new DatabaseError(messageValue, length, name) message.severity = fields.S message.code = fields.C From 4b229275cfe41ca17b7d69bd39f91ada0068a5d0 Mon Sep 17 00:00:00 2001 From: Kannan Goundan Date: Mon, 22 Mar 2021 14:07:05 -0400 Subject: [PATCH 0765/1037] pg: Re-export DatabaseError from 'pg-protocol' (#2445) * pg: Re-export DatabaseError from 'pg-protocol' Before, users would have to import DatabaseError from 'pg-protocol'. If there are multiple versions of 'pg-protocol', you might end up using the wrong one. Closes #2378 * Update error-handling-tests.js * Update query-error-handling-tests.js Co-authored-by: Brian C --- packages/pg/lib/index.js | 2 ++ .../pg/test/integration/client/error-handling-tests.js | 7 +++++++ .../test/integration/client/query-error-handling-tests.js | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/packages/pg/lib/index.js b/packages/pg/lib/index.js index 47eca1fd0..7f02abab5 100644 --- a/packages/pg/lib/index.js +++ b/packages/pg/lib/index.js @@ -4,6 +4,7 @@ var Client = require('./client') var defaults = require('./defaults') var Connection = require('./connection') var Pool = require('pg-pool') +const { DatabaseError } = require('pg-protocol') const poolFactory = (Client) => { return class BoundPool extends Pool { @@ -21,6 +22,7 @@ var PG = function (clientConstructor) { this._pools = [] this.Connection = Connection this.types = require('pg-types') + this.DatabaseError = DatabaseError } if (typeof process.env.NODE_PG_FORCE_NATIVE !== 'undefined') { diff --git a/packages/pg/test/integration/client/error-handling-tests.js b/packages/pg/test/integration/client/error-handling-tests.js index 88e6d39f7..4e879c9e0 100644 --- a/packages/pg/test/integration/client/error-handling-tests.js +++ b/packages/pg/test/integration/client/error-handling-tests.js @@ -5,6 +5,7 @@ var util = require('util') var pg = helper.pg const Client = pg.Client +const DatabaseError = pg.DatabaseError var createErorrClient = function () { var client = helper.client() @@ -140,6 +141,9 @@ suite.test('when a query is binding', function (done) { ) assert.emits(query, 'error', function (err) { + if (!helper.config.native) { + assert(err instanceof DatabaseError) + } assert.equal(err.severity, 'ERROR') ensureFuture(client, done) }) @@ -213,6 +217,9 @@ suite.test('within a simple query', (done) => { var query = client.query(new pg.Query("select eeeee from yodas_dsflsd where pixistix = 'zoiks!!!'")) assert.emits(query, 'error', function (error) { + if (!helper.config.native) { + assert(error instanceof DatabaseError) + } assert.equal(error.severity, 'ERROR') done() }) diff --git a/packages/pg/test/integration/client/query-error-handling-tests.js b/packages/pg/test/integration/client/query-error-handling-tests.js index 34eab8f65..3ede5d972 100644 --- a/packages/pg/test/integration/client/query-error-handling-tests.js +++ b/packages/pg/test/integration/client/query-error-handling-tests.js @@ -2,6 +2,7 @@ var helper = require('./test-helper') var util = require('util') var Query = helper.pg.Query +var DatabaseError = helper.pg.DatabaseError test('error during query execution', function () { var client = new Client(helper.args) @@ -74,6 +75,9 @@ test('9.3 column error fields', function () { client.query('CREATE TEMP TABLE column_err_test(a int NOT NULL)') client.query('INSERT INTO column_err_test(a) VALUES (NULL)', function (err) { + if (!helper.config.native) { + assert(err instanceof DatabaseError) + } assert.equal(err.severity, 'ERROR') assert.equal(err.code, '23502') assert.equal(err.table, 'column_err_test') @@ -102,6 +106,9 @@ test('9.3 constraint error fields', function () { client.query('CREATE TEMP TABLE constraint_err_test(a int PRIMARY KEY)') client.query('INSERT INTO constraint_err_test(a) VALUES (1)') client.query('INSERT INTO constraint_err_test(a) VALUES (1)', function (err) { + if (!helper.config.native) { + assert(err instanceof DatabaseError) + } assert.equal(err.severity, 'ERROR') assert.equal(err.code, '23505') assert.equal(err.table, 'constraint_err_test') From 3dc79b605c9802e67a4263c95e6d4442c1c07ff1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20M=20Mart=C3=ADnez?= Date: Fri, 2 Apr 2021 19:37:39 -0300 Subject: [PATCH 0766/1037] util in connection not used (#2507) --- packages/pg/lib/connection.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index ccb6742c5..7d45de2b7 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -2,7 +2,6 @@ var net = require('net') var EventEmitter = require('events').EventEmitter -var util = require('util') const { parse, serialize } = require('pg-protocol') From 6121bd3bb0e0e8ef8ec8ad5d02f59fef86b2f992 Mon Sep 17 00:00:00 2001 From: Sven Over Date: Tue, 6 Apr 2021 15:01:04 +0100 Subject: [PATCH 0767/1037] Add ParameterDescription message to pg-protocol (#2464) --- .../pg-protocol/src/inbound-parser.test.ts | 35 +++++++++++++++++++ packages/pg-protocol/src/messages.ts | 9 +++++ packages/pg-protocol/src/parser.ts | 14 ++++++++ .../pg-protocol/src/testing/test-buffers.ts | 10 ++++++ 4 files changed, 68 insertions(+) diff --git a/packages/pg-protocol/src/inbound-parser.test.ts b/packages/pg-protocol/src/inbound-parser.test.ts index 3fcbe410a..364bd8d95 100644 --- a/packages/pg-protocol/src/inbound-parser.test.ts +++ b/packages/pg-protocol/src/inbound-parser.test.ts @@ -144,6 +144,35 @@ var expectedTwoRowMessage = { ], } +var emptyParameterDescriptionBuffer = new BufferList() + .addInt16(0) // number of parameters + .join(true, 't') + +var oneParameterDescBuf = buffers.parameterDescription([1111]) + +var twoParameterDescBuf = buffers.parameterDescription([2222, 3333]) + +var expectedEmptyParameterDescriptionMessage = { + name: 'parameterDescription', + length: 6, + parameterCount: 0, + dataTypeIDs: [], +} + +var expectedOneParameterMessage = { + name: 'parameterDescription', + length: 10, + parameterCount: 1, + dataTypeIDs: [1111], +} + +var expectedTwoParameterMessage = { + name: 'parameterDescription', + length: 14, + parameterCount: 2, + dataTypeIDs: [2222, 3333], +} + var testForMessage = function (buffer: Buffer, expectedMessage: any) { it('recieves and parses ' + expectedMessage.name, async () => { const messages = await parseBuffers([buffer]) @@ -245,6 +274,12 @@ describe('PgPacketStream', function () { testForMessage(twoRowBuf, expectedTwoRowMessage) }) + describe('parameterDescription messages', function () { + testForMessage(emptyParameterDescriptionBuffer, expectedEmptyParameterDescriptionMessage) + testForMessage(oneParameterDescBuf, expectedOneParameterMessage) + testForMessage(twoParameterDescBuf, expectedTwoParameterMessage) + }) + describe('parsing rows', function () { describe('parsing empty row', function () { testForMessage(emptyRowFieldBuf, { diff --git a/packages/pg-protocol/src/messages.ts b/packages/pg-protocol/src/messages.ts index d2ea436df..7eab845e5 100644 --- a/packages/pg-protocol/src/messages.ts +++ b/packages/pg-protocol/src/messages.ts @@ -11,6 +11,7 @@ export type MessageName = | 'copyDone' | 'copyData' | 'rowDescription' + | 'parameterDescription' | 'parameterStatus' | 'backendKeyData' | 'notification' @@ -152,6 +153,14 @@ export class RowDescriptionMessage { } } +export class ParameterDescriptionMessage { + public readonly name: MessageName = 'parameterDescription' + public readonly dataTypeIDs: number[] + constructor(public readonly length: number, public readonly parameterCount: number) { + this.dataTypeIDs = new Array(this.parameterCount) + } +} + export class ParameterStatusMessage { public readonly name: MessageName = 'parameterStatus' constructor( diff --git a/packages/pg-protocol/src/parser.ts b/packages/pg-protocol/src/parser.ts index 804edebd4..f900193d7 100644 --- a/packages/pg-protocol/src/parser.ts +++ b/packages/pg-protocol/src/parser.ts @@ -15,6 +15,7 @@ import { CopyResponse, NotificationResponseMessage, RowDescriptionMessage, + ParameterDescriptionMessage, Field, DataRowMessage, ParameterStatusMessage, @@ -62,6 +63,7 @@ const enum MessageCodes { ErrorMessage = 0x45, // E NoticeMessage = 0x4e, // N RowDescriptionMessage = 0x54, // T + ParameterDescriptionMessage = 0x74, // t PortalSuspended = 0x73, // s ReplicationStart = 0x57, // W EmptyQuery = 0x49, // I @@ -188,6 +190,8 @@ export class Parser { return this.parseErrorMessage(offset, length, bytes, 'notice') case MessageCodes.RowDescriptionMessage: return this.parseRowDescriptionMessage(offset, length, bytes) + case MessageCodes.ParameterDescriptionMessage: + return this.parseParameterDescriptionMessage(offset, length, bytes) case MessageCodes.CopyIn: return this.parseCopyInMessage(offset, length, bytes) case MessageCodes.CopyOut: @@ -264,6 +268,16 @@ export class Parser { return new Field(name, tableID, columnID, dataTypeID, dataTypeSize, dataTypeModifier, mode) } + private parseParameterDescriptionMessage(offset: number, length: number, bytes: Buffer) { + this.reader.setBuffer(offset, bytes) + const parameterCount = this.reader.int16() + const message = new ParameterDescriptionMessage(length, parameterCount) + for (let i = 0; i < parameterCount; i++) { + message.dataTypeIDs[i] = this.reader.int32() + } + return message + } + private parseDataRowMessage(offset: number, length: number, bytes: Buffer) { this.reader.setBuffer(offset, bytes) const fieldCount = this.reader.int16() diff --git a/packages/pg-protocol/src/testing/test-buffers.ts b/packages/pg-protocol/src/testing/test-buffers.ts index 19ba16cce..e0a04a758 100644 --- a/packages/pg-protocol/src/testing/test-buffers.ts +++ b/packages/pg-protocol/src/testing/test-buffers.ts @@ -62,6 +62,16 @@ const buffers = { return buf.join(true, 'T') }, + parameterDescription: function (dataTypeIDs: number[]) { + dataTypeIDs = dataTypeIDs || [] + var buf = new BufferList() + buf.addInt16(dataTypeIDs.length) + dataTypeIDs.forEach(function (dataTypeID) { + buf.addInt32(dataTypeID) + }) + return buf.join(true, 't') + }, + dataRow: function (columns: any[]) { columns = columns || [] var buf = new BufferList() From d99b5741f82e0ddc109e0ffd08d4cf674c20fd52 Mon Sep 17 00:00:00 2001 From: Felix Pusch Date: Tue, 13 Apr 2021 17:56:37 +0200 Subject: [PATCH 0768/1037] pg-query-stream: remove through dependency (#2518) --- packages/pg-query-stream/package.json | 1 - packages/pg-query-stream/test/concat.ts | 9 ++++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 22532f931..f93e4fa67 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -40,7 +40,6 @@ "pg": "^8.5.1", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", - "through": "~2.3.4", "ts-node": "^8.5.4", "typescript": "^4.0.3" }, diff --git a/packages/pg-query-stream/test/concat.ts b/packages/pg-query-stream/test/concat.ts index 980038578..bdfa15862 100644 --- a/packages/pg-query-stream/test/concat.ts +++ b/packages/pg-query-stream/test/concat.ts @@ -1,6 +1,6 @@ import assert from 'assert' import concat from 'concat-stream' -import through from 'through' +import { Transform } from 'stream' import helper from './helper' import QueryStream from '../src' @@ -10,8 +10,11 @@ helper('concat', function (client) { const query = client.query(stream) query .pipe( - through(function (row) { - this.push(row.num) + new Transform({ + transform(chunk, _, callback) { + callback(null, chunk.num) + }, + objectMode: true, }) ) .pipe( From 8faf8a093722de5be176407bda0e356074a61c60 Mon Sep 17 00:00:00 2001 From: Erona Date: Tue, 13 Apr 2021 23:57:37 +0800 Subject: [PATCH 0769/1037] fix(pg-cursor): EventEmitter memory leak (#2501) --- packages/pg-cursor/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index d26e77bdc..ca86c9e45 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -28,6 +28,9 @@ util.inherits(Cursor, EventEmitter) Cursor.prototype._ifNoData = function () { this.state = 'idle' this._shiftQueue() + if (this.connection) { + this.connection.removeListener('rowDescription', this._rowDescription) + } } Cursor.prototype._rowDescription = function () { From 3115be68902a75834c72a0b72834ff0028b39db6 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Apr 2021 11:02:10 -0500 Subject: [PATCH 0770/1037] Update changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8032fff61..26e368ff9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### pg@8.6.0 + +- Better [SASL](https://github.com/brianc/node-postgres/pull/2436) error messages & more validation on bad configuration. +- Export [DatabaseError](https://github.com/brianc/node-postgres/pull/2445). +- Add [ParameterDescription](https://github.com/brianc/node-postgres/pull/2464) support to protocol parsing. +- Fix typescript [typedefs](https://github.com/brianc/node-postgres/pull/2490) with `--isolatedModules`. + ### pg-query-stream@4.0.0 - Library has been [converted](https://github.com/brianc/node-postgres/pull/2376) to Typescript. The behavior is identical, but there could be subtle breaking changes due to class names changing or other small inconsistencies introduced by the conversion. From d45947938263bec30a1e3252452f04177b785f66 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 13 Apr 2021 11:02:40 -0500 Subject: [PATCH 0771/1037] Publish - pg-connection-string@2.5.0 - pg-cursor@2.6.0 - pg-pool@3.3.0 - pg-protocol@1.5.0 - pg-query-stream@4.1.0 - pg@8.6.0 --- packages/pg-connection-string/package.json | 2 +- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 8 ++++---- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/pg-connection-string/package.json b/packages/pg-connection-string/package.json index 9eb2191ef..67543278d 100644 --- a/packages/pg-connection-string/package.json +++ b/packages/pg-connection-string/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "2.4.0", + "version": "2.5.0", "description": "Functions for dealing with a PostgresSQL connection string", "main": "./index.js", "types": "./index.d.ts", diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index e360af46b..5607ea955 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.5.2", + "version": "2.6.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.5.1" + "pg": "^8.6.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 1488cd408..b92e7df90 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.2.2", + "version": "3.3.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index 8f196d4d1..ae9ba6f52 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.4.0", + "version": "1.5.0", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index f93e4fa67..d01b18d86 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "4.0.0", + "version": "4.1.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,13 +37,13 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.5.1", + "pg": "^8.6.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" }, "dependencies": { - "pg-cursor": "^2.5.2" + "pg-cursor": "^2.6.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index b4cafdac2..af71629f3 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.5.1", + "version": "8.6.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -22,9 +22,9 @@ "dependencies": { "buffer-writer": "2.0.0", "packet-reader": "1.0.0", - "pg-connection-string": "^2.4.0", - "pg-pool": "^3.2.2", - "pg-protocol": "^1.4.0", + "pg-connection-string": "^2.5.0", + "pg-pool": "^3.3.0", + "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" }, From 8f0db306d9676dd89aeb4b044f5e6402a85da2f0 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Tue, 27 Apr 2021 20:34:08 +0000 Subject: [PATCH 0772/1037] Remove broken test (#2529) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It’s missing `co.wrap`, so it doesn’t actually run (Mocha does nothing with the paused generator). The test group that follows it, “using an ended pool”, covers the same thing anyway. --- packages/pg-pool/test/error-handling.js | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/packages/pg-pool/test/error-handling.js b/packages/pg-pool/test/error-handling.js index fea1d1148..0a996b82b 100644 --- a/packages/pg-pool/test/error-handling.js +++ b/packages/pg-pool/test/error-handling.js @@ -65,18 +65,6 @@ describe('pool error handling', function () { }) }) - 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() From 7667e7c9e730f6bf9e23682cfbd653674f040a67 Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Thu, 27 May 2021 23:37:07 +0000 Subject: [PATCH 0773/1037] Fix and enable pool `verify` option test (#2528) by not double-releasing. Reviewed-by: Sehrope Sarkuni --- packages/pg-pool/test/verify.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/pg-pool/test/verify.js b/packages/pg-pool/test/verify.js index e7ae1dd88..9331e1a06 100644 --- a/packages/pg-pool/test/verify.js +++ b/packages/pg-pool/test/verify.js @@ -7,10 +7,9 @@ const it = require('mocha').it const Pool = require('../') describe('verify', () => { - it('verifies a client with a callback', false, (done) => { + it('verifies a client with a callback', (done) => { const pool = new Pool({ verify: (client, cb) => { - client.release() cb(new Error('nope')) }, }) From d6ed9e756ef689dbffce1de56cc95c7828fc2b2d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Jun 2021 11:27:01 -0500 Subject: [PATCH 0774/1037] Bump lodash from 4.17.20 to 4.17.21 (#2540) Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21. - [Release notes](https://github.com/lodash/lodash/releases) - [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 61f44b5dc..e579f984e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3888,9 +3888,9 @@ lodash.uniq@^4.5.0: integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.2.1: - version "4.17.20" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" - integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" + integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== log-driver@^1.2.7: version "1.2.7" @@ -5937,7 +5937,7 @@ through2@^3.0.0: inherits "^2.0.4" readable-stream "2 || 3" -through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6, through@~2.3.4: +through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= From a04003164b788c66d884661b445b6ad5a41ef92b Mon Sep 17 00:00:00 2001 From: Bluenix Date: Tue, 22 Jun 2021 16:52:10 +0200 Subject: [PATCH 0775/1037] Turn Cursor into an ES6 class (#2553) * Turn Cursor into an ES6 class * Fix incorrect syntax in Cursor.end() * Remove extraneous empty line * Revert es6 change for end() * Revert back to defining the end() method inside the class * Use hanging indent to satisfy Prettier --- packages/pg-cursor/index.js | 383 ++++++++++++++++++------------------ 1 file changed, 194 insertions(+), 189 deletions(-) diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index ca86c9e45..8e8552be8 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -6,231 +6,236 @@ const util = require('util') let nextUniqueID = 1 // concept borrowed from org.postgresql.core.v3.QueryExecutorImpl -function Cursor(text, values, config) { - EventEmitter.call(this) - - this._conf = config || {} - this.text = text - this.values = values ? values.map(prepare) : null - this.connection = null - this._queue = [] - this.state = 'initialized' - this._result = new Result(this._conf.rowMode, this._conf.types) - this._cb = null - this._rows = null - this._portal = null - this._ifNoData = this._ifNoData.bind(this) - this._rowDescription = this._rowDescription.bind(this) -} - -util.inherits(Cursor, EventEmitter) - -Cursor.prototype._ifNoData = function () { - this.state = 'idle' - this._shiftQueue() - if (this.connection) { - this.connection.removeListener('rowDescription', this._rowDescription) +class Cursor extends EventEmitter { + constructor(text, values, config) { + super() + + this._conf = config || {} + this.text = text + this.values = values ? values.map(prepare) : null + this.connection = null + this._queue = [] + this.state = 'initialized' + this._result = new Result(this._conf.rowMode, this._conf.types) + this._cb = null + this._rows = null + this._portal = null + this._ifNoData = this._ifNoData.bind(this) + this._rowDescription = this._rowDescription.bind(this) } -} -Cursor.prototype._rowDescription = function () { - if (this.connection) { - this.connection.removeListener('noData', this._ifNoData) + _ifNoData() { + this.state = 'idle' + this._shiftQueue() + if (this.connection) { + this.connection.removeListener('rowDescription', this._rowDescription) + } } -} -Cursor.prototype.submit = function (connection) { - this.state = 'submitted' - this.connection = connection - this._portal = 'C_' + nextUniqueID++ + _rowDescription() { + if (this.connection) { + this.connection.removeListener('noData', this._ifNoData) + } + } - const con = connection + submit(connection) { + this.state = 'submitted' + this.connection = connection + this._portal = 'C_' + nextUniqueID++ + + const con = connection + + con.parse( + { + text: this.text, + }, + true + ) + + con.bind( + { + portal: this._portal, + values: this.values, + }, + true + ) + + con.describe( + { + type: 'P', + name: this._portal, // AWS Redshift requires a portal name + }, + true + ) + + con.flush() + + if (this._conf.types) { + this._result._getTypeParser = this._conf.types.getTypeParser + } - con.parse( - { - text: this.text, - }, - true - ) + con.once('noData', this._ifNoData) + con.once('rowDescription', this._rowDescription) + } - con.bind( - { - portal: this._portal, - values: this.values, - }, - true - ) + _shiftQueue() { + if (this._queue.length) { + this._getRows.apply(this, this._queue.shift()) + } + } - con.describe( - { - type: 'P', - name: this._portal, // AWS Redshift requires a portal name - }, - true - ) + _closePortal() { + // because we opened a named portal to stream results + // we need to close the same named portal. Leaving a named portal + // open can lock tables for modification if inside a transaction. + // see https://github.com/brianc/node-pg-cursor/issues/56 + this.connection.close({ type: 'P', name: this._portal }) - con.flush() + // If we've received an error we already sent a sync message. + // do not send another sync as it triggers another readyForQuery message. + if (this.state !== 'error') { + this.connection.sync() + } + } - if (this._conf.types) { - this._result._getTypeParser = this._conf.types.getTypeParser + handleRowDescription(msg) { + this._result.addFields(msg.fields) + this.state = 'idle' + this._shiftQueue() } - con.once('noData', this._ifNoData) - con.once('rowDescription', this._rowDescription) -} + handleDataRow(msg) { + const row = this._result.parseRow(msg.fields) + this.emit('row', row, this._result) + this._rows.push(row) + } -Cursor.prototype._shiftQueue = function () { - if (this._queue.length) { - this._getRows.apply(this, this._queue.shift()) + _sendRows() { + this.state = 'idle' + setImmediate(() => { + const cb = this._cb + // remove callback before calling it + // because likely a new one will be added + // within the call to this callback + this._cb = null + if (cb) { + this._result.rows = this._rows + cb(null, this._rows, this._result) + } + this._rows = [] + }) } -} -Cursor.prototype._closePortal = function () { - // because we opened a named portal to stream results - // we need to close the same named portal. Leaving a named portal - // open can lock tables for modification if inside a transaction. - // see https://github.com/brianc/node-pg-cursor/issues/56 - this.connection.close({ type: 'P', name: this._portal }) + handleCommandComplete(msg) { + this._result.addCommandComplete(msg) + this._closePortal() + } - // If we've received an error we already sent a sync message. - // do not send another sync as it triggers another readyForQuery message. - if (this.state !== 'error') { - this.connection.sync() + handlePortalSuspended() { + this._sendRows() } -} -Cursor.prototype.handleRowDescription = function (msg) { - this._result.addFields(msg.fields) - this.state = 'idle' - this._shiftQueue() -} + handleReadyForQuery() { + this._sendRows() + this.state = 'done' + this.emit('end', this._result) + } -Cursor.prototype.handleDataRow = function (msg) { - const row = this._result.parseRow(msg.fields) - this.emit('row', row, this._result) - this._rows.push(row) -} + handleEmptyQuery() { + this.connection.sync() + } -Cursor.prototype._sendRows = function () { - this.state = 'idle' - setImmediate(() => { - const cb = this._cb - // remove callback before calling it - // because likely a new one will be added - // within the call to this callback - this._cb = null - if (cb) { - this._result.rows = this._rows - cb(null, this._rows, this._result) + handleError(msg) { + // If we're in an initialized state we've never been submitted + // and don't have a connection instance reference yet. + // This can happen if you queue a stream and close the client before + // the client has submitted the stream. In this scenario we don't have + // a connection so there's nothing to unsubscribe from. + if (this.state !== 'initialized') { + this.connection.removeListener('noData', this._ifNoData) + this.connection.removeListener('rowDescription', this._rowDescription) + // call sync to trigger a readyForQuery + this.connection.sync() } - this._rows = [] - }) -} - -Cursor.prototype.handleCommandComplete = function (msg) { - this._result.addCommandComplete(msg) - this._closePortal() -} -Cursor.prototype.handlePortalSuspended = function () { - this._sendRows() -} - -Cursor.prototype.handleReadyForQuery = function () { - this._sendRows() - this.state = 'done' - this.emit('end', this._result) -} - -Cursor.prototype.handleEmptyQuery = function () { - this.connection.sync() -} + this.state = 'error' + this._error = msg + // satisfy any waiting callback + if (this._cb) { + this._cb(msg) + } + // dispatch error to all waiting callbacks + for (let i = 0; i < this._queue.length; i++) { + this._queue.pop()[1](msg) + } -Cursor.prototype.handleError = function (msg) { - // If we're in an initialized state we've never been submitted - // and don't have a connection instance reference yet. - // This can happen if you queue a stream and close the client before - // the client has submitted the stream. In this scenario we don't have - // a connection so there's nothing to unsubscribe from. - if (this.state !== 'initialized') { - this.connection.removeListener('noData', this._ifNoData) - this.connection.removeListener('rowDescription', this._rowDescription) - // call sync to trigger a readyForQuery - this.connection.sync() + if (this.listenerCount('error') > 0) { + // only dispatch error events if we have a listener + this.emit('error', msg) + } } - this.state = 'error' - this._error = msg - // satisfy any waiting callback - if (this._cb) { - this._cb(msg) - } - // dispatch error to all waiting callbacks - for (let i = 0; i < this._queue.length; i++) { - this._queue.pop()[1](msg) + _getRows(rows, cb) { + this.state = 'busy' + this._cb = cb + this._rows = [] + const msg = { + portal: this._portal, + rows: rows, + } + this.connection.execute(msg, true) + this.connection.flush() } - if (this.listenerCount('error') > 0) { - // only dispatch error events if we have a listener - this.emit('error', msg) + // users really shouldn't be calling 'end' here and terminating a connection to postgres + // via the low level connection.end api + end(cb) { + if (this.state !== 'initialized') { + this.connection.sync() + } + this.connection.once('end', cb) + this.connection.end() } -} -Cursor.prototype._getRows = function (rows, cb) { - this.state = 'busy' - this._cb = cb - this._rows = [] - const msg = { - portal: this._portal, - rows: rows, - } - this.connection.execute(msg, true) - this.connection.flush() -} - -// users really shouldn't be calling 'end' here and terminating a connection to postgres -// via the low level connection.end api -Cursor.prototype.end = util.deprecate(function (cb) { - if (this.state !== 'initialized') { - this.connection.sync() - } - this.connection.once('end', cb) - this.connection.end() -}, 'Cursor.end is deprecated. Call end on the client itself to end a connection to the database.') + close(cb) { + if (!this.connection || this.state === 'done') { + if (cb) { + return setImmediate(cb) + } else { + return + } + } -Cursor.prototype.close = function (cb) { - if (!this.connection || this.state === 'done') { + this._closePortal() + this.state = 'done' if (cb) { - return setImmediate(cb) - } else { - return + this.connection.once('readyForQuery', function () { + cb() + }) } } - this._closePortal() - this.state = 'done' - if (cb) { - this.connection.once('readyForQuery', function () { - cb() - }) + read(rows, cb) { + if (this.state === 'idle' || this.state === 'submitted') { + return this._getRows(rows, cb) + } + if (this.state === 'busy' || this.state === 'initialized') { + return this._queue.push([rows, cb]) + } + if (this.state === 'error') { + return setImmediate(() => cb(this._error)) + } + if (this.state === 'done') { + return setImmediate(() => cb(null, [])) + } else { + throw new Error('Unknown state: ' + this.state) + } } } -Cursor.prototype.read = function (rows, cb) { - if (this.state === 'idle' || this.state === 'submitted') { - return this._getRows(rows, cb) - } - if (this.state === 'busy' || this.state === 'initialized') { - return this._queue.push([rows, cb]) - } - if (this.state === 'error') { - return setImmediate(() => cb(this._error)) - } - if (this.state === 'done') { - return setImmediate(() => cb(null, [])) - } else { - throw new Error('Unknown state: ' + this.state) - } -} +Cursor.prototype.end = util.deprecate( + Cursor.prototype.end, + 'Cursor.end is deprecated. Call end on the client itself to end a connection to the database.' +) module.exports = Cursor From 9d2c977ce9b13f8f3b024759b1deaec165564a6a Mon Sep 17 00:00:00 2001 From: Greg Brown Date: Wed, 23 Jun 2021 02:55:21 +1200 Subject: [PATCH 0776/1037] Use _isFull instead of duplicating clients check (#2539) Noticed that options.max is compared against client count directly, but there's a method wrapping it. I can't see any reason to duplicate it? And using _isFull means I can override that for the adaptive pooling idea I'm exploring :) --- packages/pg-pool/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 780f18652..403d05a19 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -168,7 +168,7 @@ class Pool extends EventEmitter { const result = response.result // if we don't have to connect a new client, don't do so - if (this._clients.length >= this.options.max || this._idle.length) { + if (this._isFull() || this._idle.length) { // if we have idle clients schedule a pulse immediately if (this._idle.length) { process.nextTick(() => this._pulseQueue()) From aedaa59afe6028fb1a13187695325e8dbacb2c30 Mon Sep 17 00:00:00 2001 From: Bluenix Date: Tue, 27 Jul 2021 16:40:32 +0200 Subject: [PATCH 0777/1037] Add support for using promises in Cursor methods (#2554) * Add similar promise variables to read() and close() as seen in query() * Add testing for promise specific usage * Simplify tests as no real callbacks are involved Removes usage of `done()` since we can end the test when we exit the function Co-Authored-By: Charmander <~@charmander.me> * Switch to let over var Co-authored-by: Charmander <~@charmander.me> --- packages/pg-cursor/index.js | 40 ++++++++++++++++------ packages/pg-cursor/test/promises.js | 51 +++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 packages/pg-cursor/test/promises.js diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index 8e8552be8..b77fd5977 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -17,6 +17,7 @@ class Cursor extends EventEmitter { this._queue = [] this.state = 'initialized' this._result = new Result(this._conf.rowMode, this._conf.types) + this._Promise = this._conf.Promise || global.Promise this._cb = null this._rows = null this._portal = null @@ -198,6 +199,14 @@ class Cursor extends EventEmitter { } close(cb) { + let promise + + if (!cb) { + promise = new this._Promise((resolve, reject) => { + cb = (err) => (err ? reject(err) : resolve()) + }) + } + if (!this.connection || this.state === 'done') { if (cb) { return setImmediate(cb) @@ -213,23 +222,34 @@ class Cursor extends EventEmitter { cb() }) } + + // Return the promise (or undefined) + return promise } read(rows, cb) { - if (this.state === 'idle' || this.state === 'submitted') { - return this._getRows(rows, cb) - } - if (this.state === 'busy' || this.state === 'initialized') { - return this._queue.push([rows, cb]) - } - if (this.state === 'error') { - return setImmediate(() => cb(this._error)) + let promise + + if (!cb) { + promise = new this._Promise((resolve, reject) => { + cb = (err, rows) => (err ? reject(err) : resolve(rows)) + }) } - if (this.state === 'done') { - return setImmediate(() => cb(null, [])) + + if (this.state === 'idle' || this.state === 'submitted') { + this._getRows(rows, cb) + } else if (this.state === 'busy' || this.state === 'initialized') { + this._queue.push([rows, cb]) + } else if (this.state === 'error') { + setImmediate(() => cb(this._error)) + } else if (this.state === 'done') { + setImmediate(() => cb(null, [])) } else { throw new Error('Unknown state: ' + this.state) } + + // Return the promise (or undefined) + return promise } } diff --git a/packages/pg-cursor/test/promises.js b/packages/pg-cursor/test/promises.js new file mode 100644 index 000000000..7b36dab8f --- /dev/null +++ b/packages/pg-cursor/test/promises.js @@ -0,0 +1,51 @@ +const assert = require('assert') +const Cursor = require('../') +const pg = require('pg') + +const text = 'SELECT generate_series as num FROM generate_series(0, 5)' + +describe('cursor using promises', function () { + beforeEach(function (done) { + const client = (this.client = new pg.Client()) + client.connect(done) + + this.pgCursor = function (text, values) { + return client.query(new Cursor(text, values || [])) + } + }) + + afterEach(function () { + this.client.end() + }) + + it('resolve with result', async function () { + const cursor = this.pgCursor(text) + const res = await cursor.read(6) + assert.strictEqual(res.length, 6) + }) + + it('reject with error', function (done) { + const cursor = this.pgCursor('select asdfasdf') + cursor.read(1).error((err) => { + assert(err) + done() + }) + }) + + it('read multiple times', async function () { + const cursor = this.pgCursor(text) + let res + + res = await cursor.read(2) + assert.strictEqual(res.length, 2) + + res = await cursor.read(3) + assert.strictEqual(res.length, 3) + + res = await cursor.read(1) + assert.strictEqual(res.length, 1) + + res = await cursor.read(1) + assert.strictEqual(res.length, 0) + }) +}) From 684cd09bcecbf5ad5f451fdf608a3e9a9444524e Mon Sep 17 00:00:00 2001 From: Brian Crowell Date: Tue, 27 Jul 2021 11:29:07 -0500 Subject: [PATCH 0778/1037] Allow Node to exit if the pool is idle (#2568) Based on the suggestion from #2078. This adds ref/unref methods to the Connection and Client classes and then uses them to allow the process to exit if all of the connections in the pool are idle. This behavior is controlled by the allowExitOnIdle flag to the Pool constructor; it defaults to the old behavior. --- packages/pg-pool/index.js | 11 ++++++++ packages/pg-pool/test/idle-timeout-exit.js | 16 +++++++++++ packages/pg-pool/test/idle-timeout.js | 31 ++++++++++++++++++++++ packages/pg/lib/client.js | 8 ++++++ packages/pg/lib/connection.js | 8 ++++++ 5 files changed, 74 insertions(+) create mode 100644 packages/pg-pool/test/idle-timeout-exit.js diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 403d05a19..5557de5c0 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -83,6 +83,7 @@ class Pool extends EventEmitter { this.options.max = this.options.max || this.options.poolSize || 10 this.options.maxUses = this.options.maxUses || Infinity + this.options.allowExitOnIdle = this.options.allowExitOnIdle || false this.log = this.options.log || function () {} this.Client = this.options.Client || Client || require('pg').Client this.Promise = this.options.Promise || global.Promise @@ -136,6 +137,7 @@ class Pool extends EventEmitter { const idleItem = this._idle.pop() clearTimeout(idleItem.timeoutId) const client = idleItem.client + client.ref() const idleListener = idleItem.idleListener return this._acquireClient(client, pendingItem, idleListener, false) @@ -323,6 +325,15 @@ class Pool extends EventEmitter { this.log('remove idle client') this._remove(client) }, this.options.idleTimeoutMillis) + + if (this.options.allowExitOnIdle) { + // allow Node to exit if this is all that's left + tid.unref() + } + } + + if (this.options.allowExitOnIdle) { + client.unref() } this._idle.push(new IdleItem(client, idleListener, tid)) diff --git a/packages/pg-pool/test/idle-timeout-exit.js b/packages/pg-pool/test/idle-timeout-exit.js new file mode 100644 index 000000000..1292634a8 --- /dev/null +++ b/packages/pg-pool/test/idle-timeout-exit.js @@ -0,0 +1,16 @@ +// This test is meant to be spawned from idle-timeout.js +if (module === require.main) { + const allowExitOnIdle = process.env.ALLOW_EXIT_ON_IDLE === '1' + const Pool = require('../index') + + const pool = new Pool({ idleTimeoutMillis: 200, ...(allowExitOnIdle ? { allowExitOnIdle: true } : {}) }) + pool.query('SELECT NOW()', (err, res) => console.log('completed first')) + pool.on('remove', () => { + console.log('removed') + done() + }) + + setTimeout(() => { + pool.query('SELECT * from generate_series(0, 1000)', (err, res) => console.log('completed second')) + }, 50) +} diff --git a/packages/pg-pool/test/idle-timeout.js b/packages/pg-pool/test/idle-timeout.js index fd9fba4a4..0bb097565 100644 --- a/packages/pg-pool/test/idle-timeout.js +++ b/packages/pg-pool/test/idle-timeout.js @@ -4,6 +4,8 @@ const expect = require('expect.js') const describe = require('mocha').describe const it = require('mocha').it +const { fork } = require('child_process') +const path = require('path') const Pool = require('../') @@ -84,4 +86,33 @@ describe('idle timeout', () => { return pool.end() }) ) + + it('unrefs the connections and timeouts so the program can exit when idle when the allowExitOnIdle option is set', function (done) { + const child = fork(path.join(__dirname, 'idle-timeout-exit.js'), [], { + silent: true, + env: { ...process.env, ALLOW_EXIT_ON_IDLE: '1' }, + }) + let result = '' + child.stdout.setEncoding('utf8') + child.stdout.on('data', (chunk) => (result += chunk)) + child.on('error', (err) => done(err)) + child.on('close', () => { + expect(result).to.equal('completed first\ncompleted second\n') + done() + }) + }) + + it('keeps old behavior when allowExitOnIdle option is not set', function (done) { + const child = fork(path.join(__dirname, 'idle-timeout-exit.js'), [], { + silent: true, + }) + let result = '' + child.stdout.setEncoding('utf8') + child.stdout.on('data', (chunk) => (result += chunk)) + child.on('error', (err) => done(err)) + child.on('close', () => { + expect(result).to.equal('completed first\ncompleted second\nremoved\n') + done() + }) + }) }) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 1e1e83374..589aa9f84 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -577,6 +577,14 @@ class Client extends EventEmitter { return result } + ref() { + this.connection.ref() + } + + unref() { + this.connection.unref() + } + end(cb) { this._ending = true diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 7d45de2b7..ebb2f099d 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -177,6 +177,14 @@ class Connection extends EventEmitter { this._send(syncBuffer) } + ref() { + this.stream.ref() + } + + unref() { + this.stream.unref() + } + end() { // 0x58 = 'X' this._ending = true From f824d74afe99b21de2681cd665e4cee74e769960 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 27 Jul 2021 11:35:55 -0500 Subject: [PATCH 0779/1037] Update changelog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26e368ff9..5347e3557 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,15 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### pg@8.7.0 + +- Add optional config to [pool](https://github.com/brianc/node-postgres/pull/2568) to allow process to exit if pool is idle. + +### pg-cursor@2.7.0 + +- Convert to [es6 class](https://github.com/brianc/node-postgres/pull/2553) +- Add support for promises [to cursor methods](https://github.com/brianc/node-postgres/pull/2554) + ### pg@8.6.0 - Better [SASL](https://github.com/brianc/node-postgres/pull/2436) error messages & more validation on bad configuration. From d8ce457e83146a960fee9328789142327b0c8f70 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Jul 2021 11:36:35 -0500 Subject: [PATCH 0780/1037] Bump handlebars from 4.7.6 to 4.7.7 (#2538) Bumps [handlebars](https://github.com/wycats/handlebars.js) from 4.7.6 to 4.7.7. - [Release notes](https://github.com/wycats/handlebars.js/releases) - [Changelog](https://github.com/handlebars-lang/handlebars.js/blob/master/release-notes.md) - [Commits](https://github.com/wycats/handlebars.js/compare/v4.7.6...v4.7.7) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yarn.lock b/yarn.lock index e579f984e..3372de6a5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3066,9 +3066,9 @@ growl@1.10.5: integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== handlebars@^4.0.1, handlebars@^4.7.6: - version "4.7.6" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.6.tgz#d4c05c1baf90e9945f77aa68a7a219aa4a7df74e" - integrity sha512-1f2BACcBfiwAfStCKZNrUCgqNZkGsAT7UM3kkYtXuLo0KnaVfjKOyf7PRzB6++aK9STyT1Pd2ZCPe3EGOXleXA== + version "4.7.7" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" + integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== dependencies: minimist "^1.2.5" neo-async "^2.6.0" @@ -6125,9 +6125,9 @@ typescript@^4.0.3: integrity sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg== uglify-js@^3.1.4: - version "3.11.1" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.11.1.tgz#32d274fea8aac333293044afd7f81409d5040d38" - integrity sha512-OApPSuJcxcnewwjSGGfWOjx3oix5XpmrK9Z2j0fTRlHGoZ49IU6kExfZTM0++fCArOOCet+vIfWwFHbvWqwp6g== + version "3.13.5" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.5.tgz#5d71d6dbba64cf441f32929b1efce7365bb4f113" + integrity sha512-xtB8yEqIkn7zmOyS2zUNBsYCBRhDkvlNxMMY2smuJ/qA8NCHeQvKCF3i9Z4k8FJH4+PJvZRtMrPynfZ75+CSZw== uid-number@0.0.6: version "0.0.6" From 83aae778e8dcb3fb35a84de6667e21e0c8276a99 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Jul 2021 11:37:10 -0500 Subject: [PATCH 0781/1037] Bump ssri from 6.0.1 to 6.0.2 (#2531) Bumps [ssri](https://github.com/npm/ssri) from 6.0.1 to 6.0.2. - [Release notes](https://github.com/npm/ssri/releases) - [Changelog](https://github.com/npm/ssri/blob/v6.0.2/CHANGELOG.md) - [Commits](https://github.com/npm/ssri/compare/v6.0.1...v6.0.2) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 3372de6a5..ad4eed181 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5647,9 +5647,9 @@ sshpk@^1.7.0: tweetnacl "~0.14.0" ssri@^6.0.0, ssri@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" - integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== + version "6.0.2" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" + integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q== dependencies: figgy-pudding "^3.5.1" From 0da7882f45d0c63d4bb310c7d137434ef4b22d18 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 27 Jul 2021 11:42:04 -0500 Subject: [PATCH 0782/1037] Bump y18n from 4.0.0 to 4.0.1 (#2506) Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.1. - [Release notes](https://github.com/yargs/y18n/releases) - [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md) - [Commits](https://github.com/yargs/y18n/commits) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index ad4eed181..e779f038c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6388,9 +6388,9 @@ xtend@^4.0.0, xtend@~4.0.1: integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== y18n@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" - integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + version "4.0.1" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" + integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: version "3.1.1" From 779803fbce195ae5610761606dcdcd78ca4cd439 Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 27 Jul 2021 12:23:30 -0500 Subject: [PATCH 0783/1037] Add ref/unref noop to native client (#2581) * Add ref/unref noop to native client * Use promise.catch in test * Make partition test not flake on old node * Fix test flake on old node --- packages/pg-cursor/test/promises.js | 2 +- packages/pg/lib/native/client.js | 3 +++ .../integration/client/connection-timeout-tests.js | 11 ++++++----- .../integration/client/network-partition-tests.js | 3 ++- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/pg-cursor/test/promises.js b/packages/pg-cursor/test/promises.js index 7b36dab8f..1635a1a8b 100644 --- a/packages/pg-cursor/test/promises.js +++ b/packages/pg-cursor/test/promises.js @@ -26,7 +26,7 @@ describe('cursor using promises', function () { it('reject with error', function (done) { const cursor = this.pgCursor('select asdfasdf') - cursor.read(1).error((err) => { + cursor.read(1).catch((err) => { assert(err) done() }) diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index 6cf800d0e..d1faeb3d8 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -285,6 +285,9 @@ Client.prototype.cancel = function (query) { } } +Client.prototype.ref = function () {} +Client.prototype.unref = function () {} + Client.prototype.setTypeParser = function (oid, format, parseFn) { return this._types.setTypeParser(oid, format, parseFn) } diff --git a/packages/pg/test/integration/client/connection-timeout-tests.js b/packages/pg/test/integration/client/connection-timeout-tests.js index 843fa95bb..6b99698bc 100644 --- a/packages/pg/test/integration/client/connection-timeout-tests.js +++ b/packages/pg/test/integration/client/connection-timeout-tests.js @@ -13,7 +13,7 @@ const options = { database: 'existing', } -const serverWithConnectionTimeout = (timeout, callback) => { +const serverWithConnectionTimeout = (port, timeout, callback) => { const sockets = new Set() const server = net.createServer((socket) => { @@ -47,11 +47,11 @@ const serverWithConnectionTimeout = (timeout, callback) => { } } - server.listen(options.port, options.host, () => callback(closeServer)) + server.listen(port, options.host, () => callback(closeServer)) } suite.test('successful connection', (done) => { - serverWithConnectionTimeout(0, (closeServer) => { + serverWithConnectionTimeout(options.port, 0, (closeServer) => { const timeoutId = setTimeout(() => { throw new Error('Client should have connected successfully but it did not.') }, 3000) @@ -67,12 +67,13 @@ suite.test('successful connection', (done) => { }) suite.test('expired connection timeout', (done) => { - serverWithConnectionTimeout(options.connectionTimeoutMillis * 2, (closeServer) => { + const opts = { ...options, port: 54322 } + serverWithConnectionTimeout(opts.port, opts.connectionTimeoutMillis * 2, (closeServer) => { const timeoutId = setTimeout(() => { throw new Error('Client should have emitted an error but it did not.') }, 3000) - const client = new helper.Client(options) + const client = new helper.Client(opts) client .connect() .then(() => client.end()) diff --git a/packages/pg/test/integration/client/network-partition-tests.js b/packages/pg/test/integration/client/network-partition-tests.js index 993396401..2ac100dff 100644 --- a/packages/pg/test/integration/client/network-partition-tests.js +++ b/packages/pg/test/integration/client/network-partition-tests.js @@ -11,6 +11,7 @@ var Server = function (response) { this.response = response } +let port = 54321 Server.prototype.start = function (cb) { // this is our fake postgres server // it responds with our specified response immediatley after receiving every buffer @@ -39,7 +40,7 @@ Server.prototype.start = function (cb) { }.bind(this) ) - var port = 54321 + port = port + 1 var options = { host: 'localhost', From f3b0ee4c09cd01e37baf580d72dffc43edcc29f3 Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 27 Jul 2021 12:41:17 -0500 Subject: [PATCH 0784/1037] Publish - pg-cursor@2.7.0 - pg-pool@3.4.0 - pg-query-stream@4.2.0 - pg@8.7.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 5607ea955..be43e15f6 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.6.0", + "version": "2.7.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.6.0" + "pg": "^8.7.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index b92e7df90..e23191828 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.3.0", + "version": "3.4.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index d01b18d86..63697b387 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "4.1.0", + "version": "4.2.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,13 +37,13 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.6.0", + "pg": "^8.7.0", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" }, "dependencies": { - "pg-cursor": "^2.6.0" + "pg-cursor": "^2.7.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index af71629f3..10c941466 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.6.0", + "version": "8.7.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "^2.5.0", - "pg-pool": "^3.3.0", + "pg-pool": "^3.4.0", "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" From 86d31a6fad6ee05facd85bc5f83ca081ebe725b7 Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 27 Jul 2021 17:27:05 -0500 Subject: [PATCH 0785/1037] Only call client.ref if it exists * Only call client.ref if it exists. Fixes #2582 * Make test requiring port less flakey * Bump port range Fixes #2582 Fixes #2584 --- packages/pg-pool/index.js | 2 +- packages/pg/test/integration/client/connection-timeout-tests.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 5557de5c0..48bf5c788 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -137,7 +137,7 @@ class Pool extends EventEmitter { const idleItem = this._idle.pop() clearTimeout(idleItem.timeoutId) const client = idleItem.client - client.ref() + client.ref && client.ref() const idleListener = idleItem.idleListener return this._acquireClient(client, pendingItem, idleListener, false) diff --git a/packages/pg/test/integration/client/connection-timeout-tests.js b/packages/pg/test/integration/client/connection-timeout-tests.js index 6b99698bc..7a3ee4447 100644 --- a/packages/pg/test/integration/client/connection-timeout-tests.js +++ b/packages/pg/test/integration/client/connection-timeout-tests.js @@ -7,7 +7,7 @@ const suite = new helper.Suite() const options = { host: 'localhost', - port: 54321, + port: Math.floor(Math.random() * 2000) + 2000, connectionTimeoutMillis: 2000, user: 'not', database: 'existing', From 92b4d37926c276d343bfe56447ff6f526af757cf Mon Sep 17 00:00:00 2001 From: "Brian M. Carlson" Date: Tue, 27 Jul 2021 17:33:19 -0500 Subject: [PATCH 0786/1037] Publish - pg-cursor@2.7.1 - pg-pool@3.4.1 - pg-query-stream@4.2.1 - pg@8.7.1 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index be43e15f6..b85000aba 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.7.0", + "version": "2.7.1", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.7.0" + "pg": "^8.7.1" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index e23191828..d479ae55f 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.4.0", + "version": "3.4.1", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 63697b387..5f332e8cd 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "4.2.0", + "version": "4.2.1", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,13 +37,13 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.7.0", + "pg": "^8.7.1", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" }, "dependencies": { - "pg-cursor": "^2.7.0" + "pg-cursor": "^2.7.1" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 10c941466..930a7d928 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.7.0", + "version": "8.7.1", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "^2.5.0", - "pg-pool": "^3.4.0", + "pg-pool": "^3.4.1", "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" From 98cd59e3e7bd14f77d5f31dbc4115a9de9d26db1 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 29 Jul 2021 17:17:15 -0500 Subject: [PATCH 0787/1037] Return promise on cursor end (#2589) * Return promise on cursor end * Remove redudant if --- packages/pg-cursor/index.js | 15 +++++---------- packages/pg-cursor/test/close.js | 11 +++++++++++ 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index b77fd5977..ddfb2b4ca 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -208,20 +208,15 @@ class Cursor extends EventEmitter { } if (!this.connection || this.state === 'done') { - if (cb) { - return setImmediate(cb) - } else { - return - } + setImmediate(cb) + return promise } this._closePortal() this.state = 'done' - if (cb) { - this.connection.once('readyForQuery', function () { - cb() - }) - } + this.connection.once('readyForQuery', function () { + cb() + }) // Return the promise (or undefined) return promise diff --git a/packages/pg-cursor/test/close.js b/packages/pg-cursor/test/close.js index e63512abd..b34161a17 100644 --- a/packages/pg-cursor/test/close.js +++ b/packages/pg-cursor/test/close.js @@ -23,6 +23,17 @@ describe('close', function () { }) }) + it('can close a finished cursor a promise', function (done) { + const cursor = new Cursor(text) + this.client.query(cursor) + cursor.read(100, (err) => { + assert.ifError(err) + cursor.close().then(() => { + this.client.query('SELECT NOW()', done) + }) + }) + }) + it('closes cursor early', function (done) { const cursor = new Cursor(text) this.client.query(cursor) From 947ccee346f0d598e135548e1e4936a9a008fc6f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Aug 2021 00:59:44 +0000 Subject: [PATCH 0788/1037] Bump tar from 4.4.13 to 4.4.15 (#2592) Bumps [tar](https://github.com/npm/node-tar) from 4.4.13 to 4.4.15. - [Release notes](https://github.com/npm/node-tar/releases) - [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-tar/compare/v4.4.13...v4.4.15) --- updated-dependencies: - dependency-name: tar dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index e779f038c..bc5330a1d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5868,9 +5868,9 @@ table@^5.2.3: string-width "^3.0.0" tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== + version "4.4.15" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.15.tgz#3caced4f39ebd46ddda4d6203d48493a919697f8" + integrity sha512-ItbufpujXkry7bHH9NpQyTXPbJ72iTlXgkBAYsAjDXk3Ds8t/3NfO5P4xZGy7u+sYuQUbimgzswX4uQIEeNVOA== dependencies: chownr "^1.1.1" fs-minipass "^1.2.5" From 3aba3794cf7d8749c19081314a875af61efee61e Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 17 Nov 2021 10:02:22 -0600 Subject: [PATCH 0789/1037] Use github actions for CI (#2654) This is the initial port to github actions. Still pending are the SSL and client SSL cert tests which are currently being skipped. But perfect is the enemy of the good here, and having no CI because travis-ci keeps not working is unacceptable. --- .github/workflows/ci.yml | 31 ++ .../pg-query-stream/test/async-iterator.ts | 15 +- .../connection-parameters/creation-tests.js | 407 +++++++++--------- 3 files changed, 251 insertions(+), 202 deletions(-) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 000000000..13c6c77eb --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,31 @@ +name: CI + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + services: + postgres: + image: postgres:11 + env: + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + POSTGRES_DB: ci_db_test + ports: + - 5432:5432 + options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 + strategy: + matrix: + node: ['8', '10', '12', '14', '16', '17'] + name: Node ${{ matrix.node }} + steps: + - uses: actions/checkout@v2 + - name: Setup node + uses: actions/setup-node@v2 + with: + node-version: ${{ matrix.node }} + cache: yarn + - run: yarn install + # TODO(bmc): get ssl tests working in ci + - run: PGTESTNOSSL=true PGUSER=postgres PGPASSWORD=postgres PGDATABASE=ci_db_test yarn test diff --git a/packages/pg-query-stream/test/async-iterator.ts b/packages/pg-query-stream/test/async-iterator.ts index 06539d124..d47ede164 100644 --- a/packages/pg-query-stream/test/async-iterator.ts +++ b/packages/pg-query-stream/test/async-iterator.ts @@ -88,11 +88,16 @@ if (!process.version.startsWith('v8')) { rows.push(row) break } - for await (const row of stream) { - rows.push(row) - } - for await (const row of stream) { - rows.push(row) + + try { + for await (const row of stream) { + rows.push(row) + } + for await (const row of stream) { + rows.push(row) + } + } catch (e) { + // swallow error - node 17 throws if stream is aborted } assert.strictEqual(rows.length, 1) client.release() diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index 633b0eaf4..40381e788 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -1,15 +1,18 @@ 'use strict' -var helper = require('../test-helper') -var assert = require('assert') -var ConnectionParameters = require('../../../lib/connection-parameters') -var defaults = require('../../../lib').defaults +const helper = require('../test-helper') +const assert = require('assert') +const ConnectionParameters = require('../../../lib/connection-parameters') +const defaults = require('../../../lib').defaults +const dns = require('dns') // clear process.env for (var key in process.env) { delete process.env[key] } -test('ConnectionParameters construction', function () { +const suite = new helper.Suite() + +suite.test('ConnectionParameters construction', function () { assert.ok(new ConnectionParameters(), 'with null config') assert.ok(new ConnectionParameters({ user: 'asdf' }), 'with config object') assert.ok(new ConnectionParameters('postgres://localhost/postgres'), 'with connection string') @@ -33,13 +36,13 @@ var compare = function (actual, expected, type) { ) } -test('ConnectionParameters initializing from defaults', function () { +suite.test('ConnectionParameters initializing from defaults', function () { var subject = new ConnectionParameters() compare(subject, defaults, 'defaults') assert.ok(subject.isDomainSocket === false) }) -test('ConnectionParameters initializing from defaults with connectionString set', function () { +suite.test('ConnectionParameters initializing from defaults with connectionString set', function () { var config = { user: 'brians-are-the-best', database: 'scoobysnacks', @@ -62,7 +65,7 @@ test('ConnectionParameters initializing from defaults with connectionString set' compare(subject, config, 'defaults-connectionString') }) -test('ConnectionParameters initializing from config', function () { +suite.test('ConnectionParameters initializing from config', function () { var config = { user: 'brian', database: 'home', @@ -83,7 +86,7 @@ test('ConnectionParameters initializing from config', function () { assert.ok(subject.isDomainSocket === false) }) -test('ConnectionParameters initializing from config and config.connectionString', function () { +suite.test('ConnectionParameters initializing from config and config.connectionString', function () { var subject1 = new ConnectionParameters({ connectionString: 'postgres://test@host/db', }) @@ -105,31 +108,31 @@ test('ConnectionParameters initializing from config and config.connectionString' assert.equal(subject4.ssl, true) }) -test('escape spaces if present', function () { +suite.test('escape spaces if present', function () { var subject = new ConnectionParameters('postgres://localhost/post gres') assert.equal(subject.database, 'post gres') }) -test('do not double escape spaces', function () { +suite.test('do not double escape spaces', function () { var subject = new ConnectionParameters('postgres://localhost/post%20gres') assert.equal(subject.database, 'post gres') }) -test('initializing with unix domain socket', function () { +suite.test('initializing with unix domain socket', function () { var subject = new ConnectionParameters('/var/run/') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/var/run/') assert.equal(subject.database, defaults.user) }) -test('initializing with unix domain socket and a specific database, the simple way', function () { +suite.test('initializing with unix domain socket and a specific database, the simple way', function () { var subject = new ConnectionParameters('/var/run/ mydb') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/var/run/') assert.equal(subject.database, 'mydb') }) -test('initializing with unix domain socket, the health way', function () { +suite.test('initializing with unix domain socket, the health way', function () { var subject = new ConnectionParameters('socket:/some path/?db=my[db]&encoding=utf8') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/some path/') @@ -137,7 +140,7 @@ test('initializing with unix domain socket, the health way', function () { assert.equal(subject.client_encoding, 'utf8') }) -test('initializing with unix domain socket, the escaped health way', function () { +suite.test('initializing with unix domain socket, the escaped health way', function () { var subject = new ConnectionParameters('socket:/some%20path/?db=my%2Bdb&encoding=utf8') assert.ok(subject.isDomainSocket) assert.equal(subject.host, '/some path/') @@ -145,201 +148,211 @@ test('initializing with unix domain socket, the escaped health way', function () assert.equal(subject.client_encoding, 'utf8') }) -test('libpq connection string building', function () { - var checkForPart = function (array, part) { - assert.ok(array.indexOf(part) > -1, array.join(' ') + ' did not contain ' + part) - } +var checkForPart = function (array, part) { + assert.ok(array.indexOf(part) > -1, array.join(' ') + ' did not contain ' + part) +} - test('builds simple string', function () { - var config = { - user: 'brian', - password: 'xyz', - port: 888, - host: 'localhost', - database: 'bam', - } - var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString( - assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "user='brian'") - checkForPart(parts, "password='xyz'") - checkForPart(parts, "port='888'") - checkForPart(parts, "hostaddr='127.0.0.1'") - checkForPart(parts, "dbname='bam'") - }) - ) +const getDNSHost = async function (host) { + return new Promise((resolve, reject) => { + dns.lookup(host, (err, addresses) => { + err ? reject(err) : resolve(addresses) + }) }) +} - test('builds dns string', function () { - var config = { - user: 'brian', - password: 'asdf', - port: 5432, - host: 'localhost', - } - var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString( - assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "user='brian'") - checkForPart(parts, "hostaddr='127.0.0.1'") - }) - ) +suite.testAsync('builds simple string', async function () { + var config = { + user: 'brian', + password: 'xyz', + port: 888, + host: 'localhost', + database: 'bam', + } + var subject = new ConnectionParameters(config) + const dnsHost = await getDNSHost(config.host) + return new Promise((resolve) => { + subject.getLibpqConnectionString(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, "password='xyz'") + checkForPart(parts, "port='888'") + checkForPart(parts, `hostaddr='${dnsHost}'`) + checkForPart(parts, "dbname='bam'") + resolve() + }) }) +}) - test('error when dns fails', function () { - var config = { - user: 'brian', - password: 'asf', - port: 5432, - host: 'asdlfkjasldfkksfd#!$!!!!..com', - } - var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString( - assert.calls(function (err, constring) { - assert.ok(err) - assert.isNull(constring) - }) - ) +suite.test('builds dns string', async function () { + var config = { + user: 'brian', + password: 'asdf', + port: 5432, + host: 'localhost', + } + var subject = new ConnectionParameters(config) + const dnsHost = await getDNSHost(config.host) + return new Promise((resolve) => { + subject.getLibpqConnectionString(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, `hostaddr='${dnsHost}'`) + resolve() + }) }) +}) - test('connecting to unix domain socket', function () { - var config = { - user: 'brian', - password: 'asf', - port: 5432, - host: '/tmp/', - } - var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString( - assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "user='brian'") - checkForPart(parts, "host='/tmp/'") - }) - ) - }) +suite.test('error when dns fails', function () { + var config = { + user: 'brian', + password: 'asf', + port: 5432, + host: 'asdlfkjasldfkksfd#!$!!!!..com', + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert.ok(err) + assert.isNull(constring) + }) + ) +}) - test('config contains quotes and backslashes', function () { - var config = { - user: 'not\\brian', - password: "bad'chars", - port: 5432, - host: '/tmp/', - } - var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString( - assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "user='not\\\\brian'") - checkForPart(parts, "password='bad\\'chars'") - }) - ) - }) +suite.test('connecting to unix domain socket', function () { + var config = { + user: 'brian', + password: 'asf', + port: 5432, + host: '/tmp/', + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='brian'") + checkForPart(parts, "host='/tmp/'") + }) + ) +}) - test('encoding can be specified by config', function () { - var config = { - client_encoding: 'utf-8', - } - var subject = new ConnectionParameters(config) - subject.getLibpqConnectionString( - assert.calls(function (err, constring) { - assert(!err) - var parts = constring.split(' ') - checkForPart(parts, "client_encoding='utf-8'") - }) - ) - }) +suite.test('config contains quotes and backslashes', function () { + var config = { + user: 'not\\brian', + password: "bad'chars", + port: 5432, + host: '/tmp/', + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "user='not\\\\brian'") + checkForPart(parts, "password='bad\\'chars'") + }) + ) +}) - test('password contains < and/or > characters', function () { - var sourceConfig = { - user: 'brian', - password: 'helloe', - port: 5432, - host: 'localhost', - database: 'postgres', - } - var connectionString = - 'postgres://' + - sourceConfig.user + - ':' + - sourceConfig.password + - '@' + - sourceConfig.host + - ':' + - sourceConfig.port + - '/' + - sourceConfig.database - var subject = new ConnectionParameters(connectionString) - assert.equal(subject.password, sourceConfig.password) - }) +suite.test('encoding can be specified by config', function () { + var config = { + client_encoding: 'utf-8', + } + var subject = new ConnectionParameters(config) + subject.getLibpqConnectionString( + assert.calls(function (err, constring) { + assert(!err) + var parts = constring.split(' ') + checkForPart(parts, "client_encoding='utf-8'") + }) + ) +}) - test('username or password contains weird characters', function () { - var defaults = require('../../../lib/defaults') - defaults.ssl = true - var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000' - var subject = new ConnectionParameters(strang) - assert.equal(subject.user, 'my f%irst name') - assert.equal(subject.password, 'is&%awesome!') - assert.equal(subject.host, 'localhost') - assert.equal(subject.ssl, true) - }) +suite.test('password contains < and/or > characters', function () { + var sourceConfig = { + user: 'brian', + password: 'helloe', + port: 5432, + host: 'localhost', + database: 'postgres', + } + var connectionString = + 'postgres://' + + sourceConfig.user + + ':' + + sourceConfig.password + + '@' + + sourceConfig.host + + ':' + + sourceConfig.port + + '/' + + sourceConfig.database + var subject = new ConnectionParameters(connectionString) + assert.equal(subject.password, sourceConfig.password) +}) - test('url is properly encoded', function () { - var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl' - var subject = new ConnectionParameters(encoded) - assert.equal(subject.user, 'bi%na%%ry ') - assert.equal(subject.password, 's@f#') - assert.equal(subject.host, 'localhost') - assert.equal(subject.database, ' u%20rl') - }) +suite.test('username or password contains weird characters', function () { + var defaults = require('../../../lib/defaults') + defaults.ssl = true + var strang = 'pg://my f%irst name:is&%awesome!@localhost:9000' + var subject = new ConnectionParameters(strang) + assert.equal(subject.user, 'my f%irst name') + assert.equal(subject.password, 'is&%awesome!') + assert.equal(subject.host, 'localhost') + assert.equal(subject.ssl, true) +}) - test('ssl is set on client', function () { - var Client = require('../../../lib/client') - var defaults = require('../../../lib/defaults') - defaults.ssl = true - var c = new Client('postgres://user@password:host/database') - assert(c.ssl, 'Client should have ssl enabled via defaults') - }) +suite.test('url is properly encoded', function () { + var encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl' + var subject = new ConnectionParameters(encoded) + assert.equal(subject.user, 'bi%na%%ry ') + assert.equal(subject.password, 's@f#') + assert.equal(subject.host, 'localhost') + assert.equal(subject.database, ' u%20rl') +}) - test('coercing string "true" to boolean', function () { - const subject = new ConnectionParameters({ ssl: 'true' }) - assert.strictEqual(subject.ssl, true) - }) +suite.test('ssl is set on client', function () { + var Client = require('../../../lib/client') + var defaults = require('../../../lib/defaults') + defaults.ssl = true + var c = new Client('postgres://user@password:host/database') + assert(c.ssl, 'Client should have ssl enabled via defaults') +}) - test('ssl is set on client', function () { - var sourceConfig = { - user: 'brian', - password: 'helloe', - port: 5432, - host: 'localhost', - database: 'postgres', - ssl: { - sslmode: 'verify-ca', - sslca: '/path/ca.pem', - sslkey: '/path/cert.key', - sslcert: '/path/cert.crt', - sslrootcert: '/path/root.crt', - }, - } - var Client = require('../../../lib/client') - var defaults = require('../../../lib/defaults') - defaults.ssl = true - var c = new ConnectionParameters(sourceConfig) - c.getLibpqConnectionString( - assert.calls(function (err, pgCString) { - assert(!err) - assert.equal( - pgCString.indexOf("sslrootcert='/path/root.crt'") !== -1, - true, - 'libpqConnectionString should contain sslrootcert' - ) - }) - ) - }) +suite.test('coercing string "true" to boolean', function () { + const subject = new ConnectionParameters({ ssl: 'true' }) + assert.strictEqual(subject.ssl, true) +}) + +suite.test('ssl is set on client', function () { + var sourceConfig = { + user: 'brian', + password: 'helloe', + port: 5432, + host: 'localhost', + database: 'postgres', + ssl: { + sslmode: 'verify-ca', + sslca: '/path/ca.pem', + sslkey: '/path/cert.key', + sslcert: '/path/cert.crt', + sslrootcert: '/path/root.crt', + }, + } + var Client = require('../../../lib/client') + var defaults = require('../../../lib/defaults') + defaults.ssl = true + var c = new ConnectionParameters(sourceConfig) + c.getLibpqConnectionString( + assert.calls(function (err, pgCString) { + assert(!err) + assert.equal( + pgCString.indexOf("sslrootcert='/path/root.crt'") !== -1, + true, + 'libpqConnectionString should contain sslrootcert' + ) + }) + ) }) From b0bd1c32f1f415adab3a3b25379a9cb3236ebd84 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 17 Nov 2021 11:02:04 -0600 Subject: [PATCH 0790/1037] Bump tar from 4.4.15 to 4.4.19 (#2604) Bumps [tar](https://github.com/npm/node-tar) from 4.4.15 to 4.4.19. - [Release notes](https://github.com/npm/node-tar/releases) - [Changelog](https://github.com/npm/node-tar/blob/main/CHANGELOG.md) - [Commits](https://github.com/npm/node-tar/compare/v4.4.15...v4.4.19) --- updated-dependencies: - dependency-name: tar dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/yarn.lock b/yarn.lock index bc5330a1d..d2c7f6f23 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1682,7 +1682,7 @@ chokidar@3.3.0: optionalDependencies: fsevents "~2.1.1" -chownr@^1.1.1, chownr@^1.1.2: +chownr@^1.1.1, chownr@^1.1.2, chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== @@ -2807,7 +2807,7 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-minipass@^1.2.5: +fs-minipass@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== @@ -4124,7 +4124,7 @@ minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== -minipass@^2.3.5, minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: +minipass@^2.3.5, minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== @@ -4132,7 +4132,7 @@ minipass@^2.3.5, minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: safe-buffer "^5.1.2" yallist "^3.0.0" -minizlib@^1.2.1: +minizlib@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== @@ -4175,7 +4175,7 @@ mkdirp@*: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -mkdirp@0.5.5, mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@0.5.5, mkdirp@0.5.x, mkdirp@^0.5.1, mkdirp@^0.5.5: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== @@ -5368,7 +5368,7 @@ rxjs@^6.4.0: dependencies: tslib "^1.9.0" -safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -5868,17 +5868,17 @@ table@^5.2.3: string-width "^3.0.0" tar@^4.4.10, tar@^4.4.12, tar@^4.4.8: - version "4.4.15" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.15.tgz#3caced4f39ebd46ddda4d6203d48493a919697f8" - integrity sha512-ItbufpujXkry7bHH9NpQyTXPbJ72iTlXgkBAYsAjDXk3Ds8t/3NfO5P4xZGy7u+sYuQUbimgzswX4uQIEeNVOA== + version "4.4.19" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3" + integrity sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA== dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" + chownr "^1.1.4" + fs-minipass "^1.2.7" + minipass "^2.9.0" + minizlib "^1.3.3" + mkdirp "^0.5.5" + safe-buffer "^5.2.1" + yallist "^3.1.1" temp-dir@^1.0.0: version "1.0.0" @@ -6392,7 +6392,7 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.1.tgz#8db2b83c31c5d75099bb890b23f3094891e247d4" integrity sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ== -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== From 97eea2d7a4453645e44129378215f88dff371a08 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Nov 2021 09:38:43 -0600 Subject: [PATCH 0791/1037] Bump path-parse from 1.0.6 to 1.0.7 (#2595) Bumps [path-parse](https://github.com/jbgutierrez/path-parse) from 1.0.6 to 1.0.7. - [Release notes](https://github.com/jbgutierrez/path-parse/releases) - [Commits](https://github.com/jbgutierrez/path-parse/commits/v1.0.7) --- updated-dependencies: - dependency-name: path-parse dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index d2c7f6f23..1ec815582 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4793,9 +4793,9 @@ path-key@^3.1.0: integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== path-type@^1.0.0: version "1.1.0" From 2c3adf25f94358defb84f14ca50f6873a3340618 Mon Sep 17 00:00:00 2001 From: Steffen Weidenhaus Date: Fri, 17 Dec 2021 17:15:26 +1100 Subject: [PATCH 0792/1037] Update README.md (#2671) Change `name` to `now` for time column --- packages/pg-pool/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg-pool/README.md b/packages/pg-pool/README.md index c6d7e9287..b5f20bae9 100644 --- a/packages/pg-pool/README.md +++ b/packages/pg-pool/README.md @@ -136,7 +136,7 @@ because its so common to just run a query and return the client to the pool afte 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) +console.log(name.rows[0].name, 'says hello at', time.rows[0].now) ``` you can also use a callback here if you'd like: From 392a7f4a66d111cc4e9fd14253f09215441eed98 Mon Sep 17 00:00:00 2001 From: darkgl0w <31093081+darkgl0w@users.noreply.github.com> Date: Fri, 17 Dec 2021 07:21:35 +0100 Subject: [PATCH 0793/1037] chore (ci): add macOS and Windows to the CI OS matrix (#2657) * chore (ci): add macOS and Windows to the CI OS matrix * chore (ci): fix macOS runner name --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13c6c77eb..aa0a956b2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,8 @@ jobs: strategy: matrix: node: ['8', '10', '12', '14', '16', '17'] - name: Node ${{ matrix.node }} + os: [ubuntu-latest, windows-latest, macos-latest] + name: Node.js ${{ matrix.node }} (${{ matrix.os }}) steps: - uses: actions/checkout@v2 - name: Setup node From 1f7b8cb6fa000af11bda84c1961c7252b34b8ee9 Mon Sep 17 00:00:00 2001 From: Andrew Lam <32132177+awhlam@users.noreply.github.com> Date: Sun, 16 Jan 2022 12:40:34 -0800 Subject: [PATCH 0794/1037] Fix markdown for n8n.io sponsor link (#2685) --- SPONSORS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SPONSORS.md b/SPONSORS.md index 9d7d314dd..453d11465 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -11,7 +11,7 @@ node-postgres is made possible by the helpful contributors from the community as - [Dataform](https://dataform.co/) - [Eaze](https://www.eaze.com/) - [simpleanalytics](https://simpleanalytics.com/) -- [n8n.io]https://n8n.io/ +- [n8n.io](https://n8n.io/) # Supporters From a09412c603215f7d8e07344b45105d7eac230b4d Mon Sep 17 00:00:00 2001 From: darkgl0w <31093081+darkgl0w@users.noreply.github.com> Date: Thu, 27 Jan 2022 00:20:11 +0100 Subject: [PATCH 0795/1037] chore (ci): trigger a CI run on PR events (#2681) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aa0a956b2..98ea909f5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,6 @@ name: CI -on: [push] +on: [push, pull_request] jobs: build: From f3ff3e2d1f60a007e46a3ee5b711aaaa232100c5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jan 2022 17:34:10 -0600 Subject: [PATCH 0796/1037] Bump node-fetch from 2.6.1 to 2.6.7 (#2694) Bumps [node-fetch](https://github.com/node-fetch/node-fetch) from 2.6.1 to 2.6.7. - [Release notes](https://github.com/node-fetch/node-fetch/releases) - [Commits](https://github.com/node-fetch/node-fetch/compare/v2.6.1...v2.6.7) --- updated-dependencies: - dependency-name: node-fetch dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1ec815582..4c5a25507 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4323,9 +4323,11 @@ node-fetch-npm@^2.0.2: safe-buffer "^5.1.1" node-fetch@^2.5.0, node-fetch@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" node-gyp@^5.0.2: version "5.1.1" @@ -6006,6 +6008,11 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= + traverser@0.0.x: version "0.0.5" resolved "https://registry.yarnpkg.com/traverser/-/traverser-0.0.5.tgz#c66f38c456a0c21a88014b1223580c7ebe0631eb" @@ -6263,11 +6270,24 @@ wcwidth@^1.0.0: dependencies: defaults "^1.0.3" +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= + webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + whatwg-url@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" From 998f57324411ad6f53a8e205cbc1df6fcfc742cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 26 Jan 2022 17:34:36 -0600 Subject: [PATCH 0797/1037] Bump trim-off-newlines from 1.0.1 to 1.0.3 (#2695) Bumps [trim-off-newlines](https://github.com/stevemao/trim-off-newlines) from 1.0.1 to 1.0.3. - [Release notes](https://github.com/stevemao/trim-off-newlines/releases) - [Commits](https://github.com/stevemao/trim-off-newlines/compare/v1.0.1...v1.0.3) --- updated-dependencies: - dependency-name: trim-off-newlines dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 4c5a25507..1cb44de2f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6043,9 +6043,9 @@ trim-newlines@^3.0.0: integrity sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA== trim-off-newlines@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3" - integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM= + version "1.0.3" + resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.3.tgz#8df24847fcb821b0ab27d58ab6efec9f2fe961a1" + integrity sha512-kh6Tu6GbeSNMGfrrZh6Bb/4ZEHV1QlB4xNDBeog8Y9/QwFlKTRyWvY3Fs9tRDAMZliVUwieMgEdIeL/FtqjkJg== ts-node@^8.5.4: version "8.10.2" From 5508c0ee6bc751ea2474202d12fb36b4f21089a3 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Fri, 28 Jan 2022 19:59:45 +0100 Subject: [PATCH 0798/1037] fix: Prevent closing the portal twice (#2609) Fixes brianc/node-postgres#2119 --- packages/pg-cursor/index.js | 5 ++++- packages/pg-query-stream/test/async-iterator.ts | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index ddfb2b4ca..9bbda641a 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -86,6 +86,8 @@ class Cursor extends EventEmitter { } _closePortal() { + if (this.state === 'done') return + // because we opened a named portal to stream results // we need to close the same named portal. Leaving a named portal // open can lock tables for modification if inside a transaction. @@ -97,6 +99,8 @@ class Cursor extends EventEmitter { if (this.state !== 'error') { this.connection.sync() } + + this.state = 'done' } handleRowDescription(msg) { @@ -213,7 +217,6 @@ class Cursor extends EventEmitter { } this._closePortal() - this.state = 'done' this.connection.once('readyForQuery', function () { cb() }) diff --git a/packages/pg-query-stream/test/async-iterator.ts b/packages/pg-query-stream/test/async-iterator.ts index d47ede164..e2f8a7552 100644 --- a/packages/pg-query-stream/test/async-iterator.ts +++ b/packages/pg-query-stream/test/async-iterator.ts @@ -117,5 +117,17 @@ if (!process.version.startsWith('v8')) { client.release() await pool.end() }) + + it('supports breaking with low watermark', async function () { + const pool = new pg.Pool({ max: 1 }) + const client = await pool.connect() + + for await (const _ of client.query(new QueryStream('select TRUE', [], { highWaterMark: 1 }))) break + for await (const _ of client.query(new QueryStream('select TRUE', [], { highWaterMark: 1 }))) break + for await (const _ of client.query(new QueryStream('select TRUE', [], { highWaterMark: 1 }))) break + + client.release() + await pool.end() + }) }) } From 8392918d7bdac88830c3d60922b6f7bb17331aae Mon Sep 17 00:00:00 2001 From: ChrisWritable <50638920+ChrisWritable@users.noreply.github.com> Date: Fri, 28 Jan 2022 15:17:48 -0800 Subject: [PATCH 0799/1037] Add connection lifetime limit option and tests (#2698) Co-authored-by: ChrisG0x20 --- packages/pg-pool/index.js | 27 +++++++++++++ packages/pg-pool/test/lifetime-timeout.js | 46 +++++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 packages/pg-pool/test/lifetime-timeout.js diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 48bf5c788..46d2aab0c 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -84,6 +84,7 @@ class Pool extends EventEmitter { this.options.max = this.options.max || this.options.poolSize || 10 this.options.maxUses = this.options.maxUses || Infinity this.options.allowExitOnIdle = this.options.allowExitOnIdle || false + this.options.maxLifetimeSeconds = this.options.maxLifetimeSeconds || 0 this.log = this.options.log || function () {} this.Client = this.options.Client || Client || require('pg').Client this.Promise = this.options.Promise || global.Promise @@ -94,6 +95,7 @@ class Pool extends EventEmitter { this._clients = [] this._idle = [] + this._expired = new WeakSet() this._pendingQueue = [] this._endCallback = undefined this.ending = false @@ -123,6 +125,7 @@ class Pool extends EventEmitter { } return } + // if we don't have any waiting, do nothing if (!this._pendingQueue.length) { this.log('no queued requests') @@ -248,6 +251,17 @@ class Pool extends EventEmitter { } else { this.log('new client connected') + if (this.options.maxLifetimeSeconds !== 0) { + setTimeout(() => { + this.log('ending client due to expired lifetime') + this._expired.add(client) + const idleIndex = this._idle.findIndex(idleItem => idleItem.client === client) + if (idleIndex !== -1) { + this._acquireClient(client, new PendingItem((err, client, clientRelease) => clientRelease()), idleListener, false) + } + }, this.options.maxLifetimeSeconds * 1000) + } + return this._acquireClient(client, pendingItem, idleListener, true) } }) @@ -318,6 +332,15 @@ class Pool extends EventEmitter { return } + const isExpired = this._expired.has(client) + if (isExpired) { + this.log('remove expired client') + this._expired.delete(client) + this._remove(client) + this._pulseQueue() + return + } + // idle timeout let tid if (this.options.idleTimeoutMillis) { @@ -414,6 +437,10 @@ class Pool extends EventEmitter { return this._idle.length } + get expiredCount() { + return this._clients.reduce((acc, client) => acc + (this._expired.has(client) ? 1 : 0), 0) + } + get totalCount() { return this._clients.length } diff --git a/packages/pg-pool/test/lifetime-timeout.js b/packages/pg-pool/test/lifetime-timeout.js new file mode 100644 index 000000000..986161625 --- /dev/null +++ b/packages/pg-pool/test/lifetime-timeout.js @@ -0,0 +1,46 @@ +'use strict' +const co = require('co') +const expect = require('expect.js') + +const describe = require('mocha').describe +const it = require('mocha').it +const path = require('path') + +const Pool = require('../') + +describe('lifetime timeout', () => { + it('connection lifetime should expire and remove the client', (done) => { + const pool = new Pool({ maxLifetimeSeconds: 1 }) + pool.query('SELECT NOW()') + pool.on('remove', () => { + console.log('expired while idle - on-remove event') + expect(pool.expiredCount).to.equal(0) + expect(pool.totalCount).to.equal(0) + done() + }) + }) + it('connection lifetime should expire and remove the client after the client is done working', (done) => { + const pool = new Pool({ maxLifetimeSeconds: 1 }) + pool.query('SELECT pg_sleep(1.01)') + pool.on('remove', () => { + console.log('expired while busy - on-remove event') + expect(pool.expiredCount).to.equal(0) + expect(pool.totalCount).to.equal(0) + done() + }) + }) + it('can remove expired clients and recreate them', + co.wrap(function* () { + const pool = new Pool({ maxLifetimeSeconds: 1 }) + let query = pool.query('SELECT pg_sleep(1)') + expect(pool.expiredCount).to.equal(0) + expect(pool.totalCount).to.equal(1) + yield query + expect(pool.expiredCount).to.equal(0) + expect(pool.totalCount).to.equal(0) + yield pool.query('SELECT NOW()') + expect(pool.expiredCount).to.equal(0) + expect(pool.totalCount).to.equal(1) + }) + ) +}) From e4115854cb65d212f4ea2f9cb835b6a6bd953c38 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 4 Feb 2022 10:20:51 -0600 Subject: [PATCH 0800/1037] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5347e3557..4bc9e0594 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +### pg@8.8.0 + +- Add connection [lifetime limit](https://github.com/brianc/node-postgres/pull/2698) config option. + ### pg@8.7.0 - Add optional config to [pool](https://github.com/brianc/node-postgres/pull/2568) to allow process to exit if pool is idle. From 6849cc686855d0399c847f5e3d31cb0c56ae59e0 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 4 Feb 2022 10:21:57 -0600 Subject: [PATCH 0801/1037] Publish - pg-cursor@2.7.2 - pg-pool@3.5.0 - pg-query-stream@4.2.2 - pg@8.7.2 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index b85000aba..feb3513fd 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.7.1", + "version": "2.7.2", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.7.1" + "pg": "^8.7.2" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index d479ae55f..0beba3da2 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.4.1", + "version": "3.5.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 5f332e8cd..f2df775a1 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "4.2.1", + "version": "4.2.2", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,13 +37,13 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.7.1", + "pg": "^8.7.2", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" }, "dependencies": { - "pg-cursor": "^2.7.1" + "pg-cursor": "^2.7.2" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 930a7d928..3c92052b1 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.7.1", + "version": "8.7.2", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "^2.5.0", - "pg-pool": "^3.4.1", + "pg-pool": "^3.5.0", "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" From edf1a864d63d00e83866d80de38ab1a44d004d38 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 4 Feb 2022 10:22:23 -0600 Subject: [PATCH 0802/1037] Fix changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bc9e0594..72599c724 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. -### pg@8.8.0 +### pg-pool@3.5.0 - Add connection [lifetime limit](https://github.com/brianc/node-postgres/pull/2698) config option. From 9a61e9ac587829d7dc486f2da8500708c5d1a8b0 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 4 Feb 2022 10:27:51 -0600 Subject: [PATCH 0803/1037] Format with prettier --- packages/pg-pool/index.js | 9 +++++++-- packages/pg-pool/test/lifetime-timeout.js | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 46d2aab0c..0d7314eb6 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -255,9 +255,14 @@ class Pool extends EventEmitter { setTimeout(() => { this.log('ending client due to expired lifetime') this._expired.add(client) - const idleIndex = this._idle.findIndex(idleItem => idleItem.client === client) + const idleIndex = this._idle.findIndex((idleItem) => idleItem.client === client) if (idleIndex !== -1) { - this._acquireClient(client, new PendingItem((err, client, clientRelease) => clientRelease()), idleListener, false) + this._acquireClient( + client, + new PendingItem((err, client, clientRelease) => clientRelease()), + idleListener, + false + ) } }, this.options.maxLifetimeSeconds * 1000) } diff --git a/packages/pg-pool/test/lifetime-timeout.js b/packages/pg-pool/test/lifetime-timeout.js index 986161625..fddd5ff00 100644 --- a/packages/pg-pool/test/lifetime-timeout.js +++ b/packages/pg-pool/test/lifetime-timeout.js @@ -29,7 +29,8 @@ describe('lifetime timeout', () => { done() }) }) - it('can remove expired clients and recreate them', + it( + 'can remove expired clients and recreate them', co.wrap(function* () { const pool = new Pool({ maxLifetimeSeconds: 1 }) let query = pool.query('SELECT pg_sleep(1)') From 4fa7ee891a456168a75695ac026792136f16577f Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 4 Feb 2022 10:28:01 -0600 Subject: [PATCH 0804/1037] Publish - pg-cursor@2.7.3 - pg-pool@3.5.1 - pg-query-stream@4.2.3 - pg@8.7.3 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index feb3513fd..6104c9557 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.7.2", + "version": "2.7.3", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.7.2" + "pg": "^8.7.3" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 0beba3da2..d89c12c5e 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.5.0", + "version": "3.5.1", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index f2df775a1..7e913e128 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "4.2.2", + "version": "4.2.3", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,13 +37,13 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.7.2", + "pg": "^8.7.3", "stream-spec": "~0.3.5", "stream-tester": "0.0.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" }, "dependencies": { - "pg-cursor": "^2.7.2" + "pg-cursor": "^2.7.3" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 3c92052b1..acc5e5f9a 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.7.2", + "version": "8.7.3", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "^2.5.0", - "pg-pool": "^3.5.0", + "pg-pool": "^3.5.1", "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" From 21ccd4f1b6e66774bbf24aecfccdbfe7c9b49238 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 15 Feb 2022 14:52:06 -0600 Subject: [PATCH 0805/1037] Bump pathval from 1.1.0 to 1.1.1 (#2702) Bumps [pathval](https://github.com/chaijs/pathval) from 1.1.0 to 1.1.1. - [Release notes](https://github.com/chaijs/pathval/releases) - [Changelog](https://github.com/chaijs/pathval/blob/master/CHANGELOG.md) - [Commits](https://github.com/chaijs/pathval/compare/v1.1.0...v1.1.1) --- updated-dependencies: - dependency-name: pathval dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1cb44de2f..3150a8804 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4821,9 +4821,9 @@ path-type@^4.0.0: integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== pathval@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" - integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== performance-now@^2.1.0: version "2.1.0" From f5e87ac0b17c8e8d7e66cbcdcc2eac8f9852577d Mon Sep 17 00:00:00 2001 From: Lars Hvam Date: Fri, 1 Apr 2022 18:31:45 +0200 Subject: [PATCH 0806/1037] pg: update README, remove dead badge (#2719) --- packages/pg/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/pg/README.md b/packages/pg/README.md index e5fcf02c4..b3158b570 100644 --- a/packages/pg/README.md +++ b/packages/pg/README.md @@ -1,7 +1,6 @@ # node-postgres [![Build Status](https://secure.travis-ci.org/brianc/node-postgres.svg?branch=master)](http://travis-ci.org/brianc/node-postgres) -[![Dependency Status](https://david-dm.org/brianc/node-postgres.svg?path=packages/pg)](https://david-dm.org/brianc/node-postgres?path=packages/pg) NPM version NPM downloads From 4b4d97b8f3e141d6bd0f17cfe528db6ba802bb4b Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 10 May 2022 14:49:22 -0500 Subject: [PATCH 0807/1037] Remove stream-tester (#2743) * Remove stream-tester * Use random port for network-partition tests * Use random port for connection timeout test * Bump CI version --- .github/workflows/ci.yml | 6 +- packages/pg-query-stream/package.json | 1 - packages/pg-query-stream/test/pauses.ts | 15 ++++- .../client/connection-timeout-tests.js | 2 +- .../client/network-partition-tests.js | 16 +++-- yarn.lock | 58 ------------------- 6 files changed, 24 insertions(+), 74 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 98ea909f5..14e24db12 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,13 +17,13 @@ jobs: options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 strategy: matrix: - node: ['8', '10', '12', '14', '16', '17'] + node: ['8', '10', '12', '14', '16', '18'] os: [ubuntu-latest, windows-latest, macos-latest] name: Node.js ${{ matrix.node }} (${{ matrix.os }}) steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Setup node - uses: actions/setup-node@v2 + uses: actions/setup-node@v3 with: node-version: ${{ matrix.node }} cache: yarn diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 7e913e128..227cdc4fe 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -39,7 +39,6 @@ "mocha": "^7.1.2", "pg": "^8.7.3", "stream-spec": "~0.3.5", - "stream-tester": "0.0.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" }, diff --git a/packages/pg-query-stream/test/pauses.ts b/packages/pg-query-stream/test/pauses.ts index daf8347af..75fee57f6 100644 --- a/packages/pg-query-stream/test/pauses.ts +++ b/packages/pg-query-stream/test/pauses.ts @@ -1,8 +1,19 @@ import helper from './helper' import concat from 'concat-stream' -import tester from 'stream-tester' import JSONStream from 'JSONStream' import QueryStream from '../src' +import { Transform, TransformCallback } from 'stream' + +class PauseStream extends Transform { + constructor() { + super({ objectMode: true }) + } + + _transform(chunk, encoding, callback): void { + this.push(chunk, encoding) + setTimeout(callback, 1) + } +} helper('pauses', function (client) { it('pauses', function (done) { @@ -12,7 +23,7 @@ helper('pauses', function (client) { highWaterMark: 2, }) const query = client.query(stream) - const pauser = tester.createPauseStream(0.1, 100) + const pauser = new PauseStream() query .pipe(JSONStream.stringify()) .pipe(pauser) diff --git a/packages/pg/test/integration/client/connection-timeout-tests.js b/packages/pg/test/integration/client/connection-timeout-tests.js index 7a3ee4447..316e0768b 100644 --- a/packages/pg/test/integration/client/connection-timeout-tests.js +++ b/packages/pg/test/integration/client/connection-timeout-tests.js @@ -67,7 +67,7 @@ suite.test('successful connection', (done) => { }) suite.test('expired connection timeout', (done) => { - const opts = { ...options, port: 54322 } + const opts = { ...options, port: options.port + 1 } serverWithConnectionTimeout(opts.port, opts.connectionTimeoutMillis * 2, (closeServer) => { const timeoutId = setTimeout(() => { throw new Error('Client should have emitted an error but it did not.') diff --git a/packages/pg/test/integration/client/network-partition-tests.js b/packages/pg/test/integration/client/network-partition-tests.js index 2ac100dff..8397821a8 100644 --- a/packages/pg/test/integration/client/network-partition-tests.js +++ b/packages/pg/test/integration/client/network-partition-tests.js @@ -11,7 +11,6 @@ var Server = function (response) { this.response = response } -let port = 54321 Server.prototype.start = function (cb) { // this is our fake postgres server // it responds with our specified response immediatley after receiving every buffer @@ -40,14 +39,13 @@ Server.prototype.start = function (cb) { }.bind(this) ) - port = port + 1 - - var options = { - host: 'localhost', - port: port, - } - this.server.listen(options.port, options.host, function () { - cb(options) + const host = 'localhost' + this.server.listen({ host, port: 0 }, () => { + const port = this.server.address().port + cb({ + host, + port, + }) }) } diff --git a/yarn.lock b/yarn.lock index 3150a8804..6bcd1465f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1334,15 +1334,6 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== -assertions@~2.3.0: - version "2.3.4" - resolved "https://registry.yarnpkg.com/assertions/-/assertions-2.3.4.tgz#a9433ced1fce57cc999af0965d1008e96c2796e6" - integrity sha1-qUM87R/OV8yZmvCWXRAI6WwnluY= - dependencies: - fomatto "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6" - render "0.1" - traverser "1" - assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -2010,11 +2001,6 @@ currently-unhandled@^0.4.1: dependencies: array-find-index "^1.0.1" -curry@0.0.x: - version "0.0.4" - resolved "https://registry.yarnpkg.com/curry/-/curry-0.0.4.tgz#1750d518d919c44f3d37ff44edc693de1f0d5fcb" - integrity sha1-F1DVGNkZxE89N/9E7caT3h8NX8s= - cyclist@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" @@ -2755,10 +2741,6 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" -"fomatto@git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6": - version "0.6.0" - resolved "git://github.com/BonsaiDen/Fomatto.git#468666f600b46f9067e3da7200fd9df428923ea6" - for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -2793,11 +2775,6 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" -from@~0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/from/-/from-0.0.2.tgz#7fffac647a2f99b20d57b8e28379455cbb4189d0" - integrity sha1-f/+sZHovmbINV7jig3lFXLtBidA= - fs-extra@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" @@ -5215,13 +5192,6 @@ regexpp@^3.0.0, regexpp@^3.1.0: resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== -render@0.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/render/-/render-0.1.4.tgz#cfb33a34e26068591d418469e23d8cc5ce1ceff5" - integrity sha1-z7M6NOJgaFkdQYRp4j2Mxc4c7/U= - dependencies: - traverser "0.0.x" - repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" @@ -5683,15 +5653,6 @@ stream-spec@~0.3.5: dependencies: macgyver "~1.10" -stream-tester@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/stream-tester/-/stream-tester-0.0.5.tgz#4f86f2531149adaf6dd4b3ff262edf64ae9a171a" - integrity sha1-T4byUxFJra9t1LP/Ji7fZK6aFxo= - dependencies: - assertions "~2.3.0" - from "~0.0.2" - through "~0.0.3" - string-width@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" @@ -5944,11 +5905,6 @@ through@2, "through@>=2.2.7 <3", through@^2.3.4, through@^2.3.6: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= -through@~0.0.3: - version "0.0.4" - resolved "https://registry.yarnpkg.com/through/-/through-0.0.4.tgz#0bf2f0fffafaac4bacbc533667e98aad00b588c8" - integrity sha1-C/Lw//r6rEusvFM2Z+mKrQC1iMg= - tmp@^0.0.33: version "0.0.33" resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" @@ -6013,20 +5969,6 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= -traverser@0.0.x: - version "0.0.5" - resolved "https://registry.yarnpkg.com/traverser/-/traverser-0.0.5.tgz#c66f38c456a0c21a88014b1223580c7ebe0631eb" - integrity sha1-xm84xFagwhqIAUsSI1gMfr4GMes= - dependencies: - curry "0.0.x" - -traverser@1: - version "1.0.0" - resolved "https://registry.yarnpkg.com/traverser/-/traverser-1.0.0.tgz#6f59e5813759aeeab3646b8f4513fd4a62e4fe20" - integrity sha1-b1nlgTdZruqzZGuPRRP9SmLk/iA= - dependencies: - curry "0.0.x" - trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" From b812ec1e65a103d79c603b47d53019fa9f77b7b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 May 2022 23:41:05 -0500 Subject: [PATCH 0808/1037] Bump async from 0.9.0 to 2.6.4 (#2736) Bumps [async](https://github.com/caolan/async) from 0.9.0 to 2.6.4. - [Release notes](https://github.com/caolan/async/releases) - [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md) - [Commits](https://github.com/caolan/async/compare/0.9.0...v2.6.4) --- updated-dependencies: - dependency-name: async dependency-type: direct:development ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/pg/package.json | 2 +- yarn.lock | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/packages/pg/package.json b/packages/pg/package.json index acc5e5f9a..e1eec9fa9 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -29,7 +29,7 @@ "pgpass": "1.x" }, "devDependencies": { - "async": "0.9.0", + "async": "2.6.4", "bluebird": "3.5.2", "co": "4.6.0", "pg-copy-streams": "0.3.0" diff --git a/yarn.lock b/yarn.lock index 6bcd1465f..1dcce5844 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1344,16 +1344,18 @@ astral-regex@^1.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== -async@0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/async/-/async-0.9.0.tgz#ac3613b1da9bed1b47510bb4651b8931e47146c7" - integrity sha1-rDYTsdqb7RtHUQu0ZRuJMeRxRsc= - async@1.x: version "1.5.2" resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" integrity sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo= +async@2.6.4: + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== + dependencies: + lodash "^4.17.14" + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" From ec06473c164c4ed5e38fedf61026be36dd67b9b9 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 May 2022 23:41:19 -0500 Subject: [PATCH 0809/1037] Bump minimist from 1.2.5 to 1.2.6 (#2727) Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6. - [Release notes](https://github.com/substack/minimist/releases) - [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6) --- updated-dependencies: - dependency-name: minimist dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 1dcce5844..66527b4aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4099,9 +4099,9 @@ minimist-options@^3.0.1: is-plain-obj "^1.1.0" minimist@^1.1.3, minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== + version "1.2.6" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" + integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== minipass@^2.3.5, minipass@^2.6.0, minipass@^2.9.0: version "2.9.0" From c7743646cd734bef4989e2a29a9ae3201b3744f5 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Thu, 12 May 2022 19:04:21 -0500 Subject: [PATCH 0810/1037] Update sponsors --- SPONSORS.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/SPONSORS.md b/SPONSORS.md index 453d11465..71c5210bc 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -12,6 +12,7 @@ node-postgres is made possible by the helpful contributors from the community as - [Eaze](https://www.eaze.com/) - [simpleanalytics](https://simpleanalytics.com/) - [n8n.io](https://n8n.io/) +- [mpirik](https://github.com/mpirik) # Supporters @@ -39,4 +40,8 @@ node-postgres is made possible by the helpful contributors from the community as - @Guido4000 - [Martti Laine](https://github.com/codeclown) - [Tim Nolet](https://github.com/tnolet) +- [Ideal Postcodes](https://github.com/ideal-postcodes) - [checkly](https://github.com/checkly) +- [Scout APM](https://github.com/scoutapm-sponsorships) +- [Sideline Sports](https://github.com/SidelineSports) +- [Gadget](https://github.com/gadget-inc) From 3ca56027d3079b6bcee81d65e3e590328a74ea3c Mon Sep 17 00:00:00 2001 From: ChrisWritable <50638920+ChrisWritable@users.noreply.github.com> Date: Thu, 12 May 2022 17:05:02 -0700 Subject: [PATCH 0811/1037] Immediately unref() maxLifetimeSeconds Timeout object to prevent blocking allowExitOnIdle (#2721) --- packages/pg-pool/index.js | 5 ++++- packages/pg-pool/test/idle-timeout-exit.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 0d7314eb6..5e846bb31 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -252,7 +252,7 @@ class Pool extends EventEmitter { this.log('new client connected') if (this.options.maxLifetimeSeconds !== 0) { - setTimeout(() => { + const maxLifetimeTimeout = setTimeout(() => { this.log('ending client due to expired lifetime') this._expired.add(client) const idleIndex = this._idle.findIndex((idleItem) => idleItem.client === client) @@ -265,6 +265,9 @@ class Pool extends EventEmitter { ) } }, this.options.maxLifetimeSeconds * 1000) + + maxLifetimeTimeout.unref() + client.once('end', () => clearTimeout(maxLifetimeTimeout)) } return this._acquireClient(client, pendingItem, idleListener, true) diff --git a/packages/pg-pool/test/idle-timeout-exit.js b/packages/pg-pool/test/idle-timeout-exit.js index 1292634a8..b557af7f6 100644 --- a/packages/pg-pool/test/idle-timeout-exit.js +++ b/packages/pg-pool/test/idle-timeout-exit.js @@ -3,7 +3,7 @@ if (module === require.main) { const allowExitOnIdle = process.env.ALLOW_EXIT_ON_IDLE === '1' const Pool = require('../index') - const pool = new Pool({ idleTimeoutMillis: 200, ...(allowExitOnIdle ? { allowExitOnIdle: true } : {}) }) + const pool = new Pool({ maxLifetimeSeconds: 2, idleTimeoutMillis: 200, ...(allowExitOnIdle ? { allowExitOnIdle: true } : {}) }) pool.query('SELECT NOW()', (err, res) => console.log('completed first')) pool.on('remove', () => { console.log('removed') From 28ac2a17bce287cfa458153dcabe3ca06ca0e28f Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 12 May 2022 22:00:00 -0500 Subject: [PATCH 0812/1037] Add test for how to set search path (#2700) Also refactor a few tests a bit to slowly clean up some of the old style. --- .../integration/client/type-coercion-tests.js | 1 - .../connection-pool-size-tests.js | 41 ++++++++++++++++--- .../connection-pool/test-helper.js | 29 +------------ .../test/integration/gh-issues/2416-tests.js | 14 +++++++ packages/pg/test/test-helper.js | 28 ------------- 5 files changed, 51 insertions(+), 62 deletions(-) create mode 100644 packages/pg/test/integration/gh-issues/2416-tests.js diff --git a/packages/pg/test/integration/client/type-coercion-tests.js b/packages/pg/test/integration/client/type-coercion-tests.js index 33249a9b2..3bc6273c4 100644 --- a/packages/pg/test/integration/client/type-coercion-tests.js +++ b/packages/pg/test/integration/client/type-coercion-tests.js @@ -1,7 +1,6 @@ 'use strict' var helper = require('./test-helper') var pg = helper.pg -var sink const suite = new helper.Suite() var testForTypeCoercion = function (type) { diff --git a/packages/pg/test/integration/connection-pool/connection-pool-size-tests.js b/packages/pg/test/integration/connection-pool/connection-pool-size-tests.js index da281a191..1d87584e6 100644 --- a/packages/pg/test/integration/connection-pool/connection-pool-size-tests.js +++ b/packages/pg/test/integration/connection-pool/connection-pool-size-tests.js @@ -1,10 +1,41 @@ 'use strict' -var helper = require('./test-helper') +const helper = require('../test-helper') +const assert = require('assert') -helper.testPoolSize(1) +const suite = new helper.Suite() -helper.testPoolSize(2) +const testPoolSize = function (max) { + suite.testAsync(`test ${max} queries executed on a pool rapidly`, () => { + const pool = new helper.pg.Pool({ max: 10 }) -helper.testPoolSize(40) + let count = 0 -helper.testPoolSize(200) + return new Promise((resolve) => { + for (var i = 0; i < max; i++) { + pool.connect(function (err, client, release) { + assert(!err) + client.query('SELECT * FROM NOW()') + client.query('select generate_series(0, 25)', function (err, result) { + assert.strictEqual(result.rows.length, 26) + }) + client.query('SELECT * FROM NOW()', (err) => { + assert(!err) + release() + if (++count === max) { + resolve() + pool.end() + } + }) + }) + } + }) + }) +} + +testPoolSize(1) + +testPoolSize(2) + +testPoolSize(40) + +testPoolSize(200) diff --git a/packages/pg/test/integration/connection-pool/test-helper.js b/packages/pg/test/integration/connection-pool/test-helper.js index 97a177a62..14f8134eb 100644 --- a/packages/pg/test/integration/connection-pool/test-helper.js +++ b/packages/pg/test/integration/connection-pool/test-helper.js @@ -1,31 +1,4 @@ 'use strict' var helper = require('./../test-helper') -const suite = new helper.Suite() - -helper.testPoolSize = function (max) { - suite.test(`test ${max} queries executed on a pool rapidly`, (cb) => { - const pool = new helper.pg.Pool({ max: 10 }) - - var sink = new helper.Sink(max, function () { - pool.end(cb) - }) - - for (var i = 0; i < max; i++) { - pool.connect(function (err, client, done) { - assert(!err) - client.query('SELECT * FROM NOW()') - client.query('select generate_series(0, 25)', function (err, result) { - assert.equal(result.rows.length, 26) - }) - var query = client.query('SELECT * FROM NOW()', (err) => { - assert(!err) - sink.add() - done() - }) - }) - } - }) -} - -module.exports = Object.assign({}, helper, { suite: suite }) +module.exports = helper diff --git a/packages/pg/test/integration/gh-issues/2416-tests.js b/packages/pg/test/integration/gh-issues/2416-tests.js new file mode 100644 index 000000000..669eb7789 --- /dev/null +++ b/packages/pg/test/integration/gh-issues/2416-tests.js @@ -0,0 +1,14 @@ +const helper = require('../test-helper') + +const suite = new helper.Suite() + +suite.testAsync('it sets search_path on connection', async () => { + const client = new helper.pg.Client({ + options: '--search_path=foo', + }) + await client.connect() + const { rows } = await client.query('SHOW search_path') + assert.strictEqual(rows.length, 1) + assert.strictEqual(rows[0].search_path, 'foo') + await client.end() +}) diff --git a/packages/pg/test/test-helper.js b/packages/pg/test/test-helper.js index 5999ea98f..15abcd465 100644 --- a/packages/pg/test/test-helper.js +++ b/packages/pg/test/test-helper.js @@ -183,33 +183,6 @@ process.on('uncaughtException', function (err) { process.exit(255) }) -var Sink = function (expected, timeout, callback) { - var defaultTimeout = 5000 - if (typeof timeout === 'function') { - callback = timeout - timeout = defaultTimeout - } - timeout = timeout || defaultTimeout - var internalCount = 0 - var kill = function () { - assert.ok(false, 'Did not reach expected ' + expected + ' with an idle timeout of ' + timeout) - } - var killTimeout = setTimeout(kill, timeout) - return { - add: function (count) { - count = count || 1 - internalCount += count - clearTimeout(killTimeout) - if (internalCount < expected) { - killTimeout = setTimeout(kill, timeout) - } else { - assert.equal(internalCount, expected) - callback() - } - }, - } -} - var getTimezoneOffset = Date.prototype.getTimezoneOffset var setTimezoneOffset = function (minutesOffset) { @@ -231,7 +204,6 @@ const rejection = (promise) => ) module.exports = { - Sink: Sink, Suite: Suite, pg: require('./../lib/'), args: args, From 68160a29bd8dfe97c74ab9a74000977da7783d6f Mon Sep 17 00:00:00 2001 From: Peter Rust Date: Mon, 20 Jun 2022 06:25:12 -0700 Subject: [PATCH 0813/1037] Fix #2556 by keeping callback errors from interfering with cleanup (#2753) * Fix #2556 (handleRowDescription of null) by keeping callback errors from interfering with cleanup * Added regression test for #2556 --- packages/pg/lib/query.js | 9 ++++- .../test/integration/gh-issues/2556-tests.js | 40 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 packages/pg/test/integration/gh-issues/2556-tests.js diff --git a/packages/pg/lib/query.js b/packages/pg/lib/query.js index c0dfedd1e..6655a0e69 100644 --- a/packages/pg/lib/query.js +++ b/packages/pg/lib/query.js @@ -135,7 +135,14 @@ class Query extends EventEmitter { return this.handleError(this._canceledDueToError, con) } if (this.callback) { - this.callback(null, this._results) + try { + this.callback(null, this._results) + } + catch(err) { + process.nextTick(() => { + throw err + }) + } } this.emit('end', this._results) } diff --git a/packages/pg/test/integration/gh-issues/2556-tests.js b/packages/pg/test/integration/gh-issues/2556-tests.js new file mode 100644 index 000000000..13fdf80eb --- /dev/null +++ b/packages/pg/test/integration/gh-issues/2556-tests.js @@ -0,0 +1,40 @@ +'use strict' +var helper = require('./../test-helper') +var assert = require('assert') + +var callbackError = new Error('TEST: Throw in callback') + +const suite = new helper.Suite() + +suite.test('it should cleanup client even if an error is thrown in a callback', (done) => { + // temporarily replace the test framework's uncaughtException handlers + // with a custom one that ignores the callbackError + let original_handlers = process.listeners('uncaughtException') + process.removeAllListeners('uncaughtException') + process.on('uncaughtException', (err) => { + if (err != callbackError) { + original_handlers[0](err) + } + }) + + // throw an error in a callback and verify that a subsequent query works without error + var client = helper.client() + client.query('SELECT NOW()', (err) => { + assert(!err) + setTimeout(reuseClient, 50) + throw callbackError + }) + + function reuseClient() { + client.query('SELECT NOW()', (err) => { + assert(!err) + + // restore the test framework's uncaughtException handlers + for (let handler of original_handlers) { + process.on('uncaughtException', handler) + } + + client.end(done) + }) + } +}) From 3e53d06cd891797469ebdd2f8a669183ba6224f6 Mon Sep 17 00:00:00 2001 From: Martin Kubliniak Date: Wed, 10 Aug 2022 23:15:06 +0200 Subject: [PATCH 0814/1037] Support lock_timeout (#2779) --- packages/pg/lib/client.js | 3 +++ packages/pg/lib/connection-parameters.js | 1 + packages/pg/lib/defaults.js | 4 ++++ packages/pg/test/unit/connection-parameters/creation-tests.js | 3 +++ 4 files changed, 11 insertions(+) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 589aa9f84..18238f6fb 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -403,6 +403,9 @@ class Client extends EventEmitter { if (params.statement_timeout) { data.statement_timeout = String(parseInt(params.statement_timeout, 10)) } + if (params.lock_timeout) { + data.lock_timeout = String(parseInt(params.lock_timeout, 10)) + } if (params.idle_in_transaction_session_timeout) { data.idle_in_transaction_session_timeout = String(parseInt(params.idle_in_transaction_session_timeout, 10)) } diff --git a/packages/pg/lib/connection-parameters.js b/packages/pg/lib/connection-parameters.js index 165e6d5d3..6a535a820 100644 --- a/packages/pg/lib/connection-parameters.js +++ b/packages/pg/lib/connection-parameters.js @@ -103,6 +103,7 @@ class ConnectionParameters { this.application_name = val('application_name', config, 'PGAPPNAME') this.fallback_application_name = val('fallback_application_name', config, false) this.statement_timeout = val('statement_timeout', config, false) + this.lock_timeout = val('lock_timeout', config, false) this.idle_in_transaction_session_timeout = val('idle_in_transaction_session_timeout', config, false) this.query_timeout = val('query_timeout', config, false) diff --git a/packages/pg/lib/defaults.js b/packages/pg/lib/defaults.js index 9384e01cb..5c5d997d2 100644 --- a/packages/pg/lib/defaults.js +++ b/packages/pg/lib/defaults.js @@ -54,6 +54,10 @@ module.exports = { // false=unlimited statement_timeout: false, + // Abort any statement that waits longer than the specified duration in milliseconds while attempting to acquire a lock. + // false=unlimited + lock_timeout: false, + // Terminate any session with an open transaction that has been idle for longer than the specified duration in milliseconds // false=unlimited idle_in_transaction_session_timeout: false, diff --git a/packages/pg/test/unit/connection-parameters/creation-tests.js b/packages/pg/test/unit/connection-parameters/creation-tests.js index 40381e788..cd27d5011 100644 --- a/packages/pg/test/unit/connection-parameters/creation-tests.js +++ b/packages/pg/test/unit/connection-parameters/creation-tests.js @@ -28,6 +28,7 @@ var compare = function (actual, expected, type) { assert.equal(actual.password, expected.password, type + ' password') assert.equal(actual.binary, expected.binary, type + ' binary') assert.equal(actual.statement_timeout, expected.statement_timeout, type + ' statement_timeout') + assert.equal(actual.lock_timeout, expected.lock_timeout, type + ' lock_timeout') assert.equal(actual.options, expected.options, type + ' options') assert.equal( actual.idle_in_transaction_session_timeout, @@ -51,6 +52,7 @@ suite.test('ConnectionParameters initializing from defaults with connectionStrin host: 'foo.bar.net', binary: defaults.binary, statement_timeout: false, + lock_timeout: false, idle_in_transaction_session_timeout: false, options: '-c geqo=off', } @@ -78,6 +80,7 @@ suite.test('ConnectionParameters initializing from config', function () { asdf: 'blah', }, statement_timeout: 15000, + lock_timeout: 15000, idle_in_transaction_session_timeout: 15000, options: '-c geqo=off', } From 8032fbad43e801b332191b2e0862e177947392af Mon Sep 17 00:00:00 2001 From: Alex Zlotnik Date: Mon, 22 Aug 2022 13:33:51 -0700 Subject: [PATCH 0815/1037] Catch errors client throws in pool (#2569) * Catch errors client throws in pool * Add a test This test _should be_ right --- packages/pg-pool/index.js | 32 ++++++++++++++----------- packages/pg-pool/test/error-handling.js | 11 +++++++++ 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 5e846bb31..20dbe734c 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -406,20 +406,24 @@ class Pool extends EventEmitter { client.once('error', onError) this.log('dispatching query') - client.query(text, values, (err, res) => { - this.log('query dispatched') - client.removeListener('error', onError) - if (clientReleased) { - return - } - clientReleased = true - client.release(err) - if (err) { - return cb(err) - } else { - return cb(undefined, res) - } - }) + try { + client.query(text, values, (err, res) => { + this.log('query dispatched') + client.removeListener('error', onError) + if (clientReleased) { + return + } + clientReleased = true + client.release(err) + if (err) { + return cb(err) + } else { + return cb(undefined, res) + } + }) + } catch (err) { + return cb(err) + } }) return response.result } diff --git a/packages/pg-pool/test/error-handling.js b/packages/pg-pool/test/error-handling.js index 0a996b82b..f514bd79f 100644 --- a/packages/pg-pool/test/error-handling.js +++ b/packages/pg-pool/test/error-handling.js @@ -37,6 +37,17 @@ describe('pool error handling', function () { }) }) + it('Catches errors in client.query', async function () { + await expect((new Pool()).query(null)).to.throwError() + await expect(async () => { + try { + await (new Pool()).query(null) + } catch (e) { + console.log(e) + } + }).not.to.throwError() + }) + describe('calling release more than once', () => { it( 'should throw each time', From 747485d342b8d7a5b47f988b668cea012ce50cf0 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 22 Aug 2022 15:34:07 -0500 Subject: [PATCH 0816/1037] Bump min version of pg-native (#2787) Fixes 2786 --- packages/pg/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg/package.json b/packages/pg/package.json index e1eec9fa9..34b833298 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -35,7 +35,7 @@ "pg-copy-streams": "0.3.0" }, "peerDependencies": { - "pg-native": ">=2.0.0" + "pg-native": ">=3.0.1" }, "peerDependenciesMeta": { "pg-native": { From a4ef6ce38c1e04bad2215312b1c79e64654cc857 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 22 Aug 2022 19:05:59 -0500 Subject: [PATCH 0817/1037] Fix error handling test (#2789) * Fix error handling test #2569 introduced a bug in the test. The test never passed but because travis-ci lovingly broke the integration we had a long time ago the tests weren't run in CI until I merged. So, this fixes the tests & does a better job cleaning up the query in an errored state. * Update sponsors --- SPONSORS.md | 3 +++ packages/pg-pool/index.js | 4 ++-- packages/pg-pool/test/error-handling.js | 17 +++++++++-------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/SPONSORS.md b/SPONSORS.md index 71c5210bc..3bebb01eb 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -13,6 +13,9 @@ node-postgres is made possible by the helpful contributors from the community as - [simpleanalytics](https://simpleanalytics.com/) - [n8n.io](https://n8n.io/) - [mpirik](https://github.com/mpirik) +- [@BLUE-DEVIL1134](https://github.com/BLUE-DEVIL1134) +- [bubble.io](https://bubble.io/) +- GitHub[https://github.com/github] # Supporters diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 20dbe734c..00f55b4da 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -417,11 +417,11 @@ class Pool extends EventEmitter { client.release(err) if (err) { return cb(err) - } else { - return cb(undefined, res) } + return cb(undefined, res) }) } catch (err) { + client.release(err) return cb(err) } }) diff --git a/packages/pg-pool/test/error-handling.js b/packages/pg-pool/test/error-handling.js index f514bd79f..7b1570859 100644 --- a/packages/pg-pool/test/error-handling.js +++ b/packages/pg-pool/test/error-handling.js @@ -38,14 +38,15 @@ describe('pool error handling', function () { }) it('Catches errors in client.query', async function () { - await expect((new Pool()).query(null)).to.throwError() - await expect(async () => { - try { - await (new Pool()).query(null) - } catch (e) { - console.log(e) - } - }).not.to.throwError() + let caught = false + const pool = new Pool() + try { + await pool.query(null) + } catch (e) { + caught = true + } + pool.end() + expect(caught).to.be(true) }) describe('calling release more than once', () => { From ff85ac24592441e8092b40373ea4ba88af1aae8a Mon Sep 17 00:00:00 2001 From: Marcin K Date: Tue, 23 Aug 2022 02:06:43 +0200 Subject: [PATCH 0818/1037] chore(): added dependabot (#2374) --- .github/dependabot.yaml | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .github/dependabot.yaml diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 000000000..41a081f92 --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,7 @@ + +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "monthly" \ No newline at end of file From 6e386eb29479e063d741e597ab85d462af31d12f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Aug 2022 21:35:18 -0500 Subject: [PATCH 0819/1037] Bump prettier from 2.1.2 to 2.7.1 (#2792) Bumps [prettier](https://github.com/prettier/prettier) from 2.1.2 to 2.7.1. - [Release notes](https://github.com/prettier/prettier/releases) - [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/prettier/compare/2.1.2...2.7.1) --- updated-dependencies: - dependency-name: prettier dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 3de85d252..b8ac7659b 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,7 @@ "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^3.1.4", "lerna": "^3.19.0", - "prettier": "2.1.2", + "prettier": "2.7.1", "typescript": "^4.0.3" }, "prettier": { diff --git a/yarn.lock b/yarn.lock index 66527b4aa..d1cce1ee2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4925,10 +4925,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5" - integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg== +prettier@2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" + integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== process-nextick-args@~2.0.0: version "2.0.1" From 8d498959c396797d60f822c2d1a6ac4a87481d3c Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Tue, 23 Aug 2022 11:29:35 -0500 Subject: [PATCH 0820/1037] Update changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72599c724..f017a3d5a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +## pg@8.8.0 + +- Bump minimum required version of [native bindings](https://github.com/brianc/node-postgres/pull/2787) +- Catch previously uncatchable errors thrown in [`pool.query`](https://github.com/brianc/node-postgres/pull/2569) +- Prevent the pool from blocking the event loop if all clients are [idle](https://github.com/brianc/node-postgres/pull/2721) (and `allowExitOnIdle` is enabled) +- Support `lock_timeout` in [client config](https://github.com/brianc/node-postgres/pull/2779) +- Fix errors thrown in callbacks from [interfering with cleanup](https://github.com/brianc/node-postgres/pull/2753) + ### pg-pool@3.5.0 - Add connection [lifetime limit](https://github.com/brianc/node-postgres/pull/2698) config option. From c99fb2c127ddf8d712500db2c7b9a5491a178655 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Tue, 23 Aug 2022 11:36:18 -0500 Subject: [PATCH 0821/1037] Publish - pg-cursor@2.7.4 - pg-pool@3.5.2 - pg-query-stream@4.2.4 - pg@8.8.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 6104c9557..c12906abd 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.7.3", + "version": "2.7.4", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.7.3" + "pg": "^8.8.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index d89c12c5e..0bb64b579 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.5.1", + "version": "3.5.2", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 227cdc4fe..528ed271d 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "4.2.3", + "version": "4.2.4", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,12 +37,12 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^3.5.0", "mocha": "^7.1.2", - "pg": "^8.7.3", + "pg": "^8.8.0", "stream-spec": "~0.3.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" }, "dependencies": { - "pg-cursor": "^2.7.3" + "pg-cursor": "^2.7.4" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 34b833298..37afe6149 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.7.3", + "version": "8.8.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "^2.5.0", - "pg-pool": "^3.5.1", + "pg-pool": "^3.5.2", "pg-protocol": "^1.5.0", "pg-types": "^2.1.0", "pgpass": "1.x" From ad6c4a4693801120eaa0d7941664e2d30d53283d Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 29 Aug 2022 13:32:48 -0500 Subject: [PATCH 0822/1037] Update README.md (#2799) Build status icon was still pointing at travis. We don't use travis anymore: we use github actions. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bf3a7be82..15b693128 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # node-postgres -[![Build Status](https://secure.travis-ci.org/brianc/node-postgres.svg?branch=master)](http://travis-ci.org/brianc/node-postgres) +![Build Status](https://github.com/brianc/node-postgres/actions/workflows/ci.yml/badge.svg) NPM version NPM downloads From 8250af4aed9b8977932560733fe8665831aeef4d Mon Sep 17 00:00:00 2001 From: Alex <93376818+sashashura@users.noreply.github.com> Date: Mon, 29 Aug 2022 20:55:10 +0100 Subject: [PATCH 0823/1037] Minimize GitHub Workflows permissions (#2798) Signed-off-by: sashashura <93376818+sashashura@users.noreply.github.com> --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 14e24db12..73e5709d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,6 +2,9 @@ name: CI on: [push, pull_request] +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest From 659ac37ba3922be2be5880d42c09192d951825b1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Sep 2022 06:31:37 +0200 Subject: [PATCH 0824/1037] Bump eslint-plugin-promise from 3.8.0 to 6.0.1 (#2802) Bumps [eslint-plugin-promise](https://github.com/xjamundx/eslint-plugin-promise) from 3.8.0 to 6.0.1. - [Release notes](https://github.com/xjamundx/eslint-plugin-promise/releases) - [Changelog](https://github.com/xjamundx/eslint-plugin-promise/blob/development/CHANGELOG.md) - [Commits](https://github.com/xjamundx/eslint-plugin-promise/commits) --- updated-dependencies: - dependency-name: eslint-plugin-promise dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/pg-query-stream/package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 528ed271d..7a789970f 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -35,7 +35,7 @@ "@types/pg": "^7.14.5", "JSONStream": "~0.7.1", "concat-stream": "~1.0.1", - "eslint-plugin-promise": "^3.5.0", + "eslint-plugin-promise": "^6.0.1", "mocha": "^7.1.2", "pg": "^8.8.0", "stream-spec": "~0.3.5", diff --git a/yarn.lock b/yarn.lock index d1cce1ee2..d33799e00 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2382,10 +2382,10 @@ eslint-plugin-prettier@^3.1.4: dependencies: prettier-linter-helpers "^1.0.0" -eslint-plugin-promise@^3.5.0: - version "3.8.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-3.8.0.tgz#65ebf27a845e3c1e9d6f6a5622ddd3801694b621" - integrity sha512-JiFL9UFR15NKpHyGii1ZcvmtIqa3UTwiDAGb8atSffe43qJ3+1czVGN6UtkklpcJ2DVnqvTMzEKRaJdBkAL2aQ== +eslint-plugin-promise@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.0.1.tgz#a8cddf96a67c4059bdabf4d724a29572188ae423" + integrity sha512-uM4Tgo5u3UWQiroOyDEsYcVMOo7re3zmno0IZmB5auxoaQNIceAbXEkSt8RNrKtaYehARHG06pYK6K1JhtP0Zw== eslint-scope@^5.0.0, eslint-scope@^5.1.1: version "5.1.1" From 34d173d9e36430faff8c5aa1749f850fe1a9a739 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 17 Sep 2022 20:59:43 +0200 Subject: [PATCH 0825/1037] Bump coveralls from 3.1.0 to 3.1.1 (#2801) Bumps [coveralls](https://github.com/nickmerwin/node-coveralls) from 3.1.0 to 3.1.1. - [Release notes](https://github.com/nickmerwin/node-coveralls/releases) - [Commits](https://github.com/nickmerwin/node-coveralls/compare/v3.1.0...3.1.1) --- updated-dependencies: - dependency-name: coveralls dependency-type: direct:development update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index d33799e00..9cd0b3c06 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1966,9 +1966,9 @@ cosmiconfig@^5.1.0: parse-json "^4.0.0" coveralls@^3.0.4: - version "3.1.0" - resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.0.tgz#13c754d5e7a2dd8b44fe5269e21ca394fb4d615b" - integrity sha512-sHxOu2ELzW8/NC1UP5XVLbZDzO4S3VxfFye3XYCznopHy02YjNkHcj5bKaVw2O7hVaBdBjEdQGpie4II1mWhuQ== + version "3.1.1" + resolved "https://registry.yarnpkg.com/coveralls/-/coveralls-3.1.1.tgz#f5d4431d8b5ae69c5079c8f8ca00d64ac77cf081" + integrity sha512-+dxnG2NHncSD1NrqbSM3dn/lE57O6Qf/koe9+I7c+wzkqRmEvcp0kgJdxKInzYzkICKkFMZsX3Vct3++tsF9ww== dependencies: js-yaml "^3.13.1" lcov-parse "^1.0.0" From 9a95ee719b181341d381702a4404827ca906b036 Mon Sep 17 00:00:00 2001 From: Matthieu Date: Mon, 19 Sep 2022 19:29:53 +0200 Subject: [PATCH 0826/1037] pg-query-stream: Add missing peer dependency on pg (#2813) pg-query-stream depends on pg-cursor, which has a peer dependency on pg. --- packages/pg-query-stream/package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 7a789970f..92a42fe95 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -42,6 +42,9 @@ "ts-node": "^8.5.4", "typescript": "^4.0.3" }, + "peerDependencies": { + "pg": "^8" + }, "dependencies": { "pg-cursor": "^2.7.4" } From 9e2d7c4ad5d5e6c168e428d5b11326f0fd48b6db Mon Sep 17 00:00:00 2001 From: Yue Dai Date: Tue, 27 Sep 2022 03:31:07 -0700 Subject: [PATCH 0827/1037] Update pg.connect with pool.connect (#2822) pg.connect() has been deprecated. --- packages/pg-query-stream/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/pg-query-stream/README.md b/packages/pg-query-stream/README.md index d5b2802bd..b2e860528 100644 --- a/packages/pg-query-stream/README.md +++ b/packages/pg-query-stream/README.md @@ -15,11 +15,12 @@ _requires pg>=2.8.1_ ```js const pg = require('pg') +var pool = new pg.Pool() const QueryStream = require('pg-query-stream') const JSONStream = require('JSONStream') //pipe 1,000,000 rows to stdout without blowing up your memory usage -pg.connect((err, client, done) => { +pool.connect((err, client, done) => { if (err) throw err const query = new QueryStream('SELECT * FROM generate_series(0, $1) num', [1000000]) const stream = client.query(query) From 9dfb3dccbfd78c088f093dd4c0c11bda7ccd2465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Mat=C4=9Bjka?= Date: Tue, 27 Sep 2022 12:38:28 +0200 Subject: [PATCH 0828/1037] perf(pg): use native crypto.pbkdf2Sync in sasl auth (#2815) --- packages/pg/lib/sasl.js | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/packages/pg/lib/sasl.js b/packages/pg/lib/sasl.js index c61804750..fb703b270 100644 --- a/packages/pg/lib/sasl.js +++ b/packages/pg/lib/sasl.js @@ -37,7 +37,7 @@ function continueSession(session, password, serverData) { var saltBytes = Buffer.from(sv.salt, 'base64') - var saltedPassword = Hi(password, saltBytes, sv.iteration) + var saltedPassword = crypto.pbkdf2Sync(password, saltBytes, sv.iteration, 32, 'sha256') var clientKey = hmacSha256(saltedPassword, 'Client Key') var storedKey = sha256(clientKey) @@ -191,17 +191,6 @@ function hmacSha256(key, msg) { return crypto.createHmac('sha256', key).update(msg).digest() } -function Hi(password, saltBytes, iterations) { - var ui1 = hmacSha256(password, Buffer.concat([saltBytes, Buffer.from([0, 0, 0, 1])])) - var ui = ui1 - for (var i = 0; i < iterations - 1; i++) { - ui1 = hmacSha256(password, ui1) - ui = xorBuffers(ui, ui1) - } - - return ui -} - module.exports = { startSession, continueSession, From 5bcc05d1e95104d20ce08a6e3e56d0acdcc4b757 Mon Sep 17 00:00:00 2001 From: Alex Anderson <191496+alxndrsn@users.noreply.github.com> Date: Thu, 6 Oct 2022 19:59:11 +0300 Subject: [PATCH 0829/1037] pg-protocol: fix link to message format docs (#2835) --- packages/pg-protocol/src/testing/test-buffers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg-protocol/src/testing/test-buffers.ts b/packages/pg-protocol/src/testing/test-buffers.ts index e0a04a758..a4d49f322 100644 --- a/packages/pg-protocol/src/testing/test-buffers.ts +++ b/packages/pg-protocol/src/testing/test-buffers.ts @@ -1,4 +1,4 @@ -// http://developer.postgresql.org/pgdocs/postgres/protocol-message-formats.html +// https://www.postgresql.org/docs/current/protocol-message-formats.html import BufferList from './buffer-list' const buffers = { From 1aa08274a52c076af9891650d7228f029439a158 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 10 Oct 2022 12:20:46 -0500 Subject: [PATCH 0830/1037] Migrate docs repo into monorepo (#2823) * Move files over * Finish initial port of content --- docs/.gitignore | 2 + docs/components/alert.tsx | 10 + docs/components/info.tsx | 6 + docs/next.config.js | 8 + docs/package.json | 20 + docs/pages/_app.js | 9 + docs/pages/_meta.json | 5 + docs/pages/announcements.mdx | 145 ++ docs/pages/apis/_meta.json | 7 + docs/pages/apis/client.mdx | 330 +++++ docs/pages/apis/cursor.mdx | 81 + docs/pages/apis/pool.mdx | 274 ++++ docs/pages/apis/result.mdx | 52 + docs/pages/apis/types.mdx | 6 + docs/pages/features/_meta.json | 9 + docs/pages/features/connecting.mdx | 162 ++ docs/pages/features/native.mdx | 27 + docs/pages/features/pooling.mdx | 173 +++ docs/pages/features/queries.mdx | 211 +++ docs/pages/features/ssl.mdx | 61 + docs/pages/features/transactions.mdx | 93 ++ docs/pages/features/types.mdx | 106 ++ docs/pages/guides/_meta.json | 5 + docs/pages/guides/async-express.md | 83 ++ docs/pages/guides/project-structure.md | 197 +++ docs/pages/guides/upgrading.md | 114 ++ docs/pages/index.mdx | 65 + docs/theme.config.js | 27 + docs/yarn.lock | 1892 ++++++++++++++++++++++++ package.json | 2 + 30 files changed, 4182 insertions(+) create mode 100644 docs/.gitignore create mode 100644 docs/components/alert.tsx create mode 100644 docs/components/info.tsx create mode 100644 docs/next.config.js create mode 100644 docs/package.json create mode 100644 docs/pages/_app.js create mode 100644 docs/pages/_meta.json create mode 100644 docs/pages/announcements.mdx create mode 100644 docs/pages/apis/_meta.json create mode 100644 docs/pages/apis/client.mdx create mode 100644 docs/pages/apis/cursor.mdx create mode 100644 docs/pages/apis/pool.mdx create mode 100644 docs/pages/apis/result.mdx create mode 100644 docs/pages/apis/types.mdx create mode 100644 docs/pages/features/_meta.json create mode 100644 docs/pages/features/connecting.mdx create mode 100644 docs/pages/features/native.mdx create mode 100644 docs/pages/features/pooling.mdx create mode 100644 docs/pages/features/queries.mdx create mode 100644 docs/pages/features/ssl.mdx create mode 100644 docs/pages/features/transactions.mdx create mode 100644 docs/pages/features/types.mdx create mode 100644 docs/pages/guides/_meta.json create mode 100644 docs/pages/guides/async-express.md create mode 100644 docs/pages/guides/project-structure.md create mode 100644 docs/pages/guides/upgrading.md create mode 100644 docs/pages/index.mdx create mode 100644 docs/theme.config.js create mode 100644 docs/yarn.lock diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 000000000..2b3533c7e --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1,2 @@ +.next +out diff --git a/docs/components/alert.tsx b/docs/components/alert.tsx new file mode 100644 index 000000000..7bf2237ca --- /dev/null +++ b/docs/components/alert.tsx @@ -0,0 +1,10 @@ +import React from 'react' +import { Callout } from 'nextra-theme-docs' + +export const Alert = ({ children }) => { + return ( + + {children} + + ) +} diff --git a/docs/components/info.tsx b/docs/components/info.tsx new file mode 100644 index 000000000..a61e17fb2 --- /dev/null +++ b/docs/components/info.tsx @@ -0,0 +1,6 @@ +import React from 'react' +import { Callout } from 'nextra-theme-docs' + +export const Info = ({ children }) => { + return {children} +} diff --git a/docs/next.config.js b/docs/next.config.js new file mode 100644 index 000000000..45a998c7c --- /dev/null +++ b/docs/next.config.js @@ -0,0 +1,8 @@ +// next.config.js +const withNextra = require('nextra')({ + theme: 'nextra-theme-docs', + themeConfig: './theme.config.js', + // optional: add `unstable_staticImage: true` to enable Nextra's auto image import +}) + +module.exports = withNextra() diff --git a/docs/package.json b/docs/package.json new file mode 100644 index 000000000..dec5cceb2 --- /dev/null +++ b/docs/package.json @@ -0,0 +1,20 @@ +{ + "name": "docs", + "version": "1.0.0", + "description": "", + "main": "next.config.js", + "scripts": { + "start": "next dev", + "build": "next build && next export" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "next": "^12.3.1", + "nextra": "2.0.0-beta.29", + "nextra-theme-docs": "2.0.0-beta.29", + "react": "^17.0.1", + "react-dom": "^17.0.1" + } +} diff --git a/docs/pages/_app.js b/docs/pages/_app.js new file mode 100644 index 000000000..19532b06e --- /dev/null +++ b/docs/pages/_app.js @@ -0,0 +1,9 @@ +import 'nextra-theme-docs/style.css' + +export default function Nextra({ Component, pageProps }) { + return ( + <> + + + ) +} diff --git a/docs/pages/_meta.json b/docs/pages/_meta.json new file mode 100644 index 000000000..dd241d886 --- /dev/null +++ b/docs/pages/_meta.json @@ -0,0 +1,5 @@ +{ + "index": "Welcome", + "announcements": "Announcements", + "apis": "API" +} diff --git a/docs/pages/announcements.mdx b/docs/pages/announcements.mdx new file mode 100644 index 000000000..6fec81ca3 --- /dev/null +++ b/docs/pages/announcements.mdx @@ -0,0 +1,145 @@ +import { Alert } from '/components/alert.tsx' + +## 2020-02-25 + +### pg@8.0 release + +`pg@8.0` is [being released](https://github.com/brianc/node-postgres/pull/2117) which contains a handful of breaking changes. + +I will outline each breaking change here and try to give some historical context on them. Most of them are small and subtle and likely wont impact you; **however**, there is one larger breaking change you will likely run into: + +--- + +- Support all `tls.connect` [options](https://nodejs.org/api/tls.html#tls_tls_connect_options_callback) being passed to the client/pool constructor under the `ssl` option. + +Previously we white listed the parameters passed here and did slight massaging of some of them. The main **breaking** change here is that now if you do this: + +```js +const client = new Client({ ssl: true }) +``` + + + Now we will use the default ssl options to tls.connect which includes rejectUnauthorized being enabled. This means + your connection attempt may fail if you are using a self-signed cert. To use the old behavior you should do this: + + +```js +const client = new Client({ ssl: { rejectUnauthorized: false } }) +``` + +This makes pg a bit more secure "out of the box" while still enabling you to opt in to the old behavior. + +--- + +The rest of the changes are relatively minor & you likely wont need to do anything, but good to be aware none the less! + +- change default database name + +If a database name is not specified, available in the environment at `PGDATABASE`, or available at `pg.defaults`, we used to use the username of the process user as the name of the database. Now we will use the `user` property supplied to the client as the database name, if it exists. What this means is this: + +```jsx +new Client({ + user: 'foo', +}) +``` + +`pg@7.x` will default the database name to the _process_ user. `pg@8.x` will use the `user` property supplied to the client. If you have not supplied `user` to the client, and it isn't available through any of its existing lookup mechanisms (environment variables, pg.defaults) then it will still use the process user for the database name. + +- drop support for versions of node older than 8.0 + +Node@6.0 has been out of LTS for quite some time now, and I've removed it from our test matrix. `pg@8.0` _may_ still work on older versions of node, but it isn't a goal of the project anymore. Node@8.0 is actually no longer in the LTS support line, but pg will continue to test against and support 8.0 until there is a compelling reason to drop support for it. Any security vulnerability issues which come up I will back-port fixes to the `pg@7.x` line and do a release, but any other fixes or improvments will not be back ported. + +- prevent password from being logged accidentally + +`pg@8.0` makes the password field on the pool and client non-enumerable. This means when you do `console.log(client)` you wont have your database password printed out unintenionally. You can still do `console.log(client.password)` if you really want to see it! + +- make `pg.native` non-enumerable + +You can use `pg.native.Client` to access the native client. The first time you access the `pg.native` getter it imports the native bindings...which must be installed. In some cases (such as webpacking the pg code for lambda deployment) the `.native` property would be traversed and trigger an import of the native bindings as a side-effect. Making this property non-enumerable will fix this issue. An easy fix, but its technically a breaking change in cases where people _are_ relying on this side effect for any reason. + +- make `pg.Pool` an es6 class + +This makes extending `pg.Pool` possible. Previously it was not a "proper" es6 class and `class MyPool extends pg.Pool` wouldn't work. + +- make `Notice` messages _not_ an instance of a JavaScript error + +The code path for parsing `notice` and `error` messages from the postgres backend is the same. Previously created a JavaScript `Error` instance for _both_ of these message types. Now, only actual `errors` from the postgres backend will be an instance of an `Error`. The _shape_ and _properties_ of the two messages did not change outside of this. + +- monorepo + +While not technically a breaking change for the module itself, I have begun the process of [consolidating](https://github.com/brianc/node-pg-query-stream) [separate](https://github.com/brianc/node-pg-cursor/) [repos](https://github.com/brianc/node-pg-pool) into the main [repo](https://github.com/brianc/node-postgres) and converted it into a monorepo managed by lerna. This will help me stay on top of issues better (it was hard to bounce between 3-4 separate repos) and coordinate bug fixes and changes between dependant modules. + +Thanks for reading that! pg tries to be super pedantic about not breaking backwards-compatibility in non semver major releases....even for seemingly small things. If you ever notice a breaking change on a semver minor/patch release please stop by the [repo](https://github.com/brianc/node-postgres) and open an issue! + +_If you find `pg` valuable to you or your business please consider [supporting](http://github.com/sponsors/brianc) it's continued development! Big performance improvements, typescript, better docs, query pipelining and more are all in the works!_ + +## 2019-07-18 + +### New documentation + +After a _very_ long time on my todo list I've ported the docs from my old hand-rolled webapp running on route53 + elb + ec2 + dokku (I know, I went overboard!) to [gatsby](https://www.gatsbyjs.org/) hosted on [netlify](https://www.netlify.com/) which is _so_ much easier to manage. I've released the code at [https://github.com/brianc/node-postgres-docs](https://github.com/brianc/node-postgres-docs) and invite your contributions! Let's make this documentation better together. Any time changes are merged to master on the documentation repo it will automatically deploy. + +If you see an error in the docs, big or small, use the "edit on github" button to edit the page & submit a pull request right there. I'll get a new version out ASAP with your changes! If you want to add new pages of documentation open an issue if you need guidance, and I'll help you get started. + +I want to extend a special **thank you** to all the [supporters](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) and [contributors](https://github.com/brianc/node-postgres/graphs/contributors) to the project that have helped keep me going through times of burnout or life "getting in the way." ❤️ + +It's been quite a journey, and I look forward continuing it for as long as I can provide value to all y'all. 🤠 + +## 2017-08-12 + +### code execution vulnerability + +Today [@sehrope](https://github.com/sehrope) found and reported a code execution vulnerability in node-postgres. This affects all versions from `pg@2.x` through `pg@7.1.0`. + +I have published a fix on the tip of each major version branch of all affected versions as well as a fix on each minor version branch of `pg@6.x` and `pg@7.x`: + +### Fixes + +The following versions have been published to npm & contain a patch to fix the vulnerability: + +``` +pg@2.11.2 +pg@3.6.4 +pg@4.5.7 +pg@5.2.1 +pg@6.0.5 +pg@6.1.6 +pg@6.2.5 +pg@6.3.3 +pg@6.4.2 +pg@7.0.3 +pg@7.1.2 +``` + +### Example + +To demonstrate the issue & see if you are vunerable execute the following in node: + +```js +const { Client } = require('pg') +const client = new Client() +client.connect() + +const sql = `SELECT 1 AS "\\'/*", 2 AS "\\'*/\n + console.log(process.env)] = null;\n//"` + +client.query(sql, (err, res) => { + client.end() +}) +``` + +You will see your environment variables printed to your console. An attacker can use this exploit to execute any arbitrary node code within your process. + +### Impact + +This vulnerability _likely_ does not impact you if you are connecting to a database you control and not executing user-supplied sql. Still, you should **absolutely** upgrade to the most recent patch version as soon as possible to be safe. + +Two attack vectors we quickly thought of: + +- 1 - executing unsafe, user-supplied sql which contains a malicious column name like the one above. +- 2 - connecting to an untrusted database and executing a query which returns results where any of the column names are malicious. + +### Support + +I have created [an issue](https://github.com/brianc/node-postgres/issues/1408) you can use to discuss the vulnerability with me or ask questions, and I have reported this issue [on twitter](https://twitter.com/briancarlson) and directly to Heroku and [nodesecurity.io](https://nodesecurity.io/). + +I take security very seriously. If you or your company benefit from node-postgres **[please sponsor my work](https://www.patreon.com/node_postgres)**: this type of issue is one of the many things I am responsible for, and I want to be able to continue to tirelessly provide a world-class PostgreSQL experience in node for years to come. diff --git a/docs/pages/apis/_meta.json b/docs/pages/apis/_meta.json new file mode 100644 index 000000000..0b6a193c7 --- /dev/null +++ b/docs/pages/apis/_meta.json @@ -0,0 +1,7 @@ +{ + "client": "pg.Client", + "pool": "pg.Pool", + "result": "pg.Result", + "types": "pg.Types", + "cursor": "Cursor" +} diff --git a/docs/pages/apis/client.mdx b/docs/pages/apis/client.mdx new file mode 100644 index 000000000..c983859b6 --- /dev/null +++ b/docs/pages/apis/client.mdx @@ -0,0 +1,330 @@ +--- +title: pg.Client +--- + +## new Client + +`new Client(config: Config)` + +Every field of the `config` object is entirely optional. A `Client` instance will use [environment variables](/features/connecting#environment-variables) for all missing values. + +```ts +type Config = { + user?: string, // default process.env.PGUSER || process.env.USER + password?: string or function, //default process.env.PGPASSWORD + host?: string, // default process.env.PGHOST + database?: string, // default process.env.PGDATABASE || user + port?: number, // default process.env.PGPORT + connectionString?: string, // e.g. postgres://user:password@host:5432/database + ssl?: any, // passed directly to node.TLSSocket, supports all tls.connect options + types?: any, // custom type parsers + statement_timeout?: number, // number of milliseconds before a statement in query will time out, default is no timeout + query_timeout?: number, // number of milliseconds before a query call will timeout, default is no timeout + application_name?: string, // The name of the application that created this Client instance + connectionTimeoutMillis?: number, // number of milliseconds to wait for connection, default is no timeout + idle_in_transaction_session_timeout?: number // number of milliseconds before terminating any session with an open idle transaction, default is no timeout +} +``` + +example to create a client with specific connection information: + +```js +const { Client } = require('pg') + +const client = new Client({ + host: 'my.database-server.com', + port: 5334, + user: 'database-user', + password: 'secretpassword!!', +}) +``` + +## client.connect + +### `client.connect(callback: (err: Error) => void) => void` + +Calling `client.connect` with a callback: + +```js +const { Client } = require('pg') +const client = new Client() +client.connect((err) => { + if (err) { + console.error('connection error', err.stack) + } else { + console.log('connected') + } +}) +``` + +### `client.connect() => Promise` + +Calling `client.connect` without a callback yields a promise: + +```js +const { Client } = require('pg') +const client = new Client() +client + .connect() + .then(() => console.log('connected')) + .catch((err) => console.error('connection error', err.stack)) +``` + +_note: connect returning a promise only available in pg@7.0 or above_ + +## client.query + +### `client.query` - text, optional values, and callback. + +Passing query text, optional query parameters, and a callback to `client.query` results in a type-signature of: + +```ts +client.query( + text: string, + values?: Array, + callback: (err: Error, result: Result) => void +) => void +``` + +That is a kinda gross type signature but it translates out to this: + +**Plain text query with a callback:** + +```js +const { Client } = require('pg') +const client = new Client() +client.connect() +client.query('SELECT NOW()', (err, res) => { + if (err) throw err + console.log(res) + client.end() +}) +``` + +**Parameterized query with a callback:** + +```js +const { Client } = require('pg') +const client = new Client() +client.connect() +client.query('SELECT $1::text as name', ['brianc'], (err, res) => { + if (err) throw err + console.log(res) + client.end() +}) +``` + +### `client.query` - text, optional values: Promise + +If you call `client.query` with query text and optional parameters but **don't** pass a callback, then you will receive a `Promise` for a query result. + +```ts +client.query( + text: string, + values?: Array +) => Promise +``` + +**Plain text query with a promise** + +```js +const { Client } = require('pg') +const client = new Client() +client.connect() +client + .query('SELECT NOW()') + .then((result) => console.log(result)) + .catch((e) => console.error(e.stack)) + .then(() => client.end()) +``` + +**Parameterized query with a promise** + +```js +const { Client } = require('pg') +const client = new Client() +client.connect() +client + .query('SELECT $1::text as name', ['brianc']) + .then((result) => console.log(result)) + .catch((e) => console.error(e.stack)) + .then(() => client.end()) +``` + +### `client.query(config: QueryConfig, callback: (err?: Error, result?: Result) => void) => void` + +### `client.query(config: QueryConfig) => Promise` + +You can pass an object to `client.query` with the signature of: + +```ts +type QueryConfig { + // the raw query text + text: string; + + // an array of query parameters + values?: Array; + + // name of the query - used for prepared statements + name?: string; + + // by default rows come out as a key/value pair for each row + // pass the string 'array' here to receive rows as an array of values + rowMode?: string; + + // custom type parsers just for this query result + types?: Types; +} +``` + +**client.query with a QueryConfig and a callback** + +If you pass a `name` parameter to the `client.query` method, the client will create a [prepared statement](/features/queries#prepared-statements). + +```js +const query = { + name: 'get-name', + text: 'SELECT $1::text', + values: ['brianc'], + rowMode: 'array', +} + +client.query(query, (err, res) => { + if (err) { + console.error(err.stack) + } else { + console.log(res.rows) // ['brianc'] + } +}) +``` + +**client.query with a QueryConfig and a Promise** + +```js +const query = { + name: 'get-name', + text: 'SELECT $1::text', + values: ['brianc'], + rowMode: 'array', +} + +// promise +client + .query(query) + .then((res) => { + console.log(res.rows) // ['brianc'] + }) + .catch((e) => { + console.error(e.stack) + }) +``` + +**client.query with a `Submittable`** + +If you pass an object to `client.query` and the object has a `.submit` function on it, the client will pass it's PostgreSQL server connection to the object and delegate query dispatching to the supplied object. This is an advanced feature mostly intended for library authors. It is incidentally also currently how the callback and promise based queries above are handled internally, but this is subject to change. It is also how [pg-cursor](https://github.com/brianc/node-pg-cursor) and [pg-query-stream](https://github.com/brianc/node-pg-query-stream) work. + +```js +const Query = require('pg').Query +const query = new Query('select $1::text as name', ['brianc']) + +const result = client.query(query) + +assert(query === result) // true + +query.on('row', (row) => { + console.log('row!', row) // { name: 'brianc' } +}) +query.on('end', () => { + console.log('query done') +}) +query.on('error', (err) => { + console.error(err.stack) +}) +``` + +--- + +## client.end + +### client.end(cb?: (err?: Error) => void) => void + +Disconnects the client from the PostgreSQL server. + +```js +client.end((err) => { + console.log('client has disconnected') + if (err) { + console.log('error during disconnection', err.stack) + } +}) +``` + +### `client.end() => Promise` + +Calling end without a callback yields a promise: + +```js +client + .end() + .then(() => console.log('client has disconnected')) + .catch((err) => console.error('error during disconnection', err.stack)) +``` + +_note: end returning a promise is only available in pg7.0 and above_ + +## events + +### client.on('error', (err: Error) => void) => void + +When the client is in the process of connecting, dispatching a query, or disconnecting it will catch and foward errors from the PostgreSQL server to the respective `client.connect` `client.query` or `client.end` callback/promise; however, the client maintains a long-lived connection to the PostgreSQL back-end and due to network partitions, back-end crashes, fail-overs, etc the client can (and over a long enough time period _will_) eventually be disconnected while it is idle. To handle this you may want to attach an error listener to a client to catch errors. Here's a contrived example: + +```js +const client = new pg.Client() +client.connect() + +client.on('error', (err) => { + console.error('something bad has happened!', err.stack) +}) + +// walk over to server, unplug network cable + +// process output: 'something bad has happened!' followed by stacktrace :P +``` + +### client.on('end') => void + +When the client disconnects from the PostgreSQL server it will emit an end event once. + +### client.on('notification', (notification: Notification) => void) => void + +Used for `listen/notify` events: + +```ts +type Notification { + processId: number, + channel: string, + payload?: string +} +``` + +```js +const client = new pg.Client() +client.connect() + +client.query('LISTEN foo') + +client.on('notification', (msg) => { + console.log(msg.channel) // foo + console.log(msg.payload) // bar! +}) + +client.query(`NOTIFY foo, 'bar!'`) +``` + +### client.on('notice', (notice: Error) => void) => void + +Used to log out [notice messages](https://www.postgresql.org/docs/9.6/static/plpgsql-errors-and-messages.html) from the PostgreSQL server. + +```js +client.on('notice', (msg) => console.warn('notice:', msg)) +``` diff --git a/docs/pages/apis/cursor.mdx b/docs/pages/apis/cursor.mdx new file mode 100644 index 000000000..c4a6928c7 --- /dev/null +++ b/docs/pages/apis/cursor.mdx @@ -0,0 +1,81 @@ +--- +title: pg.Cursor +slug: /api/cursor +--- + +A cursor can be used to efficiently read through large result sets without loading the entire result-set into memory ahead of time. It's useful to simulate a 'streaming' style read of data, or exit early from a large result set. The cursor is passed to `client.query` and is dispatched internally in a way very similar to how normal queries are sent, but the API it presents for consuming the result set is different. + +## install + +``` +$ npm install pg pg-cursor +``` + +## constructor + +### `new Cursor(text: String, values: Any[][, config: CursorQueryConfig])` + +Instantiates a new Cursor. A cursor is an instance of `Submittable` and should be passed directly to the `client.query` method. + +```js +const { Pool } = require('pg') +const Cursor = require('pg-cursor') + +const pool = new Pool() +const client = await pool.connect() +const text = 'SELECT * FROM my_large_table WHERE something > $1' +const values = [10] + +const cursor = client.query(new Cursor(text, values)) + +cursor.read(100, (err, rows) => { + cursor.close(() => { + client.release() + }) +}) +``` + +```ts +type CursorQueryConfig { + // by default rows come out as a key/value pair for each row + // pass the string 'array' here to receive rows as an array of values + rowMode?: string; + + // custom type parsers just for this query result + types?: Types; +} +``` + +## read + +### `cursor.read(rowCount: Number, callback: (err: Error, rows: Row[], result: pg.Result) => void) => void` + +Read `rowCount` rows from the cursor instance. The callback will be called when the rows are available, loaded into memory, parsed, and converted to JavaScript types. + +If the cursor has read to the end of the result sets all subsequent calls to cursor#read will return a 0 length array of rows. Calling `read` on a cursor that has read to the end. + +Here is an example of reading to the end of a cursor: + +```js +const { Pool } = require('pg') +const Cursor = require('pg-cursor') + +const pool = new Pool() +const client = await pool.connect() +const cursor = client.query(new Cursor('select * from generate_series(0, 5)')) +cursor.read(100, (err, rows) => { + if (err) { + throw err + } + assert(rows.length == 6) + cursor.read(100, (err, rows) => { + assert(rows.length == 0) + }) +}) +``` + +## close + +### `cursor.close(callback: () => void) => void` + +Used to close the cursor early. If you want to stop reading from the cursor before you get all of the rows returned, call this. diff --git a/docs/pages/apis/pool.mdx b/docs/pages/apis/pool.mdx new file mode 100644 index 000000000..6ebc19044 --- /dev/null +++ b/docs/pages/apis/pool.mdx @@ -0,0 +1,274 @@ +--- +title: pg.Pool +--- + +import { Alert } from '/components/alert.tsx' + +## new Pool + +```ts +new Pool(config: Config) +``` + +Constructs a new pool instance. + +The pool is initially created empty and will create new clients lazily as they are needed. Every field of the `config` object is entirely optional. The config passed to the pool is also passed to every client instance within the pool when the pool creates that client. + +```ts +type Config = { + // all valid client config options are also valid here + // in addition here are the pool specific configuration parameters: + + // number of milliseconds to wait before timing out when connecting a new client + // by default this is 0 which means no timeout + connectionTimeoutMillis?: number + + // number of milliseconds a client must sit idle in the pool and not be checked out + // before it is disconnected from the backend and discarded + // default is 10000 (10 seconds) - set to 0 to disable auto-disconnection of idle clients + idleTimeoutMillis?: number + + // maximum number of clients the pool should contain + // by default this is set to 10. + max?: number + + // Default behavior is the pool will keep clients open & connected to the backend + // until idleTimeoutMillis expire for each client and node will maintain a ref + // to the socket on the client, keeping the event loop alive until all clients are closed + // after being idle or the pool is manually shutdown with `pool.end()`. + // + // Setting `allowExitOnIdle: true` in the config will allow the node event loop to exit + // as soon as all clients in the pool are idle, even if their socket is still open + // to the postgres server. This can be handy in scripts & tests + // where you don't want to wait for your clients to go idle before your process exits. + allowExitOnIdle?: boolean +} +``` + +example to create a new pool with configuration: + +```js +const { Pool } = require('pg') + +const pool = new Pool({ + host: 'localhost', + user: 'database-user', + max: 20, + idleTimeoutMillis: 30000, + connectionTimeoutMillis: 2000, +}) +``` + +## pool.query + +Often we only need to run a single query on the database, so as convenience the pool has a method to run a query on the first available idle client and return its result. + +`pool.query() => Promise` + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +pool + .query('SELECT $1::text as name', ['brianc']) + .then((res) => console.log(res.rows[0].name)) // brianc + .catch((err) => console.error('Error executing query', err.stack)) +``` + +Callbacks are also supported: + +`pool.query(callback: (err?: Error, result: pg.Result)) => void` + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +pool.query('SELECT $1::text as name', ['brianc'], (err, result) => { + if (err) { + return console.error('Error executing query', err.stack) + } + console.log(result.rows[0].name) // brianc +}) +``` + +Notice in the example above there is no need to check out or release a client. The pool is doing the acquiring and releasing internally. I find `pool.query` to be a handy shortcut many situations and use it exclusively unless I need a transaction. + + +
+ Do not use pool.query if you are using a transaction. +
+ The pool will dispatch every query passed to pool.query on the first available idle client. Transactions within PostgreSQL + are scoped to a single client and so dispatching individual queries within a single transaction across multiple, random + clients will cause big problems in your app and not work. For more info please read + transactions + . +
+ +## pool.connect + +`pool.connect(callback: (err?: Error, client?: pg.Client, release?: releaseCallback) => void) => void` + +Acquires a client from the pool. + +- If there are idle clients in the pool one will be returned to the callback on `process.nextTick`. +- If the pool is not full but all current clients are checked out a new client will be created & returned to this callback. +- If the pool is 'full' and all clients are currently checked out will wait in a FIFO queue until a client becomes available by it being released back to the pool. + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +pool.connect((err, client, release) => { + if (err) { + return console.error('Error acquiring client', err.stack) + } + client.query('SELECT NOW()', (err, result) => { + release() + if (err) { + return console.error('Error executing query', err.stack) + } + console.log(result.rows) + }) +}) +``` + +`pool.connect() => Promise` + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +;(async function () { + const client = await pool.connect() + await client.query('SELECT NOW()') + client.release() +})() +``` + +### releasing clients + +`release: (err?: Error)` + +Client instances returned from `pool.connect` will have a `release` method which will release them from the pool. + +The `release` method on an acquired client returns it back to the pool. If you pass a truthy value in the `err` position to the callback, instead of releasing the client to the pool, the pool will be instructed to disconnect and destroy this client, leaving a space within itself for a new client. + +```js +const { Pool } = require('pg') + +const pool = new Pool() +// check out a single client +const client = await pool.connect() +// release the client +client.release() +``` + +```js +const { Pool } = require('pg') + +const pool = new Pool() +assert(pool.totalCount === 0) +assert(pool.idleCount === 0) + +const client = await pool.connect() +await client.query('SELECT NOW()') +assert(pool.totalCount === 1) +assert(pool.idleCount === 0) + +// tell the pool to destroy this client +client.release(true) +assert(pool.idleCount === 0) +assert(pool.totalCount === 0) +``` + + +
+ You must release a client when you are finished with it. +
+ If you forget to release the client then your application will quickly exhaust available, idle clients in the pool and + all further calls to pool.connect will timeout with an error or hang indefinitely if you have + connectionTimeoutMillis + configured to 0. +
+ +## pool.end + +Calling `pool.end` will drain the pool of all active clients, disconnect them, and shut down any internal timers in the pool. It is common to call this at the end of a script using the pool or when your process is attempting to shut down cleanly. + +```js +// again both promises and callbacks are supported: +const { Pool } = require('pg') + +const pool = new Pool() + +// either this: +pool.end(() => { + console.log('pool has ended') +}) + +// or this: +pool.end().then(() => console.log('pool has ended')) +``` + +## properties + +`pool.totalCount: number` + +The total number of clients existing within the pool. + +`pool.idleCount: number` + +The number of clients which are not checked out but are currently idle in the pool. + +`pool.waitingCount: number` + +The number of queued requests waiting on a client when all clients are checked out. It can be helpful to monitor this number to see if you need to adjust the size of the pool. + +## events + +`Pool` instances are also instances of [`EventEmitter`](https://nodejs.org/api/events.html). + +### connect + +`pool.on('connect', (client: Client) => void) => void` + +Whenever the pool establishes a new client connection to the PostgreSQL backend it will emit the `connect` event with the newly connected client. This presents an opportunity for you to run setup commands on a client. + +```js +const pool = new Pool() +pool.on('connect', (client) => { + client.query('SET DATESTYLE = iso, mdy') +}) +``` + +### acquire + +`pool.on('acquire', (client: Client) => void) => void` + +Whenever a client is checked out from the pool the pool will emit the `acquire` event with the client that was acquired. + +### error + +`pool.on('error', (err: Error, client: Client) => void) => void` + +When a client is sitting idly in the pool it can still emit errors because it is connected to a live backend. + +If the backend goes down or a network partition is encountered all the idle, connected clients in your application will emit an error _through_ the pool's error event emitter. + +The error listener is passed the error as the first argument and the client upon which the error occurred as the 2nd argument. The client will be automatically terminated and removed from the pool, it is only passed to the error handler in case you want to inspect it. + + +
You probably want to add an event listener to the pool to catch background errors errors!
+ Just like other event emitters, if a pool emits an error event and no listeners are added node will emit an + uncaught error and potentially crash your node process. +
+ +### remove + +`pool.on('remove', (client: Client) => void) => void` + +Whenever a client is closed & removed from the pool the pool will emit the `remove` event. diff --git a/docs/pages/apis/result.mdx b/docs/pages/apis/result.mdx new file mode 100644 index 000000000..a0ef7ddb8 --- /dev/null +++ b/docs/pages/apis/result.mdx @@ -0,0 +1,52 @@ +--- +title: pg.Result +slug: /api/result +--- + +The `pg.Result` shape is returned for every successful query. + +
note: you cannot instantiate this directly
+ +## properties + +### `result.rows: Array` + +Every result will have a rows array. If no rows are returned the array will be empty. Otherwise the array will contain one item for each row returned from the query. By default node-postgres creates a map from the name to value of each column, giving you a json-like object back for each row. + +### `result.fields: Array` + +Every result will have a fields array. This array contains the `name` and `dataTypeID` of each field in the result. These fields are ordered in the same order as the columns if you are using `arrayMode` for the query: + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +const client = await pool.connect() +const result = await client.query({ + rowMode: 'array', + text: 'SELECT 1 as one, 2 as two;', +}) +console.log(result.fields[0].name) // one +console.log(result.fields[1].name) // two +console.log(result.rows) // [ [ 1, 2 ] ] +await client.end() +``` + +### `result.command: string` + +The command type last executed: `INSERT` `UPDATE` `CREATE` `SELECT` etc. + +### `result.rowCount: int` + +The number of rows processed by the last command. + +_note: this does not reflect the number of rows __returned__ from a query. e.g. an update statement could update many rows (so high `result.rowCount` value) but `result.rows.length` would be zero. To check for an empty query reponse on a `SELECT` query use `result.rows.length === 0`_. + +[@sehrope](https://github.com/brianc/node-postgres/issues/2182#issuecomment-620553915) has a good explanation: + +The `rowCount` is populated from the command tag supplied by the PostgreSQL server. It's generally of the form: `COMMAND [OID] [ROWS]` + +For DML commands (INSERT, UPDATE, etc), it reflects how many rows the server modified to process the command. For SELECT or COPY commands it reflects how many rows were retrieved or copied. More info on the specifics here: https://www.postgresql.org/docs/current/protocol-message-formats.html (search for CommandComplete for the message type) + +The note in the docs about the difference is because that value is controlled by the server. It's possible for a non-standard server (ex: PostgreSQL fork) or a server version in the future to provide different information in some situations so it'd be best not to rely on it to assume that the rows array length matches the `rowCount`. It's fine to use it for DML counts though. diff --git a/docs/pages/apis/types.mdx b/docs/pages/apis/types.mdx new file mode 100644 index 000000000..55f3b0009 --- /dev/null +++ b/docs/pages/apis/types.mdx @@ -0,0 +1,6 @@ +--- +title: Types +slug: /api/types +--- + +These docs are incomplete, for now please reference [pg-types docs](https://github.com/brianc/node-pg-types). diff --git a/docs/pages/features/_meta.json b/docs/pages/features/_meta.json new file mode 100644 index 000000000..a2f5e340a --- /dev/null +++ b/docs/pages/features/_meta.json @@ -0,0 +1,9 @@ +{ + "connecting": "Connecting", + "queries": "Queries", + "pooling": "Pooling", + "transactions": "Transactions", + "types": "Data Types", + "ssl": "SSL", + "native": "Native" +} diff --git a/docs/pages/features/connecting.mdx b/docs/pages/features/connecting.mdx new file mode 100644 index 000000000..b3c5ecc40 --- /dev/null +++ b/docs/pages/features/connecting.mdx @@ -0,0 +1,162 @@ +--- +title: Connecting +--- + +## Environment variables + +node-postgres uses the same [environment variables](https://www.postgresql.org/docs/9.1/static/libpq-envars.html) as libpq and psql to connect to a PostgreSQL server. Both individual clients & pools will use these environment variables. Here's a tiny program connecting node.js to the PostgreSQL server: + +```js +const { Pool, Client } = require('pg') + +// pools will use environment variables +// for connection information +const pool = new Pool() + +pool.query('SELECT NOW()', (err, res) => { + console.log(err, res) + pool.end() +}) + +// you can also use async/await +const res = await pool.query('SELECT NOW()') +await pool.end() + +// clients will also use environment variables +// for connection information +const client = new Client() +await client.connect() + +const res = await client.query('SELECT NOW()') +await client.end() +``` + +To run the above program and specify which database to connect to we can invoke it like so: + +```sh +$ PGUSER=dbuser \ + PGHOST=database.server.com \ + PGPASSWORD=secretpassword \ + PGDATABASE=mydb \ + PGPORT=3211 \ + node script.js +``` + +This allows us to write our programs without having to specify connection information in the program and lets us reuse them to connect to different databases without having to modify the code. + +The default values for the environment variables used are: + +``` +PGHOST=localhost +PGUSER=process.env.USER +PGDATABASE=process.env.USER +PGPASSWORD=null +PGPORT=5432 +``` + +## Programmatic + +node-postgres also supports configuring a pool or client programmatically with connection information. Here's our same script from above modified to use programmatic (hard-coded in this case) values. This can be useful if your application already has a way to manage config values or you don't want to use environment variables. + +```js +const { Pool, Client } = require('pg') + +const pool = new Pool({ + user: 'dbuser', + host: 'database.server.com', + database: 'mydb', + password: 'secretpassword', + port: 3211, +}) + +pool.query('SELECT NOW()', (err, res) => { + console.log(err, res) + pool.end() +}) + +const client = new Client({ + user: 'dbuser', + host: 'database.server.com', + database: 'mydb', + password: 'secretpassword', + port: 3211, +}) +client.connect() + +client.query('SELECT NOW()', (err, res) => { + console.log(err, res) + client.end() +}) +``` + +Many cloud providers include alternative methods for connecting to database instances using short-lived authentication tokens. node-postgres supports dynamic passwords via a callback function, either synchronous or asynchronous. The callback function must resolve to a string. + +```js +const { Pool } = require('pg') +const { RDS } = require('aws-sdk') + +const signerOptions = { + credentials: { + accessKeyId: 'YOUR-ACCESS-KEY', + secretAccessKey: 'YOUR-SECRET-ACCESS-KEY', + }, + region: 'us-east-1', + hostname: 'example.aslfdewrlk.us-east-1.rds.amazonaws.com', + port: 5432, + username: 'api-user', +} + +const signer = new RDS.Signer() + +const getPassword = () => signer.getAuthToken(signerOptions) + +const pool = new Pool({ + host: signerOptions.hostname, + port: signerOptions.port, + user: signerOptions.username, + database: 'my-db', + password: getPassword, +}) +``` + +### Unix Domain Sockets + +Connections to unix sockets can also be made. This can be useful on distros like Ubuntu, where authentication is managed via the socket connection instead of a password. + +```js +const { Client } = require('pg') +client = new Client({ + host: '/cloudsql/myproject:zone:mydb', + user: 'username', + password: 'password', + database: 'database_name', +}) +``` + +## Connection URI + +You can initialize both a pool and a client with a connection string URI as well. This is common in environments like Heroku where the database connection string is supplied to your application dyno through an environment variable. Connection string parsing brought to you by [pg-connection-string](https://github.com/iceddev/pg-connection-string). + +```js +const { Pool, Client } = require('pg') +const connectionString = 'postgresql://dbuser:secretpassword@database.server.com:3211/mydb' + +const pool = new Pool({ + connectionString, +}) + +pool.query('SELECT NOW()', (err, res) => { + console.log(err, res) + pool.end() +}) + +const client = new Client({ + connectionString, +}) +client.connect() + +client.query('SELECT NOW()', (err, res) => { + console.log(err, res) + client.end() +}) +``` diff --git a/docs/pages/features/native.mdx b/docs/pages/features/native.mdx new file mode 100644 index 000000000..698d6817b --- /dev/null +++ b/docs/pages/features/native.mdx @@ -0,0 +1,27 @@ +--- +title: Native Bindings +slug: /features/native +metaTitle: bar +--- + +Native bindings between node.js & [libpq](https://www.postgresql.org/docs/9.5/static/libpq.html) are provided by the [node-pg-native](https://github.com/brianc/node-pg-native) package. node-postgres can consume this package & use the native bindings to access the PostgreSQL server while giving you the same interface that is used with the JavaScript version of the library. + +To use the native bindings first you'll need to install them: + +```sh +$ npm install pg pg-native +``` + +Once `pg-native` is installed instead of requiring a `Client` or `Pool` constructor from `pg` you do the following: + +```js +const { Client, Pool } = require('pg').native +``` + +When you access the `.native` property on `require('pg')` it will automatically require the `pg-native` package and wrap it in the same API. + +
+ Care has been taken to normalize between the two, but there might still be edge cases where things behave subtly differently due to the nature of using libpq over handling the binary protocol directly in JavaScript, so it's recommended you chose to either use the JavaScript driver or the native bindings both in development and production. For what its worth: I use the pure JavaScript driver because the JavaScript driver is more portable (doesn't need a compiler), and the pure JavaScript driver is plenty fast. +
+ +Some of the modules using advanced features of PostgreSQL such as [pg-query-stream](https://github.com/brianc/node-pg-query-stream), [pg-cursor](https://github.com/brianc/node-pg-cursor),and [pg-copy-streams](https://github.com/brianc/node-pg-copy-streams) need to operate directly on the binary stream and therefore are incompatible with the native bindings. diff --git a/docs/pages/features/pooling.mdx b/docs/pages/features/pooling.mdx new file mode 100644 index 000000000..4719150be --- /dev/null +++ b/docs/pages/features/pooling.mdx @@ -0,0 +1,173 @@ +--- +title: Pooling +--- + +import { Alert } from '/components/alert.tsx' +import { Info } from '/components/info.tsx' + +If you're working on a web application or other software which makes frequent queries you'll want to use a connection pool. + +The easiest and by far most common way to use node-postgres is through a connection pool. + +## Why? + +- Connecting a new client to the PostgreSQL server requires a handshake which can take 20-30 milliseconds. During this time passwords are negotiated, SSL may be established, and configuration information is shared with the client & server. Incurring this cost _every time_ we want to execute a query would substantially slow down our application. + +- The PostgreSQL server can only handle a [limited number of clients at a time](https://wiki.postgresql.org/wiki/Number_Of_Database_Connections). Depending on the available memory of your PostgreSQL server you may even crash the server if you connect an unbounded number of clients. _note: I have crashed a large production PostgreSQL server instance in RDS by opening new clients and never disconnecting them in a python application long ago. It was not fun._ + +- PostgreSQL can only process one query at a time on a single connected client in a first-in first-out manner. If your multi-tenant web application is using only a single connected client all queries among all simultaneous requests will be pipelined and executed serially, one after the other. No good! + +### Good news + +node-postgres ships with built-in connection pooling via the [pg-pool](/api/pool) module. + +## Examples + +The client pool allows you to have a reusable pool of clients you can check out, use, and return. You generally want a limited number of these in your application and usually just 1. Creating an unbounded number of pools defeats the purpose of pooling at all. + +### Checkout, use, and return + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +// the pool will emit an error on behalf of any idle clients +// it contains if a backend error or network partition happens +pool.on('error', (err, client) => { + console.error('Unexpected error on idle client', err) + process.exit(-1) +}) + +// callback - checkout a client +pool.connect((err, client, done) => { + if (err) throw err + client.query('SELECT * FROM users WHERE id = $1', [1], (err, res) => { + done() + + if (err) { + console.log(err.stack) + } else { + console.log(res.rows[0]) + } + }) +}) + +// promise - checkout a client +pool.connect().then((client) => { + return client + .query('SELECT * FROM users WHERE id = $1', [1]) + .then((res) => { + client.release() + console.log(res.rows[0]) + }) + .catch((err) => { + client.release() + console.log(err.stack) + }) +}) + +// async/await - check out a client +;(async () => { + const client = await pool.connect() + try { + const res = await client.query('SELECT * FROM users WHERE id = $1', [1]) + console.log(res.rows[0]) + } catch (err) { + console.log(err.stack) + } finally { + client.release() + } +})() +``` + + +
+ You must always return the client to the pool if you successfully check it out, regardless of whether or not + there was an error with the queries you ran on the client. +
+ If you don't release the client your application will leak them and eventually your pool will be empty forever and all + future requests to check out a client from the pool will wait forever. +
+ +### Single query + +If you don't need a transaction or you just need to run a single query, the pool has a convenience method to run a query on any available client in the pool. This is the preferred way to query with node-postgres if you can as it removes the risk of leaking a client. + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +pool.query('SELECT * FROM users WHERE id = $1', [1], (err, res) => { + if (err) { + throw err + } + + console.log('user:', res.rows[0]) +}) +``` + +node-postgres also has built-in support for promises throughout all of its async APIs. + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +pool + .query('SELECT * FROM users WHERE id = $1', [1]) + .then((res) => console.log('user:', res.rows[0])) + .catch((err) => + setImmediate(() => { + throw err + }) + ) +``` + +Promises allow us to use `async`/`await` in node v8.0 and above (or earlier if you're using babel). + +```js +const { Pool } = require('pg') +const pool = new Pool() + +const { rows } = await pool.query('SELECT * FROM users WHERE id = $1', [1]) +console.log('user:', rows[0]) +``` + +### Shutdown + +To shut down a pool call `pool.end()` on the pool. This will wait for all checked-out clients to be returned and then shut down all the clients and the pool timers. + +```js +const { Pool } = require('pg') +const pool = new Pool() + +console.log('starting async query') +const result = await pool.query('SELECT NOW()') +console.log('async query finished') + +console.log('starting callback query') +pool.query('SELECT NOW()', (err, res) => { + console.log('callback query finished') +}) + +console.log('calling end') +await pool.end() +console.log('pool has drained') +``` + +The output of the above will be: + +``` +starting async query +async query finished +starting callback query +calling end +callback query finished +pool has drained +``` + + + The pool will return errors when attempting to check out a client after you've called pool.end() on the pool. + diff --git a/docs/pages/features/queries.mdx b/docs/pages/features/queries.mdx new file mode 100644 index 000000000..0deef0d0d --- /dev/null +++ b/docs/pages/features/queries.mdx @@ -0,0 +1,211 @@ +--- +title: Queries +slug: /features/queries +--- + +The api for executing queries supports both callbacks and promises. I'll provide an example for both _styles_ here. For the sake of brevity I am using the `client.query` method instead of the `pool.query` method - both methods support the same API. In fact, `pool.query` delegates directly to `client.query` internally. + +## Text only + +If your query has no parameters you do not need to include them to the query method: + +```js +// callback +client.query('SELECT NOW() as now', (err, res) => { + if (err) { + console.log(err.stack) + } else { + console.log(res.rows[0]) + } +}) + +// promise +client + .query('SELECT NOW() as now') + .then(res => console.log(res.rows[0])) + .catch(e => console.error(e.stack)) +``` + +## Parameterized query + +If you are passing parameters to your queries you will want to avoid string concatenating parameters into the query text directly. This can (and often does) lead to sql injection vulnerabilities. node-postgres supports parameterized queries, passing your query text _unaltered_ as well as your parameters to the PostgreSQL server where the parameters are safely substituted into the query with battle-tested parameter substitution code within the server itself. + +```js +const text = 'INSERT INTO users(name, email) VALUES($1, $2) RETURNING *' +const values = ['brianc', 'brian.m.carlson@gmail.com'] + +// callback +client.query(text, values, (err, res) => { + if (err) { + console.log(err.stack) + } else { + console.log(res.rows[0]) + // { name: 'brianc', email: 'brian.m.carlson@gmail.com' } + } +}) + +// promise +client + .query(text, values) + .then(res => { + console.log(res.rows[0]) + // { name: 'brianc', email: 'brian.m.carlson@gmail.com' } + }) + .catch(e => console.error(e.stack)) + +// async/await +try { + const res = await client.query(text, values) + console.log(res.rows[0]) + // { name: 'brianc', email: 'brian.m.carlson@gmail.com' } +} catch (err) { + console.log(err.stack) +} +``` + +
+ PostgreSQL does not support parameters for identifiers. If you need to have dynamic database, schema, table, or column names (e.g. in DDL statements) use pg-format package for handling escaping these values to ensure you do not have SQL injection! +
+ +Parameters passed as the second argument to `query()` will be converted to raw data types using the following rules: + +**null and undefined** + +If parameterizing `null` and `undefined` then both will be converted to `null`. + +**Date** + +Custom conversion to a UTC date string. + +**Buffer** + +Buffer instances are unchanged. + +**Array** + +Converted to a string that describes a Postgres array. Each array item is recursively converted using the rules described here. + +**Object** + +If a parameterized value has the method `toPostgres` then it will be called and its return value will be used in the query. +The signature of `toPostgres` is the following: + +``` +toPostgres (prepareValue: (value) => any): any +``` + +The `prepareValue` function provided can be used to convert nested types to raw data types suitable for the database. + +Otherwise if no `toPostgres` method is defined then `JSON.stringify` is called on the parameterized value. + +**Everything else** + +All other parameterized values will be converted by calling `value.toString` on the value. + +## Query config object + +`pool.query` and `client.query` both support taking a config object as an argument instead of taking a string and optional array of parameters. The same example above could also be performed like so: + +```js +const query = { + text: 'INSERT INTO users(name, email) VALUES($1, $2)', + values: ['brianc', 'brian.m.carlson@gmail.com'], +} + +// callback +client.query(query, (err, res) => { + if (err) { + console.log(err.stack) + } else { + console.log(res.rows[0]) + } +}) + +// promise +client + .query(query) + .then(res => console.log(res.rows[0])) + .catch(e => console.error(e.stack)) +``` + +The query config object allows for a few more advanced scenarios: + +### Prepared statements + +PostgreSQL has the concept of a [prepared statement](https://www.postgresql.org/docs/9.3/static/sql-prepare.html). node-postgres supports this by supplying a `name` parameter to the query config object. If you supply a `name` parameter the query execution plan will be cached on the PostgreSQL server on a **per connection basis**. This means if you use two different connections each will have to parse & plan the query once. node-postgres handles this transparently for you: a client only requests a query to be parsed the first time that particular client has seen that query name: + +```js +const query = { + // give the query a unique name + name: 'fetch-user', + text: 'SELECT * FROM user WHERE id = $1', + values: [1], +} + +// callback +client.query(query, (err, res) => { + if (err) { + console.log(err.stack) + } else { + console.log(res.rows[0]) + } +}) + +// promise +client + .query(query) + .then(res => console.log(res.rows[0])) + .catch(e => console.error(e.stack)) +``` + +In the above example the first time the client sees a query with the name `'fetch-user'` it will send a 'parse' request to the PostgreSQL server & execute the query as normal. The second time, it will skip the 'parse' request and send the _name_ of the query to the PostgreSQL server. + +
+
+Be careful not to fall into the trap of premature optimization. Most of your queries will likely not benefit much, if at all, from using prepared statements. This is a somewhat "power user" feature of PostgreSQL that is best used when you know how to use it - namely with very complex queries with lots of joins and advanced operations like union and switch statements. I rarely use this feature in my own apps unless writing complex aggregate queries for reports and I know the reports are going to be executed very frequently. +
+
+ +### Row mode + +By default node-postgres reads rows and collects them into JavaScript objects with the keys matching the column names and the values matching the corresponding row value for each column. If you do not need or do not want this behavior you can pass `rowMode: 'array'` to a query object. This will inform the result parser to bypass collecting rows into a JavaScript object, and instead will return each row as an array of values. + +```js +const query = { + text: 'SELECT $1::text as first_name, $2::text as last_name', + values: ['Brian', 'Carlson'], + rowMode: 'array', +} + +// callback +client.query(query, (err, res) => { + if (err) { + console.log(err.stack) + } else { + console.log(res.fields.map(field => field.name)) // ['first_name', 'last_name'] + console.log(res.rows[0]) // ['Brian', 'Carlson'] + } +}) + +// promise +client + .query(query) + .then(res => { + console.log(res.fields.map(field => field.name)) // ['first_name', 'last_name'] + console.log(res.rows[0]) // ['Brian', 'Carlson'] + }) + .catch(e => console.error(e.stack)) +``` + +### Types + +You can pass in a custom set of type parsers to use when parsing the results of a particular query. The `types` property must conform to the [Types](/api/types) API. Here is an example in which every value is returned as a string: + +```js +const query = { + text: 'SELECT * from some_table', + types: { + getTypeParser: () => val => val, + }, +} +``` diff --git a/docs/pages/features/ssl.mdx b/docs/pages/features/ssl.mdx new file mode 100644 index 000000000..0428d0549 --- /dev/null +++ b/docs/pages/features/ssl.mdx @@ -0,0 +1,61 @@ +--- +title: SSL +slug: /features/ssl +--- + +node-postgres supports TLS/SSL connections to your PostgreSQL server as long as the server is configured to support it. When instantiating a pool or a client you can provide an `ssl` property on the config object and it will be passed to the constructor for the [node TLSSocket](https://nodejs.org/api/tls.html#tls_class_tls_tlssocket). + +## Self-signed cert + +Here's an example of a configuration you can use to connect a client or a pool to a PostgreSQL server. + +```js +const config = { + database: 'database-name', + host: 'host-or-ip', + // this object will be passed to the TLSSocket constructor + ssl: { + rejectUnauthorized: false, + ca: fs.readFileSync('/path/to/server-certificates/root.crt').toString(), + key: fs.readFileSync('/path/to/client-key/postgresql.key').toString(), + cert: fs.readFileSync('/path/to/client-certificates/postgresql.crt').toString(), + }, +} + +import { Client, Pool } from 'pg' + +const client = new Client(config) +client.connect(err => { + if (err) { + console.error('error connecting', err.stack) + } else { + console.log('connected') + client.end() + } +}) + +const pool = new Pool(config) +pool + .connect() + .then(client => { + console.log('connected') + client.release() + }) + .catch(err => console.error('error connecting', err.stack)) + .then(() => pool.end()) +``` + +## Usage with `connectionString` + +If you plan to use a combination of a database connection string from the environment and SSL settings in the config object directly, then you must avoid including any of `sslcert`, `sslkey`, `sslrootcert`, or `sslmode` in the connection string. If any of these options are used then the `ssl` object is replaced and any additional options provided there will be lost. + +```js +const config = { + connectionString: 'postgres://user:password@host:port/db?sslmode=require', + // Beware! The ssl object is overwritten when parsing the connectionString + ssl: { + rejectUnauthorized: false, + ca: fs.readFileSync('/path/to/server-certificates/root.crt').toString(), + }, +} +``` diff --git a/docs/pages/features/transactions.mdx b/docs/pages/features/transactions.mdx new file mode 100644 index 000000000..408db52f8 --- /dev/null +++ b/docs/pages/features/transactions.mdx @@ -0,0 +1,93 @@ +--- +title: Transactions +--- + +import { Alert } from '/components/alert.tsx' + +To execute a transaction with node-postgres you simply execute `BEGIN / COMMIT / ROLLBACK` queries yourself through a client. Because node-postgres strives to be low level and un-opinionated, it doesn't provide any higher level abstractions specifically around transactions. + + + You must use the same client instance for all statements within a transaction. PostgreSQL + isolates a transaction to individual clients. This means if you initialize or use transactions with the{' '} + pool.query method you will have problems. Do not use transactions with + the pool.query method. + + +## Examples + +### async/await + +Things are considerably more straightforward if you're using async/await: + +```js +const { Pool } = require('pg') +const pool = new Pool() + +// note: we don't try/catch this because if connecting throws an exception +// we don't need to dispose of the client (it will be undefined) +const client = await pool.connect() + +try { + await client.query('BEGIN') + const queryText = 'INSERT INTO users(name) VALUES($1) RETURNING id' + const res = await client.query(queryText, ['brianc']) + + const insertPhotoText = 'INSERT INTO photos(user_id, photo_url) VALUES ($1, $2)' + const insertPhotoValues = [res.rows[0].id, 's3.bucket.foo'] + await client.query(insertPhotoText, insertPhotoValues) + await client.query('COMMIT') +} catch (e) { + await client.query('ROLLBACK') + throw e +} finally { + client.release() +} +``` + +### callbacks + +node-postgres is a very old library, and still has an optional callback API. Here's an example of doing the same code above, but with callbacks: + +```js +const { Pool } = require('pg') +const pool = new Pool() + +pool.connect((err, client, done) => { + const shouldAbort = (err) => { + if (err) { + console.error('Error in transaction', err.stack) + client.query('ROLLBACK', (err) => { + if (err) { + console.error('Error rolling back client', err.stack) + } + // release the client back to the pool + done() + }) + } + return !!err + } + + client.query('BEGIN', (err) => { + if (shouldAbort(err)) return + const queryText = 'INSERT INTO users(name) VALUES($1) RETURNING id' + client.query(queryText, ['brianc'], (err, res) => { + if (shouldAbort(err)) return + + const insertPhotoText = 'INSERT INTO photos(user_id, photo_url) VALUES ($1, $2)' + const insertPhotoValues = [res.rows[0].id, 's3.bucket.foo'] + client.query(insertPhotoText, insertPhotoValues, (err, res) => { + if (shouldAbort(err)) return + + client.query('COMMIT', (err) => { + if (err) { + console.error('Error committing transaction', err.stack) + } + done() + }) + }) + }) + }) +}) +``` + +..thank goodness for `async/await` yeah? diff --git a/docs/pages/features/types.mdx b/docs/pages/features/types.mdx new file mode 100644 index 000000000..65c814bae --- /dev/null +++ b/docs/pages/features/types.mdx @@ -0,0 +1,106 @@ +--- +title: Data Types +--- + +import { Alert } from '/components/alert.tsx' + +PostgreSQL has a rich system of supported [data types](https://www.postgresql.org/docs/9.5/static/datatype.html). node-postgres does its best to support the most common data types out of the box and supplies an extensible type parser to allow for custom type serialization and parsing. + +## strings by default + +node-postgres will convert a database type to a JavaScript string if it doesn't have a registered type parser for the database type. Furthermore, you can send any type to the PostgreSQL server as a string and node-postgres will pass it through without modifying it in any way. To circumvent the type parsing completely do something like the following. + +```js +const queryText = 'SELECT int_col::text, date_col::text, json_col::text FROM my_table' +const result = await client.query(queryText) + +console.log(result.rows[0]) // will contain the unparsed string value of each column +``` + +## type parsing examples + +### uuid + json / jsonb + +There is no data type in JavaScript for a uuid/guid so node-postgres converts a uuid to a string. JavaScript has great support for JSON and node-postgres converts json/jsonb objects directly into their JavaScript object via [`JSON.parse`](https://github.com/brianc/node-pg-types/blob/master/lib/textParsers.js#L193). Likewise sending an object to the PostgreSQL server via a query from node-postgres, node-posgres will call [`JSON.stringify`](https://github.com/brianc/node-postgres/blob/e5f0e5d36a91a72dda93c74388ac890fa42b3be0/lib/utils.js#L47) on your outbound value, automatically converting it to json for the server. + +```js +const createTableText = ` +CREATE EXTENSION IF NOT EXISTS "pgcrypto"; + +CREATE TEMP TABLE IF NOT EXISTS users ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + data JSONB +); +` +// create our temp table +await client.query(createTableText) + +const newUser = { email: 'brian.m.carlson@gmail.com' } +// create a new user +await client.query('INSERT INTO users(data) VALUES($1)', [newUser]) + +const { rows } = await client.query('SELECT * FROM users') + +console.log(rows) +/* +output: +[{ + id: 'd70195fd-608e-42dc-b0f5-eee975a621e9', + data: { email: 'brian.m.carlson@gmail.com' } +}] +*/ +``` + +### date / timestamp / timestamptz + +node-postgres will convert instances of JavaScript date objects into the expected input value for your PostgreSQL server. Likewise, when reading a `date`, `timestamp`, or `timestamptz` column value back into JavaScript, node-postgres will parse the value into an instance of a JavaScript `Date` object. + +```js +const createTableText = ` +CREATE TEMP TABLE dates( + date_col DATE, + timestamp_col TIMESTAMP, + timestamptz_col TIMESTAMPTZ +); +` +// create our temp table +await client.query(createTableText) + +// insert the current time into it +const now = new Date() +const insertText = 'INSERT INTO dates(date_col, timestamp_col, timestamptz_col) VALUES ($1, $2, $3)' +await client.query(insertText, [now, now, now]) + +// read the row back out +const result = await client.query('SELECT * FROM dates') + +console.log(result.rows) +// { +// date_col: 2017-05-29T05:00:00.000Z, +// timestamp_col: 2017-05-29T23:18:13.263Z, +// timestamptz_col: 2017-05-29T23:18:13.263Z +// } +``` + +psql output: + +``` +bmc=# select * from dates; + date_col | timestamp_col | timestamptz_col +------------+-------------------------+---------------------------- + 2017-05-29 | 2017-05-29 18:18:13.263 | 2017-05-29 18:18:13.263-05 +(1 row) +``` + +node-postgres converts `DATE` and `TIMESTAMP` columns into the **local** time of the node process set at `process.env.TZ`. + +_note: I generally use `TIMESTAMPTZ` when storing dates; otherwise, inserting a time from a process in one timezone and reading it out in a process in another timezone can cause unexpected differences in the time._ + + +
+ Although PostgreSQL supports microseconds in dates, JavaScript only supports dates to the millisecond precision. + Keep this in mind when you send dates to and from PostgreSQL from node: your microseconds will be truncated when + converting to a JavaScript date object even if they exist in the database. If you need to preserve them, I recommend + using a custom type parser. +
+
diff --git a/docs/pages/guides/_meta.json b/docs/pages/guides/_meta.json new file mode 100644 index 000000000..3889a0992 --- /dev/null +++ b/docs/pages/guides/_meta.json @@ -0,0 +1,5 @@ +{ + "project-structure": "Suggested Code Structure", + "async-express": "Express with Async/Await", + "upgrading": "Upgrading" +} diff --git a/docs/pages/guides/async-express.md b/docs/pages/guides/async-express.md new file mode 100644 index 000000000..3be6d955a --- /dev/null +++ b/docs/pages/guides/async-express.md @@ -0,0 +1,83 @@ +--- +title: Express with async/await +--- + +My preferred way to use node-postgres (and all async code in node.js) is with `async/await`. I find it makes reasoning about control-flow easier and allows me to write more concise and maintainable code. + +This is how I typically structure express web-applications with node-postgres to use `async/await`: + +``` +- app.js +- index.js +- routes/ + - index.js + - photos.js + - user.js +- db/ + - index.js <--- this is where I put data access code +``` + +That's the same structure I used in the [project structure](/guides/project-structure) example. + +My `db/index.js` file usually starts out like this: + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +module.exports = { + query: (text, params) => pool.query(text, params), +} +``` + +Then I will install [express-promise-router](https://www.npmjs.com/package/express-promise-router) and use it to define my routes. Here is my `routes/user.js` file: + +```js +const Router = require('express-promise-router') + +const db = require('../db') + +// create a new express-promise-router +// this has the same API as the normal express router except +// it allows you to use async functions as route handlers +const router = new Router() + +// export our router to be mounted by the parent application +module.exports = router + +router.get('/:id', async (req, res) => { + const { id } = req.params + const { rows } = await db.query('SELECT * FROM users WHERE id = $1', [id]) + res.send(rows[0]) +}) +``` + +Then in my `routes/index.js` file I'll have something like this which mounts each individual router into the main application: + +```js +// ./routes/index.js +const users = require('./user') +const photos = require('./photos') + +module.exports = (app) => { + app.use('/users', users) + app.use('/photos', photos) + // etc.. +} +``` + +And finally in my `app.js` file where I bootstrap express I will have my `routes/index.js` file mount all my routes. The routes know they're using async functions but because of express-promise-router the main express app doesn't know and doesn't care! + +```js +// ./app.js +const express = require('express') +const mountRoutes = require('./routes') + +const app = express() +mountRoutes(app) + +// ... more express setup stuff can follow +``` + +Now you've got `async/await`, node-postgres, and express all working together! diff --git a/docs/pages/guides/project-structure.md b/docs/pages/guides/project-structure.md new file mode 100644 index 000000000..742451daa --- /dev/null +++ b/docs/pages/guides/project-structure.md @@ -0,0 +1,197 @@ +--- +title: Suggested Project Structure +--- + +Whenever I am writing a project & using node-postgres I like to create a file within it and make all interactions with the database go through this file. This serves a few purposes: + +- Allows my project to adjust to any changes to the node-postgres API without having to trace down all the places I directly use node-postgres in my application. +- Allows me to have a single place to put logging and diagnostics around my database. +- Allows me to make custom extensions to my database access code & share it throughout the project. +- Allows a single place to bootstrap & configure the database. + +## example + +_note: I am using callbacks in this example to introduce as few concepts as possible at a time, but the same is doable with promises or async/await_ + +The location doesn't really matter - I've found it usually ends up being somewhat app specific and in line with whatever folder structure conventions you're using. For this example I'll use an express app structured like so: + +``` +- app.js +- index.js +- routes/ + - index.js + - photos.js + - user.js +- db/ + - index.js <--- this is where I put data access code +``` + +Typically I'll start out my `db/index.js` file like so: + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +module.exports = { + query: (text, params, callback) => { + return pool.query(text, params, callback) + }, +} +``` + +That's it. But now everywhere else in my application instead of requiring `pg` directly, I'll require this file. Here's an example of a route within `routes/user.js`: + +```js +// notice here I'm requiring my database adapter file +// and not requiring node-postgres directly +const db = require('../db') + +app.get('/:id', (req, res, next) => { + db.query('SELECT * FROM users WHERE id = $1', [req.params.id], (err, result) => { + if (err) { + return next(err) + } + res.send(result.rows[0]) + }) +}) + +// ... many other routes in this file +``` + +Imagine we have lots of routes scattered throughout many files under our `routes/` directory. We now want to go back and log every single query that's executed, how long it took, and the number of rows it returned. If we had required node-postgres directly in every route file we'd have to go edit every single route - that would take forever & be really error prone! But thankfully we put our data access into `db/index.js`. Let's go add some logging: + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +module.exports = { + query: (text, params, callback) => { + const start = Date.now() + return pool.query(text, params, (err, res) => { + const duration = Date.now() - start + console.log('executed query', { text, duration, rows: res.rowCount }) + callback(err, res) + }) + }, +} +``` + +That was pretty quick! And now all of our queries everywhere in our application are being logged. + +_note: I didn't log the query parameters. Depending on your application you might be storing encrypted passwords or other sensitive information in your database. If you log your query parameters you might accidentally log sensitive information. Every app is different though so do what suits you best!_ + +Now what if we need to check out a client from the pool to run several queries in a row in a transaction? We can add another method to our `db/index.js` file when we need to do this: + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +module.exports = { + query: (text, params, callback) => { + const start = Date.now() + return pool.query(text, params, (err, res) => { + const duration = Date.now() - start + console.log('executed query', { text, duration, rows: res.rowCount }) + callback(err, res) + }) + }, + getClient: (callback) => { + pool.connect((err, client, done) => { + callback(err, client, done) + }) + }, +} +``` + +Okay. Great - the simplest thing that could possibly work. It seems like one of our routes that checks out a client to run a transaction is forgetting to call `done` in some situation! Oh no! We are leaking a client & have hundreds of these routes to go audit. Good thing we have all our client access going through this single file. Lets add some deeper diagnostic information here to help us track down where the client leak is happening. + +```js +const { Pool } = require('pg') + +const pool = new Pool() + +module.exports = { + query: (text, params, callback) => { + const start = Date.now() + return pool.query(text, params, (err, res) => { + const duration = Date.now() - start + console.log('executed query', { text, duration, rows: res.rowCount }) + callback(err, res) + }) + }, + getClient: (callback) => { + pool.connect((err, client, done) => { + const query = client.query + + // monkey patch the query method to keep track of the last query executed + client.query = (...args) => { + client.lastQuery = args + return query.apply(client, args) + } + + // set a timeout of 5 seconds, after which we will log this client's last query + const timeout = setTimeout(() => { + console.error('A client has been checked out for more than 5 seconds!') + console.error(`The last executed query on this client was: ${client.lastQuery}`) + }, 5000) + + const release = (err) => { + // call the actual 'done' method, returning this client to the pool + done(err) + + // clear our timeout + clearTimeout(timeout) + + // set the query method back to its old un-monkey-patched version + client.query = query + } + + callback(err, client, release) + }) + }, +} +``` + +Using async/await: + +```js +module.exports = { + async query(text, params) { + const start = Date.now() + const res = await pool.query(text, params) + const duration = Date.now() - start + console.log('executed query', { text, duration, rows: res.rowCount }) + return res + }, + + async getClient() { + const client = await pool.connect() + const query = client.query + const release = client.release + // set a timeout of 5 seconds, after which we will log this client's last query + const timeout = setTimeout(() => { + console.error('A client has been checked out for more than 5 seconds!') + console.error(`The last executed query on this client was: ${client.lastQuery}`) + }, 5000) + // monkey patch the query method to keep track of the last query executed + client.query = (...args) => { + client.lastQuery = args + return query.apply(client, args) + } + client.release = () => { + // clear our timeout + clearTimeout(timeout) + // set the methods back to their old un-monkey-patched version + client.query = query + client.release = release + return release.apply(client) + } + return client + }, +} +``` + +That should hopefully give us enough diagnostic information to track down any leaks. diff --git a/docs/pages/guides/upgrading.md b/docs/pages/guides/upgrading.md new file mode 100644 index 000000000..2a1d311a2 --- /dev/null +++ b/docs/pages/guides/upgrading.md @@ -0,0 +1,114 @@ +--- +title: Upgrading +slug: /guides/upgrading +--- + +# Upgrading to 8.0 + +node-postgres at 8.0 introduces a breaking change to ssl-verified connections. If you connect with ssl and use + +``` +const client = new Client({ ssl: true }) +``` + +and the server's SSL certificate is self-signed, connections will fail as of node-postgres 8.0. To keep the existing behavior, modify the invocation to + +``` +const client = new Client({ ssl: { rejectUnauthorized: false } }) +``` + +The rest of the changes are relatively minor and unlikely to cause issues; see [the announcement](/announcements#2020-02-25) for full details. + +# Upgrading to 7.0 + +node-postgres at 7.0 introduces somewhat significant breaking changes to the public API. + +## node version support + +Starting with `pg@7.0` the earliest version of node supported will be `node@4.x LTS`. Support for `node@0.12.x` and `node@.10.x` is dropped, and the module wont work as it relies on new es6 features not available in older versions of node. + +## pg singleton + +In the past there was a singleton pool manager attached to the root `pg` object in the package. This singleton could be used to provision connection pools automatically by calling `pg.connect`. This API caused a lot of confusion for users. It also introduced a opaque module-managed singleton which was difficult to reason about, debug, error-prone, and inflexible. Starting in pg@6.0 the methods' documentation was removed, and starting in pg@6.3 the methods were deprecated with a warning message. + +If your application still relies on these they will be _gone_ in `pg@7.0`. In order to migrate you can do the following: + +```js +// old way, deprecated in 6.3.0: + +// connection using global singleton +pg.connect(function(err, client, done) { + client.query(/* etc, etc */) + done() +}) + +// singleton pool shutdown +pg.end() + +// ------------------ + +// new way, available since 6.0.0: + +// create a pool +var pool = new pg.Pool() + +// connection using created pool +pool.connect(function(err, client, done) { + client.query(/* etc, etc */) + done() +}) + +// pool shutdown +pool.end() +``` + +node-postgres ships with a built-in pool object provided by [pg-pool](https://github.com/brianc/node-pg-pool) which is already used internally by the `pg.connect` and `pg.end` methods. Migrating to a user-managed pool (or set of pools) allows you to more directly control their set up their life-cycle. + +## client.query(...).on + +Before `pg@7.0` the `client.query` method would _always_ return an instance of a query. The query instance was an event emitter, accepted a callback, and was also a promise. A few problems... + +- too many flow control options on a single object was confusing +- event emitter `.on('error')` does not mix well with promise `.catch` +- the `row` event was a common source of errors: it looks like a stream but has no support for back-pressure, misleading users into trying to pipe results or handling them in the event emitter for a desired performance gain. +- error handling with a `.done` and `.error` emitter pair for every query is cumbersome and returning the emitter from `client.query` indicated this sort of pattern may be encouraged: it is not. + +Starting with `pg@7.0` the return value `client.query` will be dependent on what you pass to the method: I think this aligns more with how most node libraries handle the callback/promise combo, and I hope it will make the "just works" :tm: feeling better while reducing surface area and surprises around event emitter / callback combos. + +### client.query with a callback + +```js +const query = client.query('SELECT NOW()', (err, res) => { + /* etc, etc */ +}) +assert(query === undefined) // true +``` + +If you pass a callback to the method `client.query` will return `undefined`. This limits flow control to the callback which is in-line with almost all of node's core APIs. + +### client.query without a callback + +```js +const query = client.query('SELECT NOW()') +assert(query instanceof Promise) // true +assert(query.on === undefined) // true +query.then((res) => /* etc, etc */) +``` + +If you do **not** pass a callback `client.query` will return an instance of a `Promise`. This will **not** be a query instance and will not be an event emitter. This is in line with how most promise-based APIs work in node. + +### client.query(Submittable) + +`client.query` has always accepted any object that has a `.submit` method on it. In this scenario the client calls `.submit` on the object, delegating execution responsibility to it. In this situation the client also **returns the instance it was passed**. This is how [pg-cursor](https://github.com/brianc/node-pg-cursor) and [pg-query-stream](https://github.com/brianc/node-pg-query-stream) work. So, if you need the event emitter functionality on your queries for some reason, it is still possible because `Query` is an instance of `Submittable`: + +```js +const { Client, Query } = require('pg') +const query = client.query(new Query('SELECT NOW()')) +query.on('row', row => {}) +query.on('end', res => {}) +query.on('error', res => {}) +``` + +`Query` is considered a public, documented part of the API of node-postgres and this form will be supported indefinitely. + +_note: I have been building apps with node-postgres for almost 7 years. In that time I have never used the event emitter API as the primary way to execute queries. I used to use callbacks and now I use async/await. If you need to stream results I highly recommend you use [pg-cursor](https://github.com/brianc/node-pg-cursor) or [pg-query-stream](https://github.com/brianc/node-pg-query-stream) and **not** the query object as an event emitter._ diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx new file mode 100644 index 000000000..234cf11e1 --- /dev/null +++ b/docs/pages/index.mdx @@ -0,0 +1,65 @@ +--- +title: Welcome +slug: / +--- + +node-postgres is a collection of node.js modules for interfacing with your PostgreSQL database. It has support for callbacks, promises, async/await, connection pooling, prepared statements, cursors, streaming results, C/C++ bindings, rich type parsing, and more! Just like PostgreSQL itself there are a lot of features: this documentation aims to get you up and running quickly and in the right direction. It also tries to provide guides for more advanced & edge-case topics allowing you to tap into the full power of PostgreSQL from node.js. + +## Install + +```bash +$ npm install pg +``` + +## Supporters + +node-postgres continued development and support is made possible by the many [supporters](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) with a special thanks to our featured supporters: + +
+
+ + crate.io + +
+
+ + eaze.com + +
+
+ +If you or your company would like to sponsor node-postgres stop by [github sponsors](https://github.com/sponsors/brianc) and sign up or feel free to [email me](mailto:brian@pecanware.com) if you want to add your logo to the documentation or discuss higher tiers of sponsorship! + +# Version compatibility + +node-postgres strives to be compatible with all recent lts versions of node & the most recent "stable" version. At the time of this writing node-postgres is compatible with node 8.x, 10.x, 12.x and 14.x To use node >= 14.x you will need to install `pg@8.2.x` or later due to some internal stream changes on the node 14 branch. Dropping support for an old node lts version will always be considered a breaking change in node-postgres and will be done on _major_ version number changes only, and we will try to keep support for 8.x for as long as reasonably possible. + +## Getting started + +This is the simplest possible way to connect, query, and disconnect with async/await: + +```js +const { Client } = require('pg') +const client = new Client() +await client.connect() + +const res = await client.query('SELECT $1::text as message', ['Hello world!']) +console.log(res.rows[0].message) // Hello world! +await client.end() +``` + +And here's the same thing with callbacks: + +```js +const { Client } = require('pg') +const client = new Client() + +client.connect() + +client.query('SELECT $1::text as message', ['Hello world!'], (err, res) => { + console.log(err ? err.stack : res.rows[0].message) // Hello World! + client.end() +}) +``` + +Our real-world apps are almost always more complicated than that, and I urge you to read on! diff --git a/docs/theme.config.js b/docs/theme.config.js new file mode 100644 index 000000000..1ec4941ad --- /dev/null +++ b/docs/theme.config.js @@ -0,0 +1,27 @@ +// theme.config.js +export default { + projectLink: 'https://github.com/brianc/node-postgres', // GitHub link in the navbar + docsRepositoryBase: 'https://github.com/brianc/node-postgres/blob/master', // base URL for the docs repository + titleSuffix: ' – node-postgres', + nextLinks: true, + prevLinks: true, + search: true, + customSearch: null, // customizable, you can use algolia for example + darkMode: true, + footer: true, + footerText: `MIT ${new Date().getFullYear()} © Brian Carlson.`, + footerEditLink: `Edit this page on GitHub`, + logo: ( + <> + ... + Next.js Static Site Generator + + ), + head: ( + <> + + + + + ), +} diff --git a/docs/yarn.lock b/docs/yarn.lock new file mode 100644 index 000000000..aa2c18408 --- /dev/null +++ b/docs/yarn.lock @@ -0,0 +1,1892 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/runtime@^7.12.5": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.0.tgz#22b11c037b094d27a8a2504ea4dcff00f50e2259" + integrity sha512-eR8Lo9hnDS7tqkO7NsV+mKvCmv5boaXFSZ70DnfhcgiEne8hv9oCEd36Klw74EtizEqLsy4YnW8UWwpBVolHZA== + dependencies: + regenerator-runtime "^0.13.4" + +"@headlessui/react@^1.6.6": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.2.tgz#e6a6a8d38342064a53182f1eb2bf6d9c1e53ba6a" + integrity sha512-snLv2lxwsf2HNTOBNgHYdvoYZ3ChJE8QszPi1d/hl9js8KrFrUulTaQBfSyPbJP5BybVreWh9DxCgz9S0Z6hKQ== + +"@mdx-js/mdx@^2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-2.1.3.tgz#d5821920ebe546b45192f4c7a64dcc68a658f7f9" + integrity sha512-ahbb47HJIJ4xnifaL06tDJiSyLEy1EhFAStO7RZIm3GTa7yGW3NGhZaj+GUCveFgl5oI54pY4BgiLmYm97y+zg== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/mdx" "^2.0.0" + estree-util-build-jsx "^2.0.0" + estree-util-is-identifier-name "^2.0.0" + estree-util-to-js "^1.1.0" + estree-walker "^3.0.0" + hast-util-to-estree "^2.0.0" + markdown-extensions "^1.0.0" + periscopic "^3.0.0" + remark-mdx "^2.0.0" + remark-parse "^10.0.0" + remark-rehype "^10.0.0" + unified "^10.0.0" + unist-util-position-from-estree "^1.0.0" + unist-util-stringify-position "^3.0.0" + unist-util-visit "^4.0.0" + vfile "^5.0.0" + +"@mdx-js/react@^2.1.2": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-2.1.3.tgz#4b28a774295ed1398cf6be1b8ddef69d6a30e78d" + integrity sha512-11n4lTvvRyxq3OYbWJwEYM+7q6PE0GxKbk0AwYIIQmrRkxDeljIsjDQkKOgdr/orgRRbYy5zi+iERdnwe01CHQ== + dependencies: + "@types/mdx" "^2.0.0" + "@types/react" ">=16" + +"@napi-rs/simple-git-android-arm-eabi@0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-android-arm-eabi/-/simple-git-android-arm-eabi-0.1.8.tgz#303bea1ec00db24466e3b3ba13de337d87c5371b" + integrity sha512-JJCejHBB1G6O8nxjQLT4quWCcvLpC3oRdJJ9G3MFYSCoYS8i1bWCWeU+K7Br+xT+D6s1t9q8kNJAwJv9Ygpi0g== + +"@napi-rs/simple-git-android-arm64@0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-android-arm64/-/simple-git-android-arm64-0.1.8.tgz#42c8d04287364fd1619002629fa52183dcf462ee" + integrity sha512-mraHzwWBw3tdRetNOS5KnFSjvdAbNBnjFLA8I4PwTCPJj3Q4txrigcPp2d59cJ0TC51xpnPXnZjYdNwwSI9g6g== + +"@napi-rs/simple-git-darwin-arm64@0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-darwin-arm64/-/simple-git-darwin-arm64-0.1.8.tgz#e210808e6d646d6efecea84c67ced8eb44a8f821" + integrity sha512-ufy/36eI/j4UskEuvqSH7uXtp3oXeLDmjQCfKJz3u5Vx98KmOMKrqAm2H81AB2WOtCo5mqS6PbBeUXR8BJX8lQ== + +"@napi-rs/simple-git-darwin-x64@0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-darwin-x64/-/simple-git-darwin-x64-0.1.8.tgz#d717525c33e0dfd8a6d6215da2fcbc0ad40011e1" + integrity sha512-Vb21U+v3tPJNl+8JtIHHT8HGe6WZ8o1Tq3f6p+Jx9Cz71zEbcIiB9FCEMY1knS/jwQEOuhhlI9Qk7d4HY+rprA== + +"@napi-rs/simple-git-linux-arm-gnueabihf@0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-arm-gnueabihf/-/simple-git-linux-arm-gnueabihf-0.1.8.tgz#03e7b2dd299c10e61bbf29f405ea74f6571cf6a1" + integrity sha512-6BPTJ7CzpSm2t54mRLVaUr3S7ORJfVJoCk2rQ8v8oDg0XAMKvmQQxOsAgqKBo9gYNHJnqrOx3AEuEgvB586BuQ== + +"@napi-rs/simple-git-linux-arm64-gnu@0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-arm64-gnu/-/simple-git-linux-arm64-gnu-0.1.8.tgz#945123f75c9a36fd0364e789ce06cd29a74a43cc" + integrity sha512-qfESqUCAA/XoQpRXHptSQ8gIFnETCQt1zY9VOkplx6tgYk9PCeaX4B1Xuzrh3eZamSCMJFn+1YB9Ut8NwyGgAA== + +"@napi-rs/simple-git-linux-arm64-musl@0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-arm64-musl/-/simple-git-linux-arm64-musl-0.1.8.tgz#2c20a0bff7c08f60b033ed7056dcb07bbbff8310" + integrity sha512-G80BQPpaRmQpn8dJGHp4I2/YVhWDUNJwcCrJAtAdbKFDCMyCHJBln2ERL/+IEUlIAT05zK/c1Z5WEprvXEdXow== + +"@napi-rs/simple-git-linux-x64-gnu@0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-x64-gnu/-/simple-git-linux-x64-gnu-0.1.8.tgz#980e22b7376252a0767298ec801d374d97553da1" + integrity sha512-NI6o1sZYEf6vPtNWJAm9w8BxJt+LlSFW0liSjYe3lc3e4dhMfV240f0ALeqlwdIldRPaDFwZSJX5/QbS7nMzhw== + +"@napi-rs/simple-git-linux-x64-musl@0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-linux-x64-musl/-/simple-git-linux-x64-musl-0.1.8.tgz#edca3b2833dc5d3fc9151f5b931f7b14478ccca4" + integrity sha512-wljGAEOW41er45VTiU8kXJmO480pQKzsgRCvPlJJSCaEVBbmo6XXbFIXnZy1a2J3Zyy2IOsRB4PVkUZaNuPkZQ== + +"@napi-rs/simple-git-win32-arm64-msvc@0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-win32-arm64-msvc/-/simple-git-win32-arm64-msvc-0.1.8.tgz#3ac4c7fe816a2cdafabd091ded76161d1ba1fe88" + integrity sha512-QuV4QILyKPfbWHoQKrhXqjiCClx0SxbCTVogkR89BwivekqJMd9UlMxZdoCmwLWutRx4z9KmzQqokvYI5QeepA== + +"@napi-rs/simple-git-win32-x64-msvc@0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git-win32-x64-msvc/-/simple-git-win32-x64-msvc-0.1.8.tgz#3b825bc2cb1c7ff535a3ca03768142d68bbf5c19" + integrity sha512-UzNS4JtjhZhZ5hRLq7BIUq+4JOwt1ThIKv11CsF1ag2l99f0123XvfEpjczKTaa94nHtjXYc2Mv9TjccBqYOew== + +"@napi-rs/simple-git@^0.1.8": + version "0.1.8" + resolved "https://registry.yarnpkg.com/@napi-rs/simple-git/-/simple-git-0.1.8.tgz#391cb58436d50bd32d924611d45bdc41f5e7607a" + integrity sha512-BvOMdkkofTz6lEE35itJ/laUokPhr/5ToMGlOH25YnhLD2yN1KpRAT4blW9tT8281/1aZjW3xyi73bs//IrDKA== + optionalDependencies: + "@napi-rs/simple-git-android-arm-eabi" "0.1.8" + "@napi-rs/simple-git-android-arm64" "0.1.8" + "@napi-rs/simple-git-darwin-arm64" "0.1.8" + "@napi-rs/simple-git-darwin-x64" "0.1.8" + "@napi-rs/simple-git-linux-arm-gnueabihf" "0.1.8" + "@napi-rs/simple-git-linux-arm64-gnu" "0.1.8" + "@napi-rs/simple-git-linux-arm64-musl" "0.1.8" + "@napi-rs/simple-git-linux-x64-gnu" "0.1.8" + "@napi-rs/simple-git-linux-x64-musl" "0.1.8" + "@napi-rs/simple-git-win32-arm64-msvc" "0.1.8" + "@napi-rs/simple-git-win32-x64-msvc" "0.1.8" + +"@next/env@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/env/-/env-12.3.1.tgz#18266bd92de3b4aa4037b1927aa59e6f11879260" + integrity sha512-9P9THmRFVKGKt9DYqeC2aKIxm8rlvkK38V1P1sRE7qyoPBIs8l9oo79QoSdPtOWfzkbDAVUqvbQGgTMsb8BtJg== + +"@next/swc-android-arm-eabi@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.1.tgz#b15ce8ad376102a3b8c0f3c017dde050a22bb1a3" + integrity sha512-i+BvKA8tB//srVPPQxIQN5lvfROcfv4OB23/L1nXznP+N/TyKL8lql3l7oo2LNhnH66zWhfoemg3Q4VJZSruzQ== + +"@next/swc-android-arm64@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.3.1.tgz#85d205f568a790a137cb3c3f720d961a2436ac9c" + integrity sha512-CmgU2ZNyBP0rkugOOqLnjl3+eRpXBzB/I2sjwcGZ7/Z6RcUJXK5Evz+N0ucOxqE4cZ3gkTeXtSzRrMK2mGYV8Q== + +"@next/swc-darwin-arm64@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.3.1.tgz#b105457d6760a7916b27e46c97cb1a40547114ae" + integrity sha512-hT/EBGNcu0ITiuWDYU9ur57Oa4LybD5DOQp4f22T6zLfpoBMfBibPtR8XktXmOyFHrL/6FC2p9ojdLZhWhvBHg== + +"@next/swc-darwin-x64@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.1.tgz#6947b39082271378896b095b6696a7791c6e32b1" + integrity sha512-9S6EVueCVCyGf2vuiLiGEHZCJcPAxglyckTZcEwLdJwozLqN0gtS0Eq0bQlGS3dH49Py/rQYpZ3KVWZ9BUf/WA== + +"@next/swc-freebsd-x64@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.1.tgz#2b6c36a4d84aae8b0ea0e0da9bafc696ae27085a" + integrity sha512-qcuUQkaBZWqzM0F1N4AkAh88lLzzpfE6ImOcI1P6YeyJSsBmpBIV8o70zV+Wxpc26yV9vpzb+e5gCyxNjKJg5Q== + +"@next/swc-linux-arm-gnueabihf@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.1.tgz#6e421c44285cfedac1f4631d5de330dd60b86298" + integrity sha512-diL9MSYrEI5nY2wc/h/DBewEDUzr/DqBjIgHJ3RUNtETAOB3spMNHvJk2XKUDjnQuluLmFMloet9tpEqU2TT9w== + +"@next/swc-linux-arm64-gnu@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.1.tgz#8863f08a81f422f910af126159d2cbb9552ef717" + integrity sha512-o/xB2nztoaC7jnXU3Q36vGgOolJpsGG8ETNjxM1VAPxRwM7FyGCPHOMk1XavG88QZSQf+1r+POBW0tLxQOJ9DQ== + +"@next/swc-linux-arm64-musl@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.1.tgz#0038f07cf0b259d70ae0c80890d826dfc775d9f3" + integrity sha512-2WEasRxJzgAmP43glFNhADpe8zB7kJofhEAVNbDJZANp+H4+wq+/cW1CdDi8DqjkShPEA6/ejJw+xnEyDID2jg== + +"@next/swc-linux-x64-gnu@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.1.tgz#c66468f5e8181ffb096c537f0dbfb589baa6a9c1" + integrity sha512-JWEaMyvNrXuM3dyy9Pp5cFPuSSvG82+yABqsWugjWlvfmnlnx9HOQZY23bFq3cNghy5V/t0iPb6cffzRWylgsA== + +"@next/swc-linux-x64-musl@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.1.tgz#c6269f3e96ac0395bc722ad97ce410ea5101d305" + integrity sha512-xoEWQQ71waWc4BZcOjmatuvPUXKTv6MbIFzpm4LFeCHsg2iwai0ILmNXf81rJR+L1Wb9ifEke2sQpZSPNz1Iyg== + +"@next/swc-win32-arm64-msvc@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.1.tgz#83c639ee969cee36ce247c3abd1d9df97b5ecade" + integrity sha512-hswVFYQYIeGHE2JYaBVtvqmBQ1CppplQbZJS/JgrVI3x2CurNhEkmds/yqvDONfwfbttTtH4+q9Dzf/WVl3Opw== + +"@next/swc-win32-ia32-msvc@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.1.tgz#52995748b92aa8ad053440301bc2c0d9fbcf27c2" + integrity sha512-Kny5JBehkTbKPmqulr5i+iKntO5YMP+bVM8Hf8UAmjSMVo3wehyLVc9IZkNmcbxi+vwETnQvJaT5ynYBkJ9dWA== + +"@next/swc-win32-x64-msvc@12.3.1": + version "12.3.1" + resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.1.tgz#27d71a95247a9eaee03d47adee7e3bd594514136" + integrity sha512-W1ijvzzg+kPEX6LAc+50EYYSEo0FVu7dmTE+t+DM4iOLqgGHoW9uYSz9wCVdkXOEEMP9xhXfGpcSxsfDucyPkA== + +"@popperjs/core@^2.11.6": + version "2.11.6" + resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.6.tgz#cee20bd55e68a1720bdab363ecf0c821ded4cd45" + integrity sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw== + +"@reach/skip-nav@^0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@reach/skip-nav/-/skip-nav-0.17.0.tgz#225aaaf947f8750568ad5f4cc3646641fd335d56" + integrity sha512-wkkpQK3ffczzGHis6TaUvpOabuAL9n9Kh5vr4h56XPIJP3X77VcHUDk7MK3HbV1mTgamGxc9Hbd1sXKSWLu3yA== + dependencies: + "@reach/utils" "0.17.0" + tslib "^2.3.0" + +"@reach/utils@0.17.0": + version "0.17.0" + resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.17.0.tgz#3d1d2ec56d857f04fe092710d8faee2b2b121303" + integrity sha512-M5y8fCBbrWeIsxedgcSw6oDlAMQDkl5uv3VnMVJ7guwpf4E48Xlh1v66z/1BgN/WYe2y8mB/ilFD2nysEfdGeA== + dependencies: + tiny-warning "^1.0.3" + tslib "^2.3.0" + +"@swc/helpers@0.4.11": + version "0.4.11" + resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.11.tgz#db23a376761b3d31c26502122f349a21b592c8de" + integrity sha512-rEUrBSGIoSFuYxwBYtlUFMlE2CwGhmW+w9355/5oduSw8e5h2+Tj4UrAGNNgP9915++wj5vkQo0UuOBqOAq4nw== + dependencies: + tslib "^2.4.0" + +"@types/acorn@^4.0.0": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@types/acorn/-/acorn-4.0.6.tgz#d61ca5480300ac41a7d973dd5b84d0a591154a22" + integrity sha512-veQTnWP+1D/xbxVrPC3zHnCZRjSrKfhbMUlEA43iMZLu7EsnTtkJklIuwrCPbOi8YkvDQAiW05VQQFvvz9oieQ== + dependencies: + "@types/estree" "*" + +"@types/debug@^4.0.0": + version "4.1.7" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.7.tgz#7cc0ea761509124709b8b2d1090d8f6c17aadb82" + integrity sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg== + dependencies: + "@types/ms" "*" + +"@types/estree-jsx@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree-jsx/-/estree-jsx-1.0.0.tgz#7bfc979ab9f692b492017df42520f7f765e98df1" + integrity sha512-3qvGd0z8F2ENTGr/GG1yViqfiKmRfrXVx5sJyHGFu3z7m5g5utCQtGp/g29JnjflhtQJBv1WDQukHiT58xPcYQ== + dependencies: + "@types/estree" "*" + +"@types/estree@*", "@types/estree@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== + +"@types/hast@^2.0.0": + version "2.3.4" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.4.tgz#8aa5ef92c117d20d974a82bdfb6a648b08c0bafc" + integrity sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g== + dependencies: + "@types/unist" "*" + +"@types/mdast@^3.0.0": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.10.tgz#4724244a82a4598884cbbe9bcfd73dff927ee8af" + integrity sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA== + dependencies: + "@types/unist" "*" + +"@types/mdurl@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9" + integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA== + +"@types/mdx@^2.0.0": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/mdx/-/mdx-2.0.2.tgz#64be19baddba4323ae7893e077e98759316fe279" + integrity sha512-mJGfgj4aWpiKb8C0nnJJchs1sHBHn0HugkVfqqyQi7Wn6mBRksLeQsPOFvih/Pu8L1vlDzfe/LidhVHBeUk3aQ== + +"@types/ms@*": + version "0.7.31" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197" + integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA== + +"@types/prop-types@*": + version "15.7.5" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" + integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== + +"@types/react@>=16": + version "18.0.21" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.21.tgz#b8209e9626bb00a34c76f55482697edd2b43cc67" + integrity sha512-7QUCOxvFgnD5Jk8ZKlUAhVcRj7GuJRjnjjiY/IUBWKgOlnvDvTMLD4RTF7NPyVmbRhNrbomZiOepg7M/2Kj1mA== + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + csstype "^3.0.2" + +"@types/scheduler@*": + version "0.16.2" + resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" + integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== + +"@types/unist@*", "@types/unist@^2.0.0": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" + integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== + +acorn-jsx@^5.0.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.0.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" + integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== + +ansi-styles@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +arch@^2.1.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" + integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== + +arg@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/arg/-/arg-1.0.0.tgz#444d885a4e25b121640b55155ef7cd03975d6050" + integrity sha512-Wk7TEzl1KqvTGs/uyhmHO/3XLd3t1UeU4IstvPXVzGPM522cTjqjNZ99esCkcL52sjqjo8e8CTBcWhkxvGzoAw== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +astring@^1.8.0: + version "1.8.3" + resolved "https://registry.yarnpkg.com/astring/-/astring-1.8.3.tgz#1a0ae738c7cc558f8e5ddc8e3120636f5cebcb85" + integrity sha512-sRpyiNrx2dEYIMmUXprS8nlpRg2Drs8m9ElX9vVEXaCB4XEAJhKfs7IcX0IwShjuOAjLR6wzIrgoptz1n19i1A== + +bail@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d" + integrity sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw== + +caniuse-lite@^1.0.30001406: + version "1.0.30001410" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001410.tgz#b5a86366fbbf439d75dd3db1d21137a73e829f44" + integrity sha512-QoblBnuE+rG0lc3Ur9ltP5q47lbguipa/ncNMyyGuqPk44FxbScWAeEO+k5fSQ8WekdAK4mWqNs1rADDAiN5xQ== + +ccount@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-2.0.1.tgz#17a3bf82302e0870d6da43a01311a8bc02a3ecf5" + integrity sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg== + +chalk@2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + integrity sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q== + dependencies: + ansi-styles "^3.1.0" + escape-string-regexp "^1.0.5" + supports-color "^4.0.0" + +character-entities-html4@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/character-entities-html4/-/character-entities-html4-2.1.0.tgz#1f1adb940c971a4b22ba39ddca6b618dc6e56b2b" + integrity sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA== + +character-entities-legacy@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz#76bc83a90738901d7bc223a9e93759fdd560125b" + integrity sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ== + +character-entities@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22" + integrity sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ== + +character-reference-invalid@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz#85c66b041e43b47210faf401278abf808ac45cb9" + integrity sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw== + +clipboardy@1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-1.2.2.tgz#2ce320b9ed9be1514f79878b53ff9765420903e2" + integrity sha512-16KrBOV7bHmHdxcQiCvfUFYVFyEah4FI8vYT1Fr7CGSA4G+xBWMEfUEQJS1hxeHGtI9ju1Bzs9uXSbj5HZKArw== + dependencies: + arch "^2.1.0" + execa "^0.8.0" + +clsx@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" + integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== + +comma-separated-tokens@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-2.0.2.tgz#d4c25abb679b7751c880be623c1179780fe1dd98" + integrity sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg== + +compute-scroll-into-view@^1.0.17: + version "1.0.17" + resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.17.tgz#6a88f18acd9d42e9cf4baa6bec7e0522607ab7ab" + integrity sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg== + +cross-spawn@^5.0.1: + version "5.1.0" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" + integrity sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A== + dependencies: + lru-cache "^4.0.1" + shebang-command "^1.2.0" + which "^1.2.9" + +csstype@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" + integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== + +debug@^4.0.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +decode-named-character-reference@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" + integrity sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg== + dependencies: + character-entities "^2.0.0" + +dequal@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + +diff@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" + integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + +escape-string-regexp@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" + integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +estree-util-attach-comments@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/estree-util-attach-comments/-/estree-util-attach-comments-2.1.0.tgz#47d69900588bcbc6bf58c3798803ec5f1f3008de" + integrity sha512-rJz6I4L0GaXYtHpoMScgDIwM0/Vwbu5shbMeER596rB2D1EWF6+Gj0e0UKzJPZrpoOc87+Q2kgVFHfjAymIqmw== + dependencies: + "@types/estree" "^1.0.0" + +estree-util-build-jsx@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/estree-util-build-jsx/-/estree-util-build-jsx-2.2.0.tgz#d4307bbeee28c14eb4d63b75c9aad28fa61d84f5" + integrity sha512-apsfRxF9uLrqosApvHVtYZjISPvTJ+lBiIydpC+9wE6cF6ssbhnjyQLqaIjgzGxvC2Hbmec1M7g91PoBayYoQQ== + dependencies: + "@types/estree-jsx" "^1.0.0" + estree-util-is-identifier-name "^2.0.0" + estree-walker "^3.0.0" + +estree-util-is-identifier-name@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-1.1.0.tgz#2e3488ea06d9ea2face116058864f6370b37456d" + integrity sha512-OVJZ3fGGt9By77Ix9NhaRbzfbDV/2rx9EP7YIDJTmsZSEc5kYn2vWcNccYyahJL2uAQZK2a5Or2i0wtIKTPoRQ== + +estree-util-is-identifier-name@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/estree-util-is-identifier-name/-/estree-util-is-identifier-name-2.0.1.tgz#cf07867f42705892718d9d89eb2d85eaa8f0fcb5" + integrity sha512-rxZj1GkQhY4x1j/CSnybK9cGuMFQYFPLq0iNyopqf14aOVLFtMv7Esika+ObJWPWiOHuMOAHz3YkWoLYYRnzWQ== + +estree-util-to-js@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/estree-util-to-js/-/estree-util-to-js-1.1.0.tgz#3bd9bb86354063537cc3d81259be2f0d4c3af39f" + integrity sha512-490lbfCcpLk+ofK6HCgqDfYs4KAfq6QVvDw3+Bm1YoKRgiOjKiKYGAVQE1uwh7zVxBgWhqp4FDtp5SqunpUk1A== + dependencies: + "@types/estree-jsx" "^1.0.0" + astring "^1.8.0" + source-map "^0.7.0" + +estree-util-value-to-estree@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/estree-util-value-to-estree/-/estree-util-value-to-estree-1.3.0.tgz#1d3125594b4d6680f666644491e7ac1745a3df49" + integrity sha512-Y+ughcF9jSUJvncXwqRageavjrNPAI+1M/L3BI3PyLp1nmgYTGUXU6t5z1Y7OWuThoDdhPME07bQU+d5LxdJqw== + dependencies: + is-plain-obj "^3.0.0" + +estree-util-visit@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/estree-util-visit/-/estree-util-visit-1.2.0.tgz#aa0311a9c2f2aa56e9ae5e8b9d87eac14e4ec8f8" + integrity sha512-wdsoqhWueuJKsh5hqLw3j8lwFqNStm92VcwtAOAny8g/KS/l5Y8RISjR4k5W6skCj3Nirag/WUCMS0Nfy3sgsg== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/unist" "^2.0.0" + +estree-walker@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-3.0.1.tgz#c2a9fb4a30232f5039b7c030b37ead691932debd" + integrity sha512-woY0RUD87WzMBUiZLx8NsYr23N5BKsOMZHhu2hoNRVh6NXGfoiT1KOL8G3UHlJAnEDGmfa5ubNA/AacfG+Kb0g== + +execa@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-0.8.0.tgz#d8d76bbc1b55217ed190fd6dd49d3c774ecfc8da" + integrity sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA== + dependencies: + cross-spawn "^5.0.1" + get-stream "^3.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== + dependencies: + is-extendable "^0.1.0" + +extend@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +flexsearch@^0.7.21: + version "0.7.21" + resolved "https://registry.yarnpkg.com/flexsearch/-/flexsearch-0.7.21.tgz#0f5ede3f2aae67ddc351efbe3b24b69d29e9d48b" + integrity sha512-W7cHV7Hrwjid6lWmy0IhsWDFQboWSng25U3VVywpHOTJnnAZNPScog67G+cVpeX9f7yDD21ih0WDrMMT+JoaYg== + +focus-visible@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/focus-visible/-/focus-visible-5.2.0.tgz#3a9e41fccf587bd25dcc2ef045508284f0a4d6b3" + integrity sha512-Rwix9pBtC1Nuy5wysTmKy+UjbDJpIfg8eHjw0rjZ1mX4GNLz1Bmd16uDpI3Gk1i70Fgcs8Csg2lPm8HULFg9DQ== + +get-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ== + +github-slugger@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" + integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== + +graceful-fs@^4.2.10: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== + +gray-matter@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.3.tgz#e893c064825de73ea1f5f7d88c7a9f7274288798" + integrity sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q== + dependencies: + js-yaml "^3.13.1" + kind-of "^6.0.2" + section-matter "^1.0.0" + strip-bom-string "^1.0.0" + +has-flag@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + integrity sha512-P+1n3MnwjR/Epg9BBo1KT8qbye2g2Ou4sFumihwt6I4tsUX7jnLcX4BTOSKg/B1ZrIYMN9FcEnG4x5a7NB8Eng== + +hast-util-to-estree@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/hast-util-to-estree/-/hast-util-to-estree-2.1.0.tgz#aeac70aad0102ae309570907b3f56a08231d5323" + integrity sha512-Vwch1etMRmm89xGgz+voWXvVHba2iiMdGMKmaMfYt35rbVtFDq8JNwwAIvi8zHMkO6Gvqo9oTMwJTmzVRfXh4g== + dependencies: + "@types/estree" "^1.0.0" + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^2.0.0" + "@types/unist" "^2.0.0" + comma-separated-tokens "^2.0.0" + estree-util-attach-comments "^2.0.0" + estree-util-is-identifier-name "^2.0.0" + hast-util-whitespace "^2.0.0" + mdast-util-mdx-expression "^1.0.0" + mdast-util-mdxjs-esm "^1.0.0" + property-information "^6.0.0" + space-separated-tokens "^2.0.0" + style-to-object "^0.3.0" + unist-util-position "^4.0.0" + zwitch "^2.0.0" + +hast-util-to-string@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/hast-util-to-string/-/hast-util-to-string-1.0.4.tgz#9b24c114866bdb9478927d7e9c36a485ac728378" + integrity sha512-eK0MxRX47AV2eZ+Lyr18DCpQgodvaS3fAQO2+b9Two9F5HEoRPhiUMNzoXArMJfZi2yieFzUBMRl3HNJ3Jus3w== + +hast-util-whitespace@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz#4fc1086467cc1ef5ba20673cb6b03cec3a970f1c" + integrity sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg== + +inline-style-parser@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" + integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== + +intersection-observer@^0.12.2: + version "0.12.2" + resolved "https://registry.yarnpkg.com/intersection-observer/-/intersection-observer-0.12.2.tgz#4a45349cc0cd91916682b1f44c28d7ec737dc375" + integrity sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg== + +is-alphabetical@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-2.0.1.tgz#01072053ea7c1036df3c7d19a6daaec7f19e789b" + integrity sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ== + +is-alphanumerical@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz#7c03fbe96e3e931113e57f964b0a368cc2dfd875" + integrity sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw== + dependencies: + is-alphabetical "^2.0.0" + is-decimal "^2.0.0" + +is-buffer@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" + integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== + +is-decimal@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-2.0.1.tgz#9469d2dc190d0214fd87d78b78caecc0cc14eef7" + integrity sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A== + +is-extendable@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== + +is-hexadecimal@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz#86b5bf668fca307498d319dfc03289d781a90027" + integrity sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg== + +is-plain-obj@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-3.0.0.tgz#af6f2ea14ac5a646183a5bbdb5baabbc156ad9d7" + integrity sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA== + +is-plain-obj@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" + integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== + +is-reference@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-3.0.0.tgz#b1380c03d96ddf7089709781e3208fceb0c92cd6" + integrity sha512-Eo1W3wUoHWoCoVM4GVl/a+K0IgiqE5aIo4kJABFyMum1ZORlPkC+UC357sSQUL5w5QCE5kCC9upl75b7+7CY/Q== + dependencies: + "@types/estree" "*" + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +"js-tokens@^3.0.0 || ^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsonc-parser@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" + integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +kleur@^4.0.3: + version "4.1.5" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" + integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== + +longest-streak@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-3.0.1.tgz#c97315b7afa0e7d9525db9a5a2953651432bdc5d" + integrity sha512-cHlYSUpL2s7Fb3394mYxwTYj8niTaNHUCLr0qdiCXQfSjfuA7CKofpX2uSwEfFDQ0EB7JcnMnm+GjbqqoinYYg== + +loose-envify@^1.1.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lru-cache@^4.0.1: + version "4.1.5" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== + dependencies: + pseudomap "^1.0.2" + yallist "^2.1.2" + +markdown-extensions@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/markdown-extensions/-/markdown-extensions-1.1.1.tgz#fea03b539faeaee9b4ef02a3769b455b189f7fc3" + integrity sha512-WWC0ZuMzCyDHYCasEGs4IPvLyTGftYwh6wIEOULOF0HXcqZlhwRzrK0w2VUlxWA98xnvb/jszw4ZSkJ6ADpM6Q== + +markdown-table@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-3.0.2.tgz#9b59eb2c1b22fe71954a65ff512887065a7bb57c" + integrity sha512-y8j3a5/DkJCmS5x4dMCQL+OR0+2EAq3DOtio1COSHsmW2BGXnNCK3v12hJt1LrUz5iZH5g0LmuYOjDdI+czghA== + +match-sorter@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/match-sorter/-/match-sorter-6.3.1.tgz#98cc37fda756093424ddf3cbc62bfe9c75b92bda" + integrity sha512-mxybbo3pPNuA+ZuCUhm5bwNkXrJTbsk5VWbR5wiwz/GC6LIiegBGn2w3O08UG/jdbYLinw51fSQ5xNU1U3MgBw== + dependencies: + "@babel/runtime" "^7.12.5" + remove-accents "0.4.2" + +mdast-util-definitions@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-5.1.1.tgz#2c1d684b28e53f84938bb06317944bee8efa79db" + integrity sha512-rQ+Gv7mHttxHOBx2dkF4HWTg+EE+UR78ptQWDylzPKaQuVGdG4HIoY3SrS/pCp80nZ04greFvXbVFHT+uf0JVQ== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + unist-util-visit "^4.0.0" + +mdast-util-find-and-replace@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/mdast-util-find-and-replace/-/mdast-util-find-and-replace-2.2.1.tgz#249901ef43c5f41d6e8a8d446b3b63b17e592d7c" + integrity sha512-SobxkQXFAdd4b5WmEakmkVoh18icjQRxGy5OWTCzgsLRm1Fu/KCtwD1HIQSsmq5ZRjVH0Ehwg6/Fn3xIUk+nKw== + dependencies: + escape-string-regexp "^5.0.0" + unist-util-is "^5.0.0" + unist-util-visit-parents "^5.0.0" + +mdast-util-from-markdown@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.2.0.tgz#84df2924ccc6c995dec1e2368b2b208ad0a76268" + integrity sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + decode-named-character-reference "^1.0.0" + mdast-util-to-string "^3.1.0" + micromark "^3.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-decode-string "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + unist-util-stringify-position "^3.0.0" + uvu "^0.5.0" + +mdast-util-gfm-autolink-literal@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-1.0.2.tgz#4032dcbaddaef7d4f2f3768ed830475bb22d3970" + integrity sha512-FzopkOd4xTTBeGXhXSBU0OCDDh5lUj2rd+HQqG92Ld+jL4lpUfgX2AT2OHAVP9aEeDKp7G92fuooSZcYJA3cRg== + dependencies: + "@types/mdast" "^3.0.0" + ccount "^2.0.0" + mdast-util-find-and-replace "^2.0.0" + micromark-util-character "^1.0.0" + +mdast-util-gfm-footnote@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-1.0.1.tgz#11d2d40a1a673a399c459e467fa85e00223191fe" + integrity sha512-p+PrYlkw9DeCRkTVw1duWqPRHX6Ywh2BNKJQcZbCwAuP/59B0Lk9kakuAd7KbQprVO4GzdW8eS5++A9PUSqIyw== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-markdown "^1.3.0" + micromark-util-normalize-identifier "^1.0.0" + +mdast-util-gfm-strikethrough@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-1.0.1.tgz#a4a74c36864ec6a6e3bbd31e1977f29beb475789" + integrity sha512-zKJbEPe+JP6EUv0mZ0tQUyLQOC+FADt0bARldONot/nefuISkaZFlmVK4tU6JgfyZGrky02m/I6PmehgAgZgqg== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-markdown "^1.3.0" + +mdast-util-gfm-table@^1.0.0: + version "1.0.6" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-table/-/mdast-util-gfm-table-1.0.6.tgz#184e900979fe790745fc3dabf77a4114595fcd7f" + integrity sha512-uHR+fqFq3IvB3Rd4+kzXW8dmpxUhvgCQZep6KdjsLK4O6meK5dYZEayLtIxNus1XO3gfjfcIFe8a7L0HZRGgag== + dependencies: + "@types/mdast" "^3.0.0" + markdown-table "^3.0.0" + mdast-util-from-markdown "^1.0.0" + mdast-util-to-markdown "^1.3.0" + +mdast-util-gfm-task-list-item@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-1.0.1.tgz#6f35f09c6e2bcbe88af62fdea02ac199cc802c5c" + integrity sha512-KZ4KLmPdABXOsfnM6JHUIjxEvcx2ulk656Z/4Balw071/5qgnhz+H1uGtf2zIGnrnvDC8xR4Fj9uKbjAFGNIeA== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-to-markdown "^1.3.0" + +mdast-util-gfm@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mdast-util-gfm/-/mdast-util-gfm-2.0.1.tgz#16fcf70110ae689a06d77e8f4e346223b64a0ea6" + integrity sha512-42yHBbfWIFisaAfV1eixlabbsa6q7vHeSPY+cg+BBjX51M8xhgMacqH9g6TftB/9+YkcI0ooV4ncfrJslzm/RQ== + dependencies: + mdast-util-from-markdown "^1.0.0" + mdast-util-gfm-autolink-literal "^1.0.0" + mdast-util-gfm-footnote "^1.0.0" + mdast-util-gfm-strikethrough "^1.0.0" + mdast-util-gfm-table "^1.0.0" + mdast-util-gfm-task-list-item "^1.0.0" + mdast-util-to-markdown "^1.0.0" + +mdast-util-mdx-expression@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/mdast-util-mdx-expression/-/mdast-util-mdx-expression-1.3.0.tgz#fed063cc6320da1005c8e50338bb374d6dac69ba" + integrity sha512-9kTO13HaL/ChfzVCIEfDRdp1m5hsvsm6+R8yr67mH+KS2ikzZ0ISGLPTbTswOFpLLlgVHO9id3cul4ajutCvCA== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + mdast-util-from-markdown "^1.0.0" + mdast-util-to-markdown "^1.0.0" + +mdast-util-mdx-jsx@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-2.1.0.tgz#029f5a9c38485dbb5cf482059557ee7d788f1947" + integrity sha512-KzgzfWMhdteDkrY4mQtyvTU5bc/W4ppxhe9SzelO6QUUiwLAM+Et2Dnjjprik74a336kHdo0zKm7Tp+n6FFeRg== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + ccount "^2.0.0" + mdast-util-to-markdown "^1.3.0" + parse-entities "^4.0.0" + stringify-entities "^4.0.0" + unist-util-remove-position "^4.0.0" + unist-util-stringify-position "^3.0.0" + vfile-message "^3.0.0" + +mdast-util-mdx@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mdast-util-mdx/-/mdast-util-mdx-2.0.0.tgz#dd4f6c993cf27da32725e50a04874f595b7b63fb" + integrity sha512-M09lW0CcBT1VrJUaF/PYxemxxHa7SLDHdSn94Q9FhxjCQfuW7nMAWKWimTmA3OyDMSTH981NN1csW1X+HPSluw== + dependencies: + mdast-util-mdx-expression "^1.0.0" + mdast-util-mdx-jsx "^2.0.0" + mdast-util-mdxjs-esm "^1.0.0" + +mdast-util-mdxjs-esm@^1.0.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-1.3.0.tgz#137345ef827169aeeeb6069277cd3e090830ce9a" + integrity sha512-7N5ihsOkAEGjFotIX9p/YPdl4TqUoMxL4ajNz7PbT89BqsdWJuBC9rvgt6wpbwTZqWWR0jKWqQbwsOWDBUZv4g== + dependencies: + "@types/estree-jsx" "^1.0.0" + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + mdast-util-from-markdown "^1.0.0" + mdast-util-to-markdown "^1.0.0" + +mdast-util-to-hast@^12.1.0: + version "12.2.2" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-12.2.2.tgz#2bd8cf985a67c90c181eadcfdd8d31b8798ed9a1" + integrity sha512-lVkUttV9wqmdXFtEBXKcepvU/zfwbhjbkM5rxrquLW55dS1DfOrnAXCk5mg1be1sfY/WfMmayGy1NsbK1GLCYQ== + dependencies: + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + "@types/mdurl" "^1.0.0" + mdast-util-definitions "^5.0.0" + mdurl "^1.0.0" + micromark-util-sanitize-uri "^1.0.0" + trim-lines "^3.0.0" + unist-builder "^3.0.0" + unist-util-generated "^2.0.0" + unist-util-position "^4.0.0" + unist-util-visit "^4.0.0" + +mdast-util-to-markdown@^1.0.0, mdast-util-to-markdown@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-markdown/-/mdast-util-to-markdown-1.3.0.tgz#38b6cdc8dc417de642a469c4fc2abdf8c931bd1e" + integrity sha512-6tUSs4r+KK4JGTTiQ7FfHmVOaDrLQJPmpjD6wPMlHGUVXoG9Vjc3jIeP+uyBWRf8clwB2blM+W7+KrlMYQnftA== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + longest-streak "^3.0.0" + mdast-util-to-string "^3.0.0" + micromark-util-decode-string "^1.0.0" + unist-util-visit "^4.0.0" + zwitch "^2.0.0" + +mdast-util-to-string@^3.0.0, mdast-util-to-string@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz#56c506d065fbf769515235e577b5a261552d56e9" + integrity sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA== + +mdurl@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== + +micromark-core-commonmark@^1.0.0, micromark-core-commonmark@^1.0.1: + version "1.0.6" + resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.0.6.tgz#edff4c72e5993d93724a3c206970f5a15b0585ad" + integrity sha512-K+PkJTxqjFfSNkfAhp4GB+cZPfQd6dxtTXnf+RjZOV7T4EEXnvgzOcnp+eSTmpGk9d1S9sL6/lqrgSNn/s0HZA== + dependencies: + decode-named-character-reference "^1.0.0" + micromark-factory-destination "^1.0.0" + micromark-factory-label "^1.0.0" + micromark-factory-space "^1.0.0" + micromark-factory-title "^1.0.0" + micromark-factory-whitespace "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-chunked "^1.0.0" + micromark-util-classify-character "^1.0.0" + micromark-util-html-tag-name "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-subtokenize "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.1" + uvu "^0.5.0" + +micromark-extension-gfm-autolink-literal@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-1.0.3.tgz#dc589f9c37eaff31a175bab49f12290edcf96058" + integrity sha512-i3dmvU0htawfWED8aHMMAzAVp/F0Z+0bPh3YrbTPPL1v4YAlCZpy5rBO5p0LPYiZo0zFVkoYh7vDU7yQSiCMjg== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-sanitize-uri "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-extension-gfm-footnote@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-1.0.4.tgz#cbfd8873b983e820c494498c6dac0105920818d5" + integrity sha512-E/fmPmDqLiMUP8mLJ8NbJWJ4bTw6tS+FEQS8CcuDtZpILuOb2kjLqPEeAePF1djXROHXChM/wPJw0iS4kHCcIg== + dependencies: + micromark-core-commonmark "^1.0.0" + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-sanitize-uri "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-extension-gfm-strikethrough@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-1.0.4.tgz#162232c284ffbedd8c74e59c1525bda217295e18" + integrity sha512-/vjHU/lalmjZCT5xt7CcHVJGq8sYRm80z24qAKXzaHzem/xsDYb2yLL+NNVbYvmpLx3O7SYPuGL5pzusL9CLIQ== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-classify-character "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-extension-gfm-table@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-table/-/micromark-extension-gfm-table-1.0.5.tgz#7b708b728f8dc4d95d486b9e7a2262f9cddbcbb4" + integrity sha512-xAZ8J1X9W9K3JTJTUL7G6wSKhp2ZYHrFk5qJgY/4B33scJzE2kpfRL6oiw/veJTbt7jiM/1rngLlOKPWr1G+vg== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-extension-gfm-tagfilter@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-1.0.1.tgz#fb2e303f7daf616db428bb6a26e18fda14a90a4d" + integrity sha512-Ty6psLAcAjboRa/UKUbbUcwjVAv5plxmpUTy2XC/3nJFL37eHej8jrHrRzkqcpipJliuBH30DTs7+3wqNcQUVA== + dependencies: + micromark-util-types "^1.0.0" + +micromark-extension-gfm-task-list-item@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-1.0.3.tgz#7683641df5d4a09795f353574d7f7f66e47b7fc4" + integrity sha512-PpysK2S1Q/5VXi72IIapbi/jliaiOFzv7THH4amwXeYXLq3l1uo8/2Be0Ac1rEwK20MQEsGH2ltAZLNY2KI/0Q== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-extension-gfm@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/micromark-extension-gfm/-/micromark-extension-gfm-2.0.1.tgz#40f3209216127a96297c54c67f5edc7ef2d1a2a2" + integrity sha512-p2sGjajLa0iYiGQdT0oelahRYtMWvLjy8J9LOCxzIQsllMCGLbsLW+Nc+N4vi02jcRJvedVJ68cjelKIO6bpDA== + dependencies: + micromark-extension-gfm-autolink-literal "^1.0.0" + micromark-extension-gfm-footnote "^1.0.0" + micromark-extension-gfm-strikethrough "^1.0.0" + micromark-extension-gfm-table "^1.0.0" + micromark-extension-gfm-tagfilter "^1.0.0" + micromark-extension-gfm-task-list-item "^1.0.0" + micromark-util-combine-extensions "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-extension-mdx-expression@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-1.0.3.tgz#cd3843573921bf55afcfff4ae0cd2e857a16dcfa" + integrity sha512-TjYtjEMszWze51NJCZmhv7MEBcgYRgb3tJeMAJ+HQCAaZHHRBaDCccqQzGizR/H4ODefP44wRTgOn2vE5I6nZA== + dependencies: + micromark-factory-mdx-expression "^1.0.0" + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-events-to-acorn "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-extension-mdx-jsx@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-1.0.3.tgz#9f196be5f65eb09d2a49b237a7b3398bba2999be" + integrity sha512-VfA369RdqUISF0qGgv2FfV7gGjHDfn9+Qfiv5hEwpyr1xscRj/CiVRkU7rywGFCO7JwJ5L0e7CJz60lY52+qOA== + dependencies: + "@types/acorn" "^4.0.0" + estree-util-is-identifier-name "^2.0.0" + micromark-factory-mdx-expression "^1.0.0" + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + vfile-message "^3.0.0" + +micromark-extension-mdx-md@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-mdx-md/-/micromark-extension-mdx-md-1.0.0.tgz#382f5df9ee3706dd120b51782a211f31f4760d22" + integrity sha512-xaRAMoSkKdqZXDAoSgp20Azm0aRQKGOl0RrS81yGu8Hr/JhMsBmfs4wR7m9kgVUIO36cMUQjNyiyDKPrsv8gOw== + dependencies: + micromark-util-types "^1.0.0" + +micromark-extension-mdxjs-esm@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-1.0.3.tgz#630d9dc9db2c2fd470cac8c1e7a824851267404d" + integrity sha512-2N13ol4KMoxb85rdDwTAC6uzs8lMX0zeqpcyx7FhS7PxXomOnLactu8WI8iBNXW8AVyea3KIJd/1CKnUmwrK9A== + dependencies: + micromark-core-commonmark "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-events-to-acorn "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + unist-util-position-from-estree "^1.1.0" + uvu "^0.5.0" + vfile-message "^3.0.0" + +micromark-extension-mdxjs@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-extension-mdxjs/-/micromark-extension-mdxjs-1.0.0.tgz#772644e12fc8299a33e50f59c5aa15727f6689dd" + integrity sha512-TZZRZgeHvtgm+IhtgC2+uDMR7h8eTKF0QUX9YsgoL9+bADBpBY6SiLvWqnBlLbCEevITmTqmEuY3FoxMKVs1rQ== + dependencies: + acorn "^8.0.0" + acorn-jsx "^5.0.0" + micromark-extension-mdx-expression "^1.0.0" + micromark-extension-mdx-jsx "^1.0.0" + micromark-extension-mdx-md "^1.0.0" + micromark-extension-mdxjs-esm "^1.0.0" + micromark-util-combine-extensions "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-destination@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-1.0.0.tgz#fef1cb59ad4997c496f887b6977aa3034a5a277e" + integrity sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-label@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-1.0.2.tgz#6be2551fa8d13542fcbbac478258fb7a20047137" + integrity sha512-CTIwxlOnU7dEshXDQ+dsr2n+yxpP0+fn271pu0bwDIS8uqfFcumXpj5mLn3hSC8iw2MUr6Gx8EcKng1dD7i6hg== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-factory-mdx-expression@^1.0.0: + version "1.0.6" + resolved "https://registry.yarnpkg.com/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-1.0.6.tgz#917e17d16e6e9c2551f3a862e6a9ebdd22056476" + integrity sha512-WRQIc78FV7KrCfjsEf/sETopbYjElh3xAmNpLkd1ODPqxEngP42eVRGbiPEQWpRV27LzqW+XVTvQAMIIRLPnNA== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-events-to-acorn "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + unist-util-position-from-estree "^1.0.0" + uvu "^0.5.0" + vfile-message "^3.0.0" + +micromark-factory-space@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-1.0.0.tgz#cebff49968f2b9616c0fcb239e96685cb9497633" + integrity sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-title@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-1.0.2.tgz#7e09287c3748ff1693930f176e1c4a328382494f" + integrity sha512-zily+Nr4yFqgMGRKLpTVsNl5L4PMu485fGFDOQJQBl2NFpjGte1e86zC0da93wf97jrc4+2G2GQudFMHn3IX+A== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-factory-whitespace@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.0.0.tgz#e991e043ad376c1ba52f4e49858ce0794678621c" + integrity sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-character@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-1.1.0.tgz#d97c54d5742a0d9611a68ca0cd4124331f264d86" + integrity sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg== + dependencies: + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-chunked@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-1.0.0.tgz#5b40d83f3d53b84c4c6bce30ed4257e9a4c79d06" + integrity sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-classify-character@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-1.0.0.tgz#cbd7b447cb79ee6997dd274a46fc4eb806460a20" + integrity sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-combine-extensions@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.0.0.tgz#91418e1e74fb893e3628b8d496085639124ff3d5" + integrity sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-decode-numeric-character-reference@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.0.0.tgz#dcc85f13b5bd93ff8d2868c3dba28039d490b946" + integrity sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-decode-string@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-1.0.2.tgz#942252ab7a76dec2dbf089cc32505ee2bc3acf02" + integrity sha512-DLT5Ho02qr6QWVNYbRZ3RYOSSWWFuH3tJexd3dgN1odEuPNxCngTCXJum7+ViRAd9BbdxCvMToPOD/IvVhzG6Q== + dependencies: + decode-named-character-reference "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-symbol "^1.0.0" + +micromark-util-encode@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.0.1.tgz#2c1c22d3800870ad770ece5686ebca5920353383" + integrity sha512-U2s5YdnAYexjKDel31SVMPbfi+eF8y1U4pfiRW/Y8EFVCy/vgxk/2wWTxzcqE71LHtCuCzlBDRU2a5CQ5j+mQA== + +micromark-util-events-to-acorn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-1.2.0.tgz#65785cb77299d791bfefdc6a5213ab57ceead115" + integrity sha512-WWp3bf7xT9MppNuw3yPjpnOxa8cj5ACivEzXJKu0WwnjBYfzaBvIAT9KfeyI0Qkll+bfQtfftSwdgTH6QhTOKw== + dependencies: + "@types/acorn" "^4.0.0" + "@types/estree" "^1.0.0" + estree-util-visit "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + vfile-location "^4.0.0" + vfile-message "^3.0.0" + +micromark-util-html-tag-name@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.1.0.tgz#eb227118befd51f48858e879b7a419fc0df20497" + integrity sha512-BKlClMmYROy9UiV03SwNmckkjn8QHVaWkqoAqzivabvdGcwNGMMMH/5szAnywmsTBUzDsU57/mFi0sp4BQO6dA== + +micromark-util-normalize-identifier@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.0.0.tgz#4a3539cb8db954bbec5203952bfe8cedadae7828" + integrity sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-resolve-all@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.0.0.tgz#a7c363f49a0162e931960c44f3127ab58f031d88" + integrity sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw== + dependencies: + micromark-util-types "^1.0.0" + +micromark-util-sanitize-uri@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.0.0.tgz#27dc875397cd15102274c6c6da5585d34d4f12b2" + integrity sha512-cCxvBKlmac4rxCGx6ejlIviRaMKZc0fWm5HdCHEeDWRSkn44l6NdYVRyU+0nT1XC72EQJMZV8IPHF+jTr56lAg== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-symbol "^1.0.0" + +micromark-util-subtokenize@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.0.2.tgz#ff6f1af6ac836f8bfdbf9b02f40431760ad89105" + integrity sha512-d90uqCnXp/cy4G881Ub4psE57Sf8YD0pim9QdjCRNjfas2M1u6Lbt+XZK9gnHL2XFhnozZiEdCa9CNfXSfQ6xA== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-util-symbol@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-1.0.1.tgz#b90344db62042ce454f351cf0bebcc0a6da4920e" + integrity sha512-oKDEMK2u5qqAptasDAwWDXq0tG9AssVwAx3E9bBF3t/shRIGsWIRG+cGafs2p/SnDSOecnt6hZPCE2o6lHfFmQ== + +micromark-util-types@^1.0.0, micromark-util-types@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-1.0.2.tgz#f4220fdb319205812f99c40f8c87a9be83eded20" + integrity sha512-DCfg/T8fcrhrRKTPjRrw/5LLvdGV7BHySf/1LOZx7TzWZdYRjogNtyNq885z3nNallwr3QUKARjqvHqX1/7t+w== + +micromark@^3.0.0: + version "3.0.10" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-3.0.10.tgz#1eac156f0399d42736458a14b0ca2d86190b457c" + integrity sha512-ryTDy6UUunOXy2HPjelppgJ2sNfcPz1pLlMdA6Rz9jPzhLikWXv/irpWV/I2jd68Uhmny7hHxAlAhk4+vWggpg== + dependencies: + "@types/debug" "^4.0.0" + debug "^4.0.0" + decode-named-character-reference "^1.0.0" + micromark-core-commonmark "^1.0.1" + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-chunked "^1.0.0" + micromark-util-combine-extensions "^1.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-sanitize-uri "^1.0.0" + micromark-util-subtokenize "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.1" + uvu "^0.5.0" + +mri@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" + integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +nanoid@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== + +next-themes@^0.2.0-beta.2: + version "0.2.1" + resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.2.1.tgz#0c9f128e847979daf6c67f70b38e6b6567856e45" + integrity sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A== + +next@^12.3.1: + version "12.3.1" + resolved "https://registry.yarnpkg.com/next/-/next-12.3.1.tgz#127b825ad2207faf869b33393ec8c75fe61e50f1" + integrity sha512-l7bvmSeIwX5lp07WtIiP9u2ytZMv7jIeB8iacR28PuUEFG5j0HGAPnMqyG5kbZNBG2H7tRsrQ4HCjuMOPnANZw== + dependencies: + "@next/env" "12.3.1" + "@swc/helpers" "0.4.11" + caniuse-lite "^1.0.30001406" + postcss "8.4.14" + styled-jsx "5.0.7" + use-sync-external-store "1.2.0" + optionalDependencies: + "@next/swc-android-arm-eabi" "12.3.1" + "@next/swc-android-arm64" "12.3.1" + "@next/swc-darwin-arm64" "12.3.1" + "@next/swc-darwin-x64" "12.3.1" + "@next/swc-freebsd-x64" "12.3.1" + "@next/swc-linux-arm-gnueabihf" "12.3.1" + "@next/swc-linux-arm64-gnu" "12.3.1" + "@next/swc-linux-arm64-musl" "12.3.1" + "@next/swc-linux-x64-gnu" "12.3.1" + "@next/swc-linux-x64-musl" "12.3.1" + "@next/swc-win32-arm64-msvc" "12.3.1" + "@next/swc-win32-ia32-msvc" "12.3.1" + "@next/swc-win32-x64-msvc" "12.3.1" + +nextra-theme-docs@2.0.0-beta.29: + version "2.0.0-beta.29" + resolved "https://registry.yarnpkg.com/nextra-theme-docs/-/nextra-theme-docs-2.0.0-beta.29.tgz#febfaaee75bbe8bd0df744a4da5739c7b9594a8c" + integrity sha512-2oGsuOv7sMxnsYPM6+qI7F0Rcq9cMTtClwa8MeOdn0FCtMjhxJjfeLxpDvXrELkVNOU9/Bg1SFHxHTLpt0/Xjw== + dependencies: + "@headlessui/react" "^1.6.6" + "@mdx-js/react" "^2.1.2" + "@popperjs/core" "^2.11.6" + "@reach/skip-nav" "^0.17.0" + clsx "^1.2.1" + flexsearch "^0.7.21" + focus-visible "^5.2.0" + github-slugger "^1.4.0" + intersection-observer "^0.12.2" + match-sorter "^6.3.1" + next-themes "^0.2.0-beta.2" + parse-git-url "^1.0.1" + scroll-into-view-if-needed "^2.2.29" + +nextra@2.0.0-beta.29: + version "2.0.0-beta.29" + resolved "https://registry.yarnpkg.com/nextra/-/nextra-2.0.0-beta.29.tgz#128383f84e8bcf8826a2f2ad594db945268fcb0e" + integrity sha512-UjsaoMNsJRG0fbzqgoLDXgvJwcSJxwPr+ojBBjJsaZ6fu5+cwbCx8wXazA0y5sSxGw75fG6D1I7rS6pflHctuQ== + dependencies: + "@mdx-js/mdx" "^2.1.3" + "@napi-rs/simple-git" "^0.1.8" + github-slugger "^1.4.0" + graceful-fs "^4.2.10" + gray-matter "^4.0.3" + rehype-mdx-title "^1.0.0" + rehype-pretty-code "0.2.4" + remark-gfm "^3.0.1" + remark-reading-time "^2.0.1" + shiki "0.10.1" + slash "^3.0.0" + title "^3.5.3" + unist-util-visit "^4.1.1" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw== + dependencies: + path-key "^2.0.0" + +object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow== + +parse-entities@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-4.0.0.tgz#f67c856d4e3fe19b1a445c3fabe78dcdc1053eeb" + integrity sha512-5nk9Fn03x3rEhGaX1FU6IDwG/k+GxLXlFAkgrbM1asuAFl3BhdQWvASaIsmwWypRNcZKHPYnIuOSfIWEyEQnPQ== + dependencies: + "@types/unist" "^2.0.0" + character-entities "^2.0.0" + character-entities-legacy "^3.0.0" + character-reference-invalid "^2.0.0" + decode-named-character-reference "^1.0.0" + is-alphanumerical "^2.0.0" + is-decimal "^2.0.0" + is-hexadecimal "^2.0.0" + +parse-git-url@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parse-git-url/-/parse-git-url-1.0.1.tgz#92bdaf615a7e24d32bea3bf955ee90a9050aeb57" + integrity sha512-Zukjztu09UXpXV/Q+4vgwyVPzUBkUvDjlqHlpG+swv/zYzed/5Igw/33rIEJxFDRc5LxvEqYDVDzhBfnOLWDYw== + +parse-numeric-range@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz#7c63b61190d61e4d53a1197f0c83c47bb670ffa3" + integrity sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ== + +path-key@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw== + +periscopic@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/periscopic/-/periscopic-3.0.4.tgz#b3fbed0d1bc844976b977173ca2cd4a0ef4fa8d1" + integrity sha512-SFx68DxCv0Iyo6APZuw/AKewkkThGwssmU0QWtTlvov3VAtPX+QJ4CadwSaz8nrT5jPIuxdvJWB4PnD2KNDxQg== + dependencies: + estree-walker "^3.0.0" + is-reference "^3.0.0" + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +postcss@8.4.14: + version "8.4.14" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" + integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== + dependencies: + nanoid "^3.3.4" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +property-information@^6.0.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-6.1.1.tgz#5ca85510a3019726cb9afed4197b7b8ac5926a22" + integrity sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w== + +pseudomap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== + +react-dom@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" + integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + scheduler "^0.20.2" + +react@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" + integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +reading-time@^1.3.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/reading-time/-/reading-time-1.5.0.tgz#d2a7f1b6057cb2e169beaf87113cc3411b5bc5bb" + integrity sha512-onYyVhBNr4CmAxFsKS7bz+uTLRakypIe4R+5A824vBSkQy/hB3fZepoVEf8OVAxzLvK+H/jm9TzpI3ETSm64Kg== + +regenerator-runtime@^0.13.4: + version "0.13.9" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" + integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== + +rehype-mdx-title@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rehype-mdx-title/-/rehype-mdx-title-1.0.0.tgz#292598b5ad8af2c2bd01b3674caea1a44bb60f63" + integrity sha512-5B/53Y+KQHm4/nrE6pIIPc9Ie2fbPMCLs8WwMGYWWHr+5g3TkmEijRkr8TGYHULtc+C7bOoPR8LIF5DpGROIDg== + dependencies: + estree-util-is-identifier-name "^1.1.0" + hast-util-to-string "^1.0.4" + unist-util-visit "^2.0.3" + +rehype-pretty-code@0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/rehype-pretty-code/-/rehype-pretty-code-0.2.4.tgz#73b1e1c3ca7f50aaeeb131185a744a5ea936a08f" + integrity sha512-vbqwIa4cNwRaVur9caUw/b0jOQR88Svrs9c9RaQoogvbBxs5X9bWrSe5oFypaRTTq2cpZ45YzJQ7UUPO76LMKA== + dependencies: + parse-numeric-range "^1.3.0" + +remark-gfm@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-3.0.1.tgz#0b180f095e3036545e9dddac0e8df3fa5cfee54f" + integrity sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-gfm "^2.0.0" + micromark-extension-gfm "^2.0.0" + unified "^10.0.0" + +remark-mdx@^2.0.0: + version "2.1.3" + resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-2.1.3.tgz#6273e8b94d27ade35407a63bc8cdd04592f7be9f" + integrity sha512-3SmtXOy9+jIaVctL8Cs3VAQInjRLGOwNXfrBB9KCT+EpJpKD3PQiy0x8hUNGyjQmdyOs40BqgPU7kYtH9uoR6w== + dependencies: + mdast-util-mdx "^2.0.0" + micromark-extension-mdxjs "^1.0.0" + +remark-parse@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-10.0.1.tgz#6f60ae53edbf0cf38ea223fe643db64d112e0775" + integrity sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw== + dependencies: + "@types/mdast" "^3.0.0" + mdast-util-from-markdown "^1.0.0" + unified "^10.0.0" + +remark-reading-time@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/remark-reading-time/-/remark-reading-time-2.0.1.tgz#fe8bb8e420db7678dc749385167adb4fc99318f7" + integrity sha512-fy4BKy9SRhtYbEHvp6AItbRTnrhiDGbqLQTSYVbQPGuRCncU1ubSsh9p/W5QZSxtYcUXv8KGL0xBgPLyNJA1xw== + dependencies: + estree-util-is-identifier-name "^2.0.0" + estree-util-value-to-estree "^1.3.0" + reading-time "^1.3.0" + unist-util-visit "^3.1.0" + +remark-rehype@^10.0.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/remark-rehype/-/remark-rehype-10.1.0.tgz#32dc99d2034c27ecaf2e0150d22a6dcccd9a6279" + integrity sha512-EFmR5zppdBp0WQeDVZ/b66CWJipB2q2VLNFMabzDSGR66Z2fQii83G5gTBbgGEnEEA0QRussvrFHxk1HWGJskw== + dependencies: + "@types/hast" "^2.0.0" + "@types/mdast" "^3.0.0" + mdast-util-to-hast "^12.1.0" + unified "^10.0.0" + +remove-accents@0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.4.2.tgz#0a43d3aaae1e80db919e07ae254b285d9e1c7bb5" + integrity sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA== + +sade@^1.7.3: + version "1.8.1" + resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" + integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== + dependencies: + mri "^1.1.0" + +scheduler@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.20.2.tgz#4baee39436e34aa93b4874bddcbf0fe8b8b50e91" + integrity sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +scroll-into-view-if-needed@^2.2.29: + version "2.2.29" + resolved "https://registry.yarnpkg.com/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.29.tgz#551791a84b7e2287706511f8c68161e4990ab885" + integrity sha512-hxpAR6AN+Gh53AdAimHM6C8oTN1ppwVZITihix+WqalywBeFcQ6LdQP5ABNl26nX8GTEL7VT+b8lKpdqq65wXg== + dependencies: + compute-scroll-into-view "^1.0.17" + +section-matter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" + integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA== + dependencies: + extend-shallow "^2.0.1" + kind-of "^6.0.0" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg== + dependencies: + shebang-regex "^1.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ== + +shiki@0.10.1: + version "0.10.1" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.10.1.tgz#6f9a16205a823b56c072d0f1a0bcd0f2646bef14" + integrity sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng== + dependencies: + jsonc-parser "^3.0.0" + vscode-oniguruma "^1.6.1" + vscode-textmate "5.2.0" + +signal-exit@^3.0.0: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +source-map@^0.7.0: + version "0.7.4" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.4.tgz#a9bbe705c9d8846f4e08ff6765acf0f1b0898656" + integrity sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA== + +space-separated-tokens@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-2.0.1.tgz#43193cec4fb858a2ce934b7f98b7f2c18107098b" + integrity sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw== + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stringify-entities@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.3.tgz#cfabd7039d22ad30f3cc435b0ca2c1574fc88ef8" + integrity sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g== + dependencies: + character-entities-html4 "^2.0.0" + character-entities-legacy "^3.0.0" + +strip-bom-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" + integrity sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g== + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== + +style-to-object@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" + integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== + dependencies: + inline-style-parser "0.1.1" + +styled-jsx@5.0.7: + version "5.0.7" + resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.7.tgz#be44afc53771b983769ac654d355ca8d019dff48" + integrity sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA== + +supports-color@^4.0.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + integrity sha512-ycQR/UbvI9xIlEdQT1TQqwoXtEldExbCEAJgRo5YXlmSKjv6ThHnP9/vwGa1gr19Gfw+LkFd7KqYMhzrRC5JYw== + dependencies: + has-flag "^2.0.0" + +tiny-warning@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + +title@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/title/-/title-3.5.3.tgz#b338d701a3d949db6b49b2c86f409f9c2f36cd91" + integrity sha512-20JyowYglSEeCvZv3EZ0nZ046vLarO37prvV0mbtQV7C8DJPGgN967r8SJkqd3XK3K3lD3/Iyfp3avjfil8Q2Q== + dependencies: + arg "1.0.0" + chalk "2.3.0" + clipboardy "1.2.2" + titleize "1.0.0" + +titleize@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/titleize/-/titleize-1.0.0.tgz#7d350722061830ba6617631e0cfd3ea08398d95a" + integrity sha512-TARUb7z1pGvlLxgPk++7wJ6aycXF3GJ0sNSBTAsTuJrQG5QuZlkUQP+zl+nbjAh4gMX9yDw9ZYklMd7vAfJKEw== + +trim-lines@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" + integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg== + +trough@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/trough/-/trough-2.1.0.tgz#0f7b511a4fde65a46f18477ab38849b22c554876" + integrity sha512-AqTiAOLcj85xS7vQ8QkAV41hPDIJ71XJB4RCUrzo/1GM2CQwhkJGaf9Hgr7BOugMRpgGUrqRg/DrBDl4H40+8g== + +tslib@^2.3.0, tslib@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + +unified@^10.0.0: + version "10.1.2" + resolved "https://registry.yarnpkg.com/unified/-/unified-10.1.2.tgz#b1d64e55dafe1f0b98bb6c719881103ecf6c86df" + integrity sha512-pUSWAi/RAnVy1Pif2kAoeWNBa3JVrx0MId2LASj8G+7AiHWoKZNTomq6LG326T68U7/e263X6fTdcXIy7XnF7Q== + dependencies: + "@types/unist" "^2.0.0" + bail "^2.0.0" + extend "^3.0.0" + is-buffer "^2.0.0" + is-plain-obj "^4.0.0" + trough "^2.0.0" + vfile "^5.0.0" + +unist-builder@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-3.0.0.tgz#728baca4767c0e784e1e64bb44b5a5a753021a04" + integrity sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ== + dependencies: + "@types/unist" "^2.0.0" + +unist-util-generated@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-2.0.0.tgz#86fafb77eb6ce9bfa6b663c3f5ad4f8e56a60113" + integrity sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw== + +unist-util-is@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.1.0.tgz#976e5f462a7a5de73d94b706bac1b90671b57797" + integrity sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg== + +unist-util-is@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-5.1.1.tgz#e8aece0b102fa9bc097b0fef8f870c496d4a6236" + integrity sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ== + +unist-util-position-from-estree@^1.0.0, unist-util-position-from-estree@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unist-util-position-from-estree/-/unist-util-position-from-estree-1.1.1.tgz#96f4d543dfb0428edc01ebb928570b602d280c4c" + integrity sha512-xtoY50b5+7IH8tFbkw64gisG9tMSpxDjhX9TmaJJae/XuxQ9R/Kc8Nv1eOsf43Gt4KV/LkriMy9mptDr7XLcaw== + dependencies: + "@types/unist" "^2.0.0" + +unist-util-position@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-4.0.3.tgz#5290547b014f6222dff95c48d5c3c13a88fadd07" + integrity sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ== + dependencies: + "@types/unist" "^2.0.0" + +unist-util-remove-position@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-4.0.1.tgz#d5b46a7304ac114c8d91990ece085ca7c2c135c8" + integrity sha512-0yDkppiIhDlPrfHELgB+NLQD5mfjup3a8UYclHruTJWmY74je8g+CIFr79x5f6AkmzSwlvKLbs63hC0meOMowQ== + dependencies: + "@types/unist" "^2.0.0" + unist-util-visit "^4.0.0" + +unist-util-stringify-position@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.2.tgz#5c6aa07c90b1deffd9153be170dce628a869a447" + integrity sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg== + dependencies: + "@types/unist" "^2.0.0" + +unist-util-visit-parents@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" + integrity sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + +unist-util-visit-parents@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-4.1.1.tgz#e83559a4ad7e6048a46b1bdb22614f2f3f4724f2" + integrity sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + +unist-util-visit-parents@^5.0.0, unist-util-visit-parents@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-5.1.1.tgz#868f353e6fce6bf8fa875b251b0f4fec3be709bb" + integrity sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + +unist-util-visit@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" + integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + unist-util-visit-parents "^3.0.0" + +unist-util-visit@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-3.1.0.tgz#9420d285e1aee938c7d9acbafc8e160186dbaf7b" + integrity sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-visit-parents "^4.0.0" + +unist-util-visit@^4.0.0, unist-util-visit@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-4.1.1.tgz#1c4842d70bd3df6cc545276f5164f933390a9aad" + integrity sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^5.0.0" + unist-util-visit-parents "^5.1.1" + +use-sync-external-store@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" + integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== + +uvu@^0.5.0: + version "0.5.6" + resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df" + integrity sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA== + dependencies: + dequal "^2.0.0" + diff "^5.0.0" + kleur "^4.0.3" + sade "^1.7.3" + +vfile-location@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-4.0.1.tgz#06f2b9244a3565bef91f099359486a08b10d3a95" + integrity sha512-JDxPlTbZrZCQXogGheBHjbRWjESSPEak770XwWPfw5mTc1v1nWGLB/apzZxsx8a0SJVfF8HK8ql8RD308vXRUw== + dependencies: + "@types/unist" "^2.0.0" + vfile "^5.0.0" + +vfile-message@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-3.1.2.tgz#a2908f64d9e557315ec9d7ea3a910f658ac05f7d" + integrity sha512-QjSNP6Yxzyycd4SVOtmKKyTsSvClqBPJcd00Z0zuPj3hOIjg0rUPG6DbFGPvUKRgYyaIWLPKpuEclcuvb3H8qA== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^3.0.0" + +vfile@^5.0.0: + version "5.3.5" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-5.3.5.tgz#ec2e206b1414f561c85b7972bb1eeda8ab47ee61" + integrity sha512-U1ho2ga33eZ8y8pkbQLH54uKqGhFJ6GYIHnnG5AhRpAh3OWjkrRHKa/KogbmQn8We+c0KVV3rTOgR9V/WowbXQ== + dependencies: + "@types/unist" "^2.0.0" + is-buffer "^2.0.0" + unist-util-stringify-position "^3.0.0" + vfile-message "^3.0.0" + +vscode-oniguruma@^1.6.1: + version "1.6.2" + resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz#aeb9771a2f1dbfc9083c8a7fdd9cccaa3f386607" + integrity sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA== + +vscode-textmate@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" + integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== + +which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +yallist@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== + +zwitch@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.2.tgz#91f8d0e901ffa3d66599756dde7f57b17c95dce1" + integrity sha512-JZxotl7SxAJH0j7dN4pxsTV6ZLXoLdGME+PsjkL/DaBrVryK9kTGq06GfKrwcSOqypP+fdXGoCHE36b99fWVoA== diff --git a/package.json b/package.json index b8ac7659b..2dbdaedea 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ "test": "yarn lerna exec yarn test", "build": "tsc --build", "build:watch": "tsc --build --watch", + "docs:build": "cd docs && yarn build", + "docs:start": "cd docs && yarn start", "pretest": "yarn build", "prepublish": "yarn build", "lint": "eslint '*/**/*.{js,ts,tsx}'" From c7dc7fd93a1558e6d0f18e30c49cc7daf2a2bd76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 15 Oct 2022 12:55:47 -0500 Subject: [PATCH 0831/1037] Bump pgpass from 1.0.2 to 1.0.5 (#2827) Bumps [pgpass](https://github.com/hoegaarden/pgpass) from 1.0.2 to 1.0.5. - [Release notes](https://github.com/hoegaarden/pgpass/releases) - [Commits](https://github.com/hoegaarden/pgpass/compare/v1.0.2...v1.0.5) --- updated-dependencies: - dependency-name: pgpass dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9cd0b3c06..6fb12ffc8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4836,11 +4836,11 @@ pg-types@^2.1.0: postgres-interval "^1.1.0" pgpass@1.x: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.2.tgz#2a7bb41b6065b67907e91da1b07c1847c877b306" - integrity sha1-Knu0G2BltnkH6R2hsHwYR8h3swY= + version "1.0.5" + resolved "https://registry.yarnpkg.com/pgpass/-/pgpass-1.0.5.tgz#9b873e4a564bb10fa7a7dbd55312728d422a223d" + integrity sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug== dependencies: - split "^1.0.0" + split2 "^4.1.0" picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: version "2.2.2" @@ -5593,6 +5593,11 @@ split2@^2.0.0: dependencies: through2 "^2.0.2" +split2@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/split2/-/split2-4.1.0.tgz#101907a24370f85bb782f08adaabe4e281ecf809" + integrity sha512-VBiJxFkxiXRlUIeyMQi8s4hgvKCSjtknJv/LVYbrgALPwf5zSKmEwV9Lst25AkvMDnvxODugjdl6KZgwKM1WYQ== + split@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/split/-/split-1.0.1.tgz#605bd9be303aa59fb35f9229fbea0ddec9ea07d9" From 406f141a1a62350a632b3182f7a3a0877d7bbe53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Sat, 15 Oct 2022 19:57:16 +0200 Subject: [PATCH 0832/1037] perf: remove superfluous flush message (#2842) --- packages/pg/lib/connection.js | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index ebb2f099d..fe04efb6b 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -173,7 +173,6 @@ class Connection extends EventEmitter { sync() { this._ending = true - this._send(flushBuffer) this._send(syncBuffer) } From 5538df6b446f4b4f921947b460fe38acb897e579 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 15 Oct 2022 12:57:41 -0500 Subject: [PATCH 0833/1037] Bump @typescript-eslint/eslint-plugin from 4.4.0 to 4.33.0 (#2826) Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 4.4.0 to 4.33.0. - [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases) - [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md) - [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.33.0/packages/eslint-plugin) --- updated-dependencies: - dependency-name: "@typescript-eslint/eslint-plugin" dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 187 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 143 insertions(+), 44 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6fb12ffc8..a24466c1a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -954,10 +954,10 @@ "@types/minimatch" "*" "@types/node" "*" -"@types/json-schema@^7.0.3": - version "7.0.6" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" - integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== +"@types/json-schema@^7.0.7": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== "@types/minimatch@*": version "3.0.3" @@ -1013,29 +1013,30 @@ "@types/pg-types" "*" "@typescript-eslint/eslint-plugin@^4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.4.0.tgz#0321684dd2b902c89128405cf0385e9fe8561934" - integrity sha512-RVt5wU9H/2H+N/ZrCasTXdGbUTkbf7Hfi9eLiA8vPQkzUJ/bLDCC3CsoZioPrNcnoyN8r0gT153dC++A4hKBQQ== + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.33.0.tgz#c24dc7c8069c7706bc40d99f6fa87edcb2005276" + integrity sha512-aINiAxGVdOl1eJyVjaWn/YcVAq4Gi/Yo35qHGCnqbWVz61g39D0h23veY/MA0rFFGfxK7TySg2uwDeNv+JgVpg== dependencies: - "@typescript-eslint/experimental-utils" "4.4.0" - "@typescript-eslint/scope-manager" "4.4.0" - debug "^4.1.1" + "@typescript-eslint/experimental-utils" "4.33.0" + "@typescript-eslint/scope-manager" "4.33.0" + debug "^4.3.1" functional-red-black-tree "^1.0.1" - regexpp "^3.0.0" - semver "^7.3.2" - tsutils "^3.17.1" - -"@typescript-eslint/experimental-utils@4.4.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.4.0.tgz#62a05d3f543b8fc5dec4982830618ea4d030e1a9" - integrity sha512-01+OtK/oWeSJTjQcyzDztfLF1YjvKpLFo+JZmurK/qjSRcyObpIecJ4rckDoRCSh5Etw+jKfdSzVEHevh9gJ1w== - dependencies: - "@types/json-schema" "^7.0.3" - "@typescript-eslint/scope-manager" "4.4.0" - "@typescript-eslint/types" "4.4.0" - "@typescript-eslint/typescript-estree" "4.4.0" - eslint-scope "^5.0.0" - eslint-utils "^2.0.0" + ignore "^5.1.8" + regexpp "^3.1.0" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/experimental-utils@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz#6f2a786a4209fa2222989e9380b5331b2810f7fd" + integrity sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q== + dependencies: + "@types/json-schema" "^7.0.7" + "@typescript-eslint/scope-manager" "4.33.0" + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/typescript-estree" "4.33.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" "@typescript-eslint/parser@^4.4.0": version "4.4.0" @@ -1047,6 +1048,14 @@ "@typescript-eslint/typescript-estree" "4.4.0" debug "^4.1.1" +"@typescript-eslint/scope-manager@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz#d38e49280d983e8772e29121cf8c6e9221f280a3" + integrity sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + "@typescript-eslint/scope-manager@4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.4.0.tgz#2f3dd27692a12cc9a046a90ba6a9d8cb7731190a" @@ -1055,11 +1064,29 @@ "@typescript-eslint/types" "4.4.0" "@typescript-eslint/visitor-keys" "4.4.0" +"@typescript-eslint/types@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.33.0.tgz#a1e59036a3b53ae8430ceebf2a919dc7f9af6d72" + integrity sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ== + "@typescript-eslint/types@4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.4.0.tgz#63440ef87a54da7399a13bdd4b82060776e9e621" integrity sha512-nU0VUpzanFw3jjX+50OTQy6MehVvf8pkqFcURPAE06xFNFenMj1GPEI6IESvp7UOHAnq+n/brMirZdR+7rCrlA== +"@typescript-eslint/typescript-estree@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz#0dfb51c2908f68c5c08d82aefeaf166a17c24609" + integrity sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA== + dependencies: + "@typescript-eslint/types" "4.33.0" + "@typescript-eslint/visitor-keys" "4.33.0" + debug "^4.3.1" + globby "^11.0.3" + is-glob "^4.0.1" + semver "^7.3.5" + tsutils "^3.21.0" + "@typescript-eslint/typescript-estree@4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.4.0.tgz#16a2df7c16710ddd5406b32b86b9c1124b1ca526" @@ -1074,6 +1101,14 @@ semver "^7.3.2" tsutils "^3.17.1" +"@typescript-eslint/visitor-keys@4.33.0": + version "4.33.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz#2a22f77a41604289b7a186586e9ec48ca92ef1dd" + integrity sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg== + dependencies: + "@typescript-eslint/types" "4.33.0" + eslint-visitor-keys "^2.0.0" + "@typescript-eslint/visitor-keys@4.4.0": version "4.4.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.4.0.tgz#0a9118344082f14c0f051342a74b42dfdb012640" @@ -1468,7 +1503,7 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.1, braces@~3.0.2: +braces@^3.0.1, braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -2048,10 +2083,10 @@ debug@^2.2.0, debug@^2.3.3: dependencies: ms "2.0.0" -debug@^4.0.1, debug@^4.1.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" - integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== +debug@^4.0.1, debug@^4.1.1, debug@^4.3.1: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" @@ -2387,7 +2422,7 @@ eslint-plugin-promise@^6.0.1: resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-6.0.1.tgz#a8cddf96a67c4059bdabf4d724a29572188ae423" integrity sha512-uM4Tgo5u3UWQiroOyDEsYcVMOo7re3zmno0IZmB5auxoaQNIceAbXEkSt8RNrKtaYehARHG06pYK6K1JhtP0Zw== -eslint-scope@^5.0.0, eslint-scope@^5.1.1: +eslint-scope@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== @@ -2402,6 +2437,13 @@ eslint-utils@^2.0.0, eslint-utils@^2.1.0: dependencies: eslint-visitor-keys "^1.1.0" +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" @@ -2631,6 +2673,17 @@ fast-glob@^3.1.1: micromatch "^4.0.2" picomatch "^2.2.1" +fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -2961,6 +3014,13 @@ glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: dependencies: is-glob "^4.0.1" +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + glob-to-regexp@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" @@ -3020,6 +3080,18 @@ globby@^11.0.1: merge2 "^1.3.0" slash "^3.0.0" +globby@^11.0.3: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + globby@^9.2.0: version "9.2.0" resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" @@ -3215,10 +3287,10 @@ ignore@^4.0.3, ignore@^4.0.6: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.1.1, ignore@^5.1.4: - version "5.1.8" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" - integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== +ignore@^5.1.1, ignore@^5.1.4, ignore@^5.1.8, ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== import-fresh@^2.0.0: version "2.0.0" @@ -3898,6 +3970,13 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + macgyver@~1.10: version "1.10.1" resolved "https://registry.yarnpkg.com/macgyver/-/macgyver-1.10.1.tgz#b09d1599d8b36ed5b16f59589515d9d14bc2fd88" @@ -4020,7 +4099,7 @@ meow@^7.0.0: type-fest "^0.13.1" yargs-parser "^18.1.3" -merge2@^1.2.3, merge2@^1.3.0: +merge2@^1.2.3, merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -4052,6 +4131,14 @@ micromatch@^4.0.2: braces "^3.0.1" picomatch "^2.0.5" +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + mime-db@1.44.0: version "1.44.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" @@ -4847,6 +4934,11 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -5374,10 +5466,12 @@ semver@^6.0.0, semver@^6.1.0, semver@^6.2.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== -semver@^7.2.1, semver@^7.3.2: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== +semver@^7.2.1, semver@^7.3.2, semver@^7.3.5: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" @@ -6012,10 +6106,10 @@ tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tsutils@^3.17.1: - version "3.17.1" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" - integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== +tsutils@^3.17.1, tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== dependencies: tslib "^1.8.1" @@ -6366,6 +6460,11 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.1.1: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yargs-parser@13.1.2, yargs-parser@^13.1.2: version "13.1.2" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" From 89b4e7f2a2bb6d663fcc96b352572c52eb69feb7 Mon Sep 17 00:00:00 2001 From: "Ryan B. Harvey" Date: Fri, 28 Oct 2022 00:56:53 -0500 Subject: [PATCH 0834/1037] Fix devcontainer build failure due to env var being interpreted as non-string (#2844) --- .devcontainer/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 11c8c9f3b..05475b824 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -27,7 +27,7 @@ services: PGHOST: db # set this to true in the development environment until I can get SSL setup on the # docker postgres instance - PGTESTNOSSL: true + PGTESTNOSSL: 'true' # Overrides default command so things don't shut down after the process ends. command: sleep infinity From 0965531cdaed208f273f5c193dbee912ce835aa1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Nov 2022 00:29:25 -0500 Subject: [PATCH 0835/1037] Bump typescript from 4.0.3 to 4.8.4 (#2850) Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.0.3 to 4.8.4. - [Release notes](https://github.com/Microsoft/TypeScript/releases) - [Commits](https://github.com/Microsoft/TypeScript/compare/v4.0.3...v4.8.4) --- updated-dependencies: - dependency-name: typescript dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index a24466c1a..5fc372e9e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6170,9 +6170,9 @@ typedarray@^0.0.6: integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= typescript@^4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.3.tgz#153bbd468ef07725c1df9c77e8b453f8d36abba5" - integrity sha512-tEu6DGxGgRJPb/mVPIZ48e69xCn2yRmCgYmDugAVwmJ6o+0u1RI18eO7E7WBTLYLaEVVOhwQmcdhQHweux/WPg== + version "4.8.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.8.4.tgz#c464abca159669597be5f96b8943500b238e60e6" + integrity sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ== uglify-js@^3.1.4: version "3.13.5" From c253eb669699f5d72f29b30ccfbf934bc7360a95 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 4 Nov 2022 00:30:19 -0500 Subject: [PATCH 0836/1037] Bump chai from 4.2.0 to 4.3.6 (#2851) Bumps [chai](https://github.com/chaijs/chai) from 4.2.0 to 4.3.6. - [Release notes](https://github.com/chaijs/chai/releases) - [Changelog](https://github.com/chaijs/chai/blob/4.x.x/History.md) - [Commits](https://github.com/chaijs/chai/compare/4.2.0...v4.3.6) --- updated-dependencies: - dependency-name: chai dependency-type: direct:development update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- yarn.lock | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 5fc372e9e..3a4d75a98 100644 --- a/yarn.lock +++ b/yarn.lock @@ -942,9 +942,9 @@ "@types/node" ">= 8" "@types/chai@^4.2.13", "@types/chai@^4.2.7": - version "4.2.13" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.13.tgz#8a3801f6655179d1803d81e94a2e4aaf317abd16" - integrity sha512-o3SGYRlOpvLFpwJA6Sl1UPOwKFEvE4FxTEB/c9XHI2whdnd4kmPVkNLL8gY4vWGBxWWDumzLbKsAhEH5SKn37Q== + version "4.3.3" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.3.tgz#3c90752792660c4b562ad73b3fbd68bf3bc7ae07" + integrity sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g== "@types/glob@^7.1.1": version "7.1.3" @@ -1657,15 +1657,16 @@ caseless@~0.12.0: integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= chai@^4.1.1, chai@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5" - integrity sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw== + version "4.3.6" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" + integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== dependencies: assertion-error "^1.1.0" check-error "^1.0.2" deep-eql "^3.0.1" get-func-name "^2.0.0" - pathval "^1.1.0" + loupe "^2.3.1" + pathval "^1.1.1" type-detect "^4.0.5" chalk@^2.0.0, chalk@^2.3.1, chalk@^2.4.2: @@ -3963,6 +3964,13 @@ loud-rejection@^1.0.0: currently-unhandled "^0.4.1" signal-exit "^3.0.0" +loupe@^2.3.1: + version "2.3.4" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" + integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== + dependencies: + get-func-name "^2.0.0" + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -4886,7 +4894,7 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pathval@^1.1.0: +pathval@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== From 15b502d4c1ae3a85c2cdeb0e474f72297d4f63ba Mon Sep 17 00:00:00 2001 From: Frazer Smith Date: Sun, 6 Nov 2022 01:26:42 +0000 Subject: [PATCH 0837/1037] refactor(pg): remove unused imports (#2854) --- packages/pg/lib/client.js | 1 - packages/pg/lib/native/client.js | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 18238f6fb..82d571d8a 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -1,7 +1,6 @@ 'use strict' var EventEmitter = require('events').EventEmitter -var util = require('util') var utils = require('./utils') var sasl = require('./sasl') var pgPass = require('pgpass') diff --git a/packages/pg/lib/native/client.js b/packages/pg/lib/native/client.js index d1faeb3d8..58fc4aeaa 100644 --- a/packages/pg/lib/native/client.js +++ b/packages/pg/lib/native/client.js @@ -3,7 +3,6 @@ // eslint-disable-next-line var Native = require('pg-native') var TypeOverrides = require('../type-overrides') -var pkg = require('../../package.json') var EventEmitter = require('events').EventEmitter var util = require('util') var ConnectionParameters = require('../connection-parameters') From c7133eb67fec1b96735918c11549a0b69d52505d Mon Sep 17 00:00:00 2001 From: Frazer Smith Date: Tue, 8 Nov 2022 19:24:39 +0000 Subject: [PATCH 0838/1037] ci: remove git credentials after checkout (#2858) --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73e5709d3..8e0f098c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,6 +25,8 @@ jobs: name: Node.js ${{ matrix.node }} (${{ matrix.os }}) steps: - uses: actions/checkout@v3 + with: + persist-credentials: false - name: Setup node uses: actions/setup-node@v3 with: From c7dc621d3fb52c158eb23aa31dea6bd440700a4a Mon Sep 17 00:00:00 2001 From: Charmander <~@charmander.me> Date: Mon, 21 Nov 2022 09:57:30 -0800 Subject: [PATCH 0839/1037] pg-cursor: Fix errors only being sent to half the queue (#2831) * pg-cursor: Add failing test for errors on queued reads * pg-cursor: Fix errors being sent to only half the queue --- packages/pg-cursor/index.js | 4 +++- packages/pg-cursor/test/error-handling.js | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/packages/pg-cursor/index.js b/packages/pg-cursor/index.js index 9bbda641a..d3c0266b0 100644 --- a/packages/pg-cursor/index.js +++ b/packages/pg-cursor/index.js @@ -171,8 +171,10 @@ class Cursor extends EventEmitter { } // dispatch error to all waiting callbacks for (let i = 0; i < this._queue.length; i++) { - this._queue.pop()[1](msg) + const queuedCallback = this._queue[i][1] + queuedCallback.call(this, msg) } + this._queue.length = 0 if (this.listenerCount('error') > 0) { // only dispatch error events if we have a listener diff --git a/packages/pg-cursor/test/error-handling.js b/packages/pg-cursor/test/error-handling.js index f6edef6d5..22620bd83 100644 --- a/packages/pg-cursor/test/error-handling.js +++ b/packages/pg-cursor/test/error-handling.js @@ -19,6 +19,23 @@ describe('error handling', function () { }) }) }) + + it('errors queued reads', async () => { + const client = new pg.Client() + await client.connect() + + const cursor = client.query(new Cursor('asdfdffsdf')) + + const immediateRead = cursor.read(1) + const queuedRead1 = cursor.read(1) + const queuedRead2 = cursor.read(1) + + assert(await immediateRead.then(() => null, (err) => err)) + assert(await queuedRead1.then(() => null, (err) => err)) + assert(await queuedRead2.then(() => null, (err) => err)) + + client.end() + }) }) describe('read callback does not fire sync', () => { From 12b9a697769b422ad491de3875320665e5a6c61a Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 23 Nov 2022 15:08:09 -0600 Subject: [PATCH 0840/1037] update docs - clean up interface (#2863) * update docs - clean up interface * Remove node v8.x from test matrix --- .github/workflows/ci.yml | 2 +- SPONSORS.md | 2 + docs/pages/apis/client.mdx | 91 ++++++++++++++++++-------------------- docs/pages/apis/pool.mdx | 8 +++- docs/pages/index.mdx | 15 +------ 5 files changed, 53 insertions(+), 65 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8e0f098c1..97f4013ba 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,7 @@ jobs: options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 strategy: matrix: - node: ['8', '10', '12', '14', '16', '18'] + node: ['10', '12', '14', '16', '18'] os: [ubuntu-latest, windows-latest, macos-latest] name: Node.js ${{ matrix.node }} (${{ matrix.os }}) steps: diff --git a/SPONSORS.md b/SPONSORS.md index 3bebb01eb..c16b8d3df 100644 --- a/SPONSORS.md +++ b/SPONSORS.md @@ -16,6 +16,7 @@ node-postgres is made possible by the helpful contributors from the community as - [@BLUE-DEVIL1134](https://github.com/BLUE-DEVIL1134) - [bubble.io](https://bubble.io/) - GitHub[https://github.com/github] +- loveland [https://github.com/loveland] # Supporters @@ -48,3 +49,4 @@ node-postgres is made possible by the helpful contributors from the community as - [Scout APM](https://github.com/scoutapm-sponsorships) - [Sideline Sports](https://github.com/SidelineSports) - [Gadget](https://github.com/gadget-inc) +- [Sentry](https://sentry.io/welcome/) diff --git a/docs/pages/apis/client.mdx b/docs/pages/apis/client.mdx index c983859b6..92268bed8 100644 --- a/docs/pages/apis/client.mdx +++ b/docs/pages/apis/client.mdx @@ -41,8 +41,6 @@ const client = new Client({ ## client.connect -### `client.connect(callback: (err: Error) => void) => void` - Calling `client.connect` with a callback: ```js @@ -57,8 +55,6 @@ client.connect((err) => { }) ``` -### `client.connect() => Promise` - Calling `client.connect` without a callback yields a promise: ```js @@ -74,19 +70,35 @@ _note: connect returning a promise only available in pg@7.0 or above_ ## client.query -### `client.query` - text, optional values, and callback. +### QueryConfig -Passing query text, optional query parameters, and a callback to `client.query` results in a type-signature of: +You can pass an object to `client.query` with the signature of: ```ts -client.query( - text: string, - values?: Array, - callback: (err: Error, result: Result) => void -) => void +type QueryConfig { + // the raw query text + text: string; + + // an array of query parameters + values?: Array; + + // name of the query - used for prepared statements + name?: string; + + // by default rows come out as a key/value pair for each row + // pass the string 'array' here to receive rows as an array of values + rowMode?: string; + + // custom type parsers just for this query result + types?: Types; +} ``` -That is a kinda gross type signature but it translates out to this: +### callback API + +```ts +client.query(text: string, values?: any[], callback?: (err: Error, result: QueryResult) => void) => void +``` **Plain text query with a callback:** @@ -114,15 +126,12 @@ client.query('SELECT $1::text as name', ['brianc'], (err, res) => { }) ``` -### `client.query` - text, optional values: Promise +### Promise API If you call `client.query` with query text and optional parameters but **don't** pass a callback, then you will receive a `Promise` for a query result. ```ts -client.query( - text: string, - values?: Array -) => Promise +client.query(text: string, values?: any[]) => Promise ``` **Plain text query with a promise** @@ -151,30 +160,8 @@ client .then(() => client.end()) ``` -### `client.query(config: QueryConfig, callback: (err?: Error, result?: Result) => void) => void` - -### `client.query(config: QueryConfig) => Promise` - -You can pass an object to `client.query` with the signature of: - ```ts -type QueryConfig { - // the raw query text - text: string; - - // an array of query parameters - values?: Array; - - // name of the query - used for prepared statements - name?: string; - - // by default rows come out as a key/value pair for each row - // pass the string 'array' here to receive rows as an array of values - rowMode?: string; - - // custom type parsers just for this query result - types?: Types; -} +client.query(config: QueryConfig) => Promise ``` **client.query with a QueryConfig and a callback** @@ -246,8 +233,6 @@ query.on('error', (err) => { ## client.end -### client.end(cb?: (err?: Error) => void) => void - Disconnects the client from the PostgreSQL server. ```js @@ -259,8 +244,6 @@ client.end((err) => { }) ``` -### `client.end() => Promise` - Calling end without a callback yields a promise: ```js @@ -274,7 +257,11 @@ _note: end returning a promise is only available in pg7.0 and above_ ## events -### client.on('error', (err: Error) => void) => void +### error + +```ts +client.on('error', (err: Error) => void) => void +``` When the client is in the process of connecting, dispatching a query, or disconnecting it will catch and foward errors from the PostgreSQL server to the respective `client.connect` `client.query` or `client.end` callback/promise; however, the client maintains a long-lived connection to the PostgreSQL back-end and due to network partitions, back-end crashes, fail-overs, etc the client can (and over a long enough time period _will_) eventually be disconnected while it is idle. To handle this you may want to attach an error listener to a client to catch errors. Here's a contrived example: @@ -291,11 +278,15 @@ client.on('error', (err) => { // process output: 'something bad has happened!' followed by stacktrace :P ``` -### client.on('end') => void +### end + +```ts +client.on('end') => void +``` When the client disconnects from the PostgreSQL server it will emit an end event once. -### client.on('notification', (notification: Notification) => void) => void +### notification Used for `listen/notify` events: @@ -321,7 +312,11 @@ client.on('notification', (msg) => { client.query(`NOTIFY foo, 'bar!'`) ``` -### client.on('notice', (notice: Error) => void) => void +### notice + +```ts +client.on('notice', (notice: Error) => void) => void +``` Used to log out [notice messages](https://www.postgresql.org/docs/9.6/static/plpgsql-errors-and-messages.html) from the PostgreSQL server. diff --git a/docs/pages/apis/pool.mdx b/docs/pages/apis/pool.mdx index 6ebc19044..497e5253f 100644 --- a/docs/pages/apis/pool.mdx +++ b/docs/pages/apis/pool.mdx @@ -63,7 +63,9 @@ const pool = new Pool({ Often we only need to run a single query on the database, so as convenience the pool has a method to run a query on the first available idle client and return its result. -`pool.query() => Promise` +```ts +pool.query(text: string, values?: any[]) => Promise +``` ```js const { Pool } = require('pg') @@ -78,7 +80,9 @@ pool Callbacks are also supported: -`pool.query(callback: (err?: Error, result: pg.Result)) => void` +```ts +pool.query(text: string, values?: any[], callback?: (err?: Error, result: pg.Result)) => void +``` ```js const { Pool } = require('pg') diff --git a/docs/pages/index.mdx b/docs/pages/index.mdx index 234cf11e1..2e14116b5 100644 --- a/docs/pages/index.mdx +++ b/docs/pages/index.mdx @@ -13,20 +13,7 @@ $ npm install pg ## Supporters -node-postgres continued development and support is made possible by the many [supporters](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) with a special thanks to our featured supporters: - -
-
- - crate.io - -
-
- - eaze.com - -
-
+node-postgres continued development and support is made possible by the many [supporters](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md). If you or your company would like to sponsor node-postgres stop by [github sponsors](https://github.com/sponsors/brianc) and sign up or feel free to [email me](mailto:brian@pecanware.com) if you want to add your logo to the documentation or discuss higher tiers of sponsorship! From 27d612a2ac2df8737397019a5806f745f19b760e Mon Sep 17 00:00:00 2001 From: Brian C Date: Wed, 23 Nov 2022 21:50:36 -0600 Subject: [PATCH 0841/1037] Update docs (#2867) - fix config warnings - add search bar - add google analytics --- docs/theme.config.js | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/docs/theme.config.js b/docs/theme.config.js index 1ec4941ad..4ab2b8d23 100644 --- a/docs/theme.config.js +++ b/docs/theme.config.js @@ -1,16 +1,26 @@ // theme.config.js export default { - projectLink: 'https://github.com/brianc/node-postgres', // GitHub link in the navbar - docsRepositoryBase: 'https://github.com/brianc/node-postgres/blob/master', // base URL for the docs repository + project: { + link: 'https://github.com/brianc/node-postgres', + }, + twitter: { + cardType: 'summary_large_image', + site: 'https://node-postgres.com', + }, + docsRepositoryBase: 'https://github.com/brianc/node-postgres/blob/master/docs', // base URL for the docs repository titleSuffix: ' – node-postgres', - nextLinks: true, - prevLinks: true, - search: true, - customSearch: null, // customizable, you can use algolia for example darkMode: true, footer: true, - footerText: `MIT ${new Date().getFullYear()} © Brian Carlson.`, - footerEditLink: `Edit this page on GitHub`, + navigation: { + prev: true, + next: true, + }, + footer: { + text: `MIT ${new Date().getFullYear()} © Brian Carlson.`, + }, + editLink: { + text: 'Edit this page on GitHub', + }, logo: ( <> ... @@ -22,6 +32,20 @@ export default { + + ), } From 16118cecdd777ff077b70484cb39abf19f5a22f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Dec 2022 22:02:31 -0600 Subject: [PATCH 0842/1037] Bump eslint-config-prettier from 6.12.0 to 8.5.0 (#2875) Bumps [eslint-config-prettier](https://github.com/prettier/eslint-config-prettier) from 6.12.0 to 8.5.0. - [Release notes](https://github.com/prettier/eslint-config-prettier/releases) - [Changelog](https://github.com/prettier/eslint-config-prettier/blob/main/CHANGELOG.md) - [Commits](https://github.com/prettier/eslint-config-prettier/compare/v6.12.0...v8.5.0) --- updated-dependencies: - dependency-name: eslint-config-prettier dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 15 ++++----------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/package.json b/package.json index 2dbdaedea..dfd9b0312 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "@typescript-eslint/eslint-plugin": "^4.4.0", "@typescript-eslint/parser": "^4.4.0", "eslint": "^7.11.0", - "eslint-config-prettier": "^6.12.0", + "eslint-config-prettier": "^8.5.0", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prettier": "^3.1.4", "lerna": "^3.19.0", diff --git a/yarn.lock b/yarn.lock index 3a4d75a98..4360e06d5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2384,12 +2384,10 @@ escodegen@1.8.x: optionalDependencies: source-map "~0.2.0" -eslint-config-prettier@^6.12.0: - version "6.12.0" - resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.12.0.tgz#9eb2bccff727db1c52104f0b49e87ea46605a0d2" - integrity sha512-9jWPlFlgNwRUYVoujvWTQ1aMO8o6648r+K7qU7K5Jmkbyqav1fuEZC0COYpGBxyiAJb65Ra9hrmFx19xRGwXWw== - dependencies: - get-stdin "^6.0.0" +eslint-config-prettier@^8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" + integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== eslint-plugin-es@^3.0.0: version "3.0.1" @@ -2927,11 +2925,6 @@ get-stdin@^4.0.1: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" integrity sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4= -get-stdin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" - integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== - get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" From c6c05f823c6abec337e7ec30db86bba4daababde Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Dec 2022 22:02:45 -0600 Subject: [PATCH 0843/1037] Bump JSONStream from 0.7.4 to 1.3.5 (#2874) Bumps [JSONStream](https://github.com/dominictarr/JSONStream) from 0.7.4 to 1.3.5. - [Release notes](https://github.com/dominictarr/JSONStream/releases) - [Commits](https://github.com/dominictarr/JSONStream/commits) --- updated-dependencies: - dependency-name: JSONStream dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- packages/pg-query-stream/package.json | 2 +- yarn.lock | 15 +-------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 92a42fe95..50f6571f4 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -33,7 +33,7 @@ "@types/mocha": "^8.0.3", "@types/node": "^14.0.0", "@types/pg": "^7.14.5", - "JSONStream": "~0.7.1", + "JSONStream": "~1.3.5", "concat-stream": "~1.0.1", "eslint-plugin-promise": "^6.0.1", "mocha": "^7.1.2", diff --git a/yarn.lock b/yarn.lock index 4360e06d5..2b0959c1b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1126,7 +1126,7 @@ mkdirp-promise "^5.0.1" mz "^2.5.0" -JSONStream@^1.0.4, JSONStream@^1.3.4: +JSONStream@^1.0.4, JSONStream@^1.3.4, JSONStream@~1.3.5: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" integrity sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ== @@ -1134,14 +1134,6 @@ JSONStream@^1.0.4, JSONStream@^1.3.4: jsonparse "^1.2.0" through ">=2.2.7 <3" -JSONStream@~0.7.1: - version "0.7.4" - resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-0.7.4.tgz#734290e41511eea7c2cfe151fbf9a563a97b9786" - integrity sha1-c0KQ5BUR7qfCz+FR+/mlY6l7l4Y= - dependencies: - jsonparse "0.0.5" - through ">=2.2.7 <3" - abbrev@1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" @@ -3733,11 +3725,6 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" -jsonparse@0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-0.0.5.tgz#330542ad3f0a654665b778f3eb2d9a9fa507ac64" - integrity sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ= - jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" From 3e34816f6fcedb165618367045a3119849ff37cd Mon Sep 17 00:00:00 2001 From: Meron Ogbai <22526062+meronogbai@users.noreply.github.com> Date: Sat, 31 Dec 2022 07:45:42 +0300 Subject: [PATCH 0844/1037] Update title (#2886) This will change the title of the docs from Next.js Static Site Generator to node-postgres --- docs/theme.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/theme.config.js b/docs/theme.config.js index 4ab2b8d23..263a26945 100644 --- a/docs/theme.config.js +++ b/docs/theme.config.js @@ -24,7 +24,7 @@ export default { logo: ( <> ... - Next.js Static Site Generator + node-postgres ), head: ( From f82f39c20c4a0b834529c7d3d38a43a9ec366572 Mon Sep 17 00:00:00 2001 From: Ruy Adorno Date: Mon, 23 Jan 2023 13:02:39 -0500 Subject: [PATCH 0845/1037] Add support to stream factory (#2898) This changeset enables declaring the `stream` config value as a factory method. Providing a much more flexible control of the socket connection. Defining a custom `stream` config value allows the postgres driver to support a larger variety of environments/setups such as proxy servers and secure socket connections that are used by cloud providers such as GCP. Currently, usage of the `stream` config value is only viable for single connections given that it's only possible to define a single socket stream instance per new Client/Pool instance. By adding support to a factory function, it becomes possible to enable usage of custom socket streams for connection pools. For reference, see the `mysql2` driver for MySQL (linked below) for prior art example of this pattern. Refs: https://github.com/sidorares/node-mysql2/blob/ba15fe25703665e516ab0a23af8d828d1473b8c3/lib/connection.js#L63-L65 Refs: https://cloud.google.com/sql/docs/postgres/connect-overview Signed-off-by: Ruy Adorno Signed-off-by: Ruy Adorno --- packages/pg/lib/connection.js | 5 +++++ packages/pg/test/unit/connection/startup-tests.js | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index fe04efb6b..86724c5c5 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -14,7 +14,12 @@ class Connection extends EventEmitter { constructor(config) { super() config = config || {} + this.stream = config.stream || new net.Socket() + if (typeof this.stream === 'function') { + this.stream = this.stream(config) + } + this._keepAlive = config.keepAlive this._keepAliveInitialDelayMillis = config.keepAliveInitialDelayMillis this.lastBuffer = false diff --git a/packages/pg/test/unit/connection/startup-tests.js b/packages/pg/test/unit/connection/startup-tests.js index e2eb6ee99..d5d30d5de 100644 --- a/packages/pg/test/unit/connection/startup-tests.js +++ b/packages/pg/test/unit/connection/startup-tests.js @@ -7,6 +7,18 @@ test('connection can take existing stream', function () { assert.equal(con.stream, stream) }) +test('connection can take stream factory method', function () { + var stream = new MemoryStream() + var connectionOpts = {} + var makeStream = function (opts) { + assert.equal(connectionOpts, opts) + return stream + } + connectionOpts.stream = makeStream + var con = new Connection(connectionOpts) + assert.equal(con.stream, stream) +}) + test('using any stream', function () { var makeStream = function () { var stream = new MemoryStream() From bb8745b2159a5096c25acba23dc0603c0f75fe5e Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Mon, 23 Jan 2023 13:03:51 -0500 Subject: [PATCH 0846/1037] Fix SASL to bubble up errors, enable SASL tests in CI, and add informative empty SASL password message (#2901) * Enable SASL tests in GitHub actions CI * Add SASL test to ensure that client password is a string * Fix SASL error handling to emit and bubble up errors * Add informative error when SASL password is empty string --- .github/workflows/ci.yml | 15 +++++++- packages/pg/lib/client.js | 24 +++++++++--- packages/pg/lib/sasl.js | 3 ++ .../integration/client/sasl-scram-tests.js | 21 ++++++++++ .../pg/test/unit/client/sasl-scram-tests.js | 38 +++++++++++++++++++ 5 files changed, 94 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 97f4013ba..ab5bef47b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,6 +15,7 @@ jobs: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: ci_db_test + POSTGRES_HOST_AUTH_METHOD: 'md5' ports: - 5432:5432 options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 @@ -23,7 +24,19 @@ jobs: node: ['10', '12', '14', '16', '18'] os: [ubuntu-latest, windows-latest, macos-latest] name: Node.js ${{ matrix.node }} (${{ matrix.os }}) + env: + PGUSER: postgres + PGHOST: localhost + PGPASSWORD: postgres + PGDATABASE: ci_db_test + PGTESTNOSSL: 'true' + SCRAM_TEST_PGUSER: scram_test + SCRAM_TEST_PGPASSWORD: test4scram steps: + - run: | + psql \ + -c "SET password_encryption = 'scram-sha-256'" \ + -c "CREATE ROLE scram_test LOGIN PASSWORD 'test4scram'" - uses: actions/checkout@v3 with: persist-credentials: false @@ -34,4 +47,4 @@ jobs: cache: yarn - run: yarn install # TODO(bmc): get ssl tests working in ci - - run: PGTESTNOSSL=true PGUSER=postgres PGPASSWORD=postgres PGDATABASE=ci_db_test yarn test + - run: yarn test diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 82d571d8a..2090c4b5f 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -247,19 +247,31 @@ class Client extends EventEmitter { _handleAuthSASL(msg) { this._checkPgPass(() => { - this.saslSession = sasl.startSession(msg.mechanisms) - this.connection.sendSASLInitialResponseMessage(this.saslSession.mechanism, this.saslSession.response) + try { + this.saslSession = sasl.startSession(msg.mechanisms) + this.connection.sendSASLInitialResponseMessage(this.saslSession.mechanism, this.saslSession.response) + } catch (err) { + this.connection.emit('error', err) + } }) } _handleAuthSASLContinue(msg) { - sasl.continueSession(this.saslSession, this.password, msg.data) - this.connection.sendSCRAMClientFinalMessage(this.saslSession.response) + try { + sasl.continueSession(this.saslSession, this.password, msg.data) + this.connection.sendSCRAMClientFinalMessage(this.saslSession.response) + } catch (err) { + this.connection.emit('error', err) + } } _handleAuthSASLFinal(msg) { - sasl.finalizeSession(this.saslSession, msg.data) - this.saslSession = null + try { + sasl.finalizeSession(this.saslSession, msg.data) + this.saslSession = null + } catch (err) { + this.connection.emit('error', err) + } } _handleBackendKeyData(msg) { diff --git a/packages/pg/lib/sasl.js b/packages/pg/lib/sasl.js index fb703b270..c8d2d2bdc 100644 --- a/packages/pg/lib/sasl.js +++ b/packages/pg/lib/sasl.js @@ -23,6 +23,9 @@ function continueSession(session, password, serverData) { if (typeof password !== 'string') { throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string') } + if (password === '') { + throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a non-empty string') + } if (typeof serverData !== 'string') { throw new Error('SASL: SCRAM-SERVER-FIRST-MESSAGE: serverData must be a string') } diff --git a/packages/pg/test/integration/client/sasl-scram-tests.js b/packages/pg/test/integration/client/sasl-scram-tests.js index debc28685..3b3fd4a57 100644 --- a/packages/pg/test/integration/client/sasl-scram-tests.js +++ b/packages/pg/test/integration/client/sasl-scram-tests.js @@ -73,3 +73,24 @@ suite.testAsync('sasl/scram fails when password is wrong', async () => { ) assert.ok(usingSasl, 'Should be using SASL for authentication') }) + +suite.testAsync('sasl/scram fails when password is empty', async () => { + const client = new pg.Client({ + ...config, + // We use a password function here so the connection defaults do not + // override the empty string value with one from process.env.PGPASSWORD + password: () => '', + }) + let usingSasl = false + client.connection.once('authenticationSASL', () => { + usingSasl = true + }) + await assert.rejects( + () => client.connect(), + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a non-empty string', + }, + 'Error code should be for a password error' + ) + assert.ok(usingSasl, 'Should be using SASL for authentication') +}) diff --git a/packages/pg/test/unit/client/sasl-scram-tests.js b/packages/pg/test/unit/client/sasl-scram-tests.js index e53448bdf..36a5556b4 100644 --- a/packages/pg/test/unit/client/sasl-scram-tests.js +++ b/packages/pg/test/unit/client/sasl-scram-tests.js @@ -80,6 +80,44 @@ test('sasl/scram', function () { ) }) + test('fails when client password is not a string', function () { + for(const badPasswordValue of [null, undefined, 123, new Date(), {}]) { + assert.throws( + function () { + sasl.continueSession( + { + message: 'SASLInitialResponse', + clientNonce: 'a', + }, + badPasswordValue, + 'r=1,i=1' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a string', + } + ) + } + }) + + test('fails when client password is an empty string', function () { + assert.throws( + function () { + sasl.continueSession( + { + message: 'SASLInitialResponse', + clientNonce: 'a', + }, + '', + 'r=1,i=1' + ) + }, + { + message: 'SASL: SCRAM-SERVER-FIRST-MESSAGE: client password must be a non-empty string', + } + ) + }) + test('fails when iteration is missing in server message', function () { assert.throws( function () { From 47afe5cded70cfaf873b35ae68eca4986102b988 Mon Sep 17 00:00:00 2001 From: Brian C Date: Mon, 23 Jan 2023 13:55:38 -0800 Subject: [PATCH 0847/1037] Attempt to fix timing test flake on older versions of node in CI (#2902) --- packages/pg-pool/test/lifetime-timeout.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/pg-pool/test/lifetime-timeout.js b/packages/pg-pool/test/lifetime-timeout.js index fddd5ff00..3e690429e 100644 --- a/packages/pg-pool/test/lifetime-timeout.js +++ b/packages/pg-pool/test/lifetime-timeout.js @@ -21,7 +21,7 @@ describe('lifetime timeout', () => { }) it('connection lifetime should expire and remove the client after the client is done working', (done) => { const pool = new Pool({ maxLifetimeSeconds: 1 }) - pool.query('SELECT pg_sleep(1.01)') + pool.query('SELECT pg_sleep(1.4)') pool.on('remove', () => { console.log('expired while busy - on-remove event') expect(pool.expiredCount).to.equal(0) @@ -33,10 +33,11 @@ describe('lifetime timeout', () => { 'can remove expired clients and recreate them', co.wrap(function* () { const pool = new Pool({ maxLifetimeSeconds: 1 }) - let query = pool.query('SELECT pg_sleep(1)') + let query = pool.query('SELECT pg_sleep(1.4)') expect(pool.expiredCount).to.equal(0) expect(pool.totalCount).to.equal(1) yield query + yield new Promise((resolve) => setTimeout(resolve, 100)) expect(pool.expiredCount).to.equal(0) expect(pool.totalCount).to.equal(0) yield pool.query('SELECT NOW()') From 5bdc61a33d4ef25cc12ea36a4199864109551c56 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 27 Jan 2023 09:11:05 -0600 Subject: [PATCH 0848/1037] Remove expired sponsors --- README.md | 15 +-------------- packages/pg/README.md | 13 +------------ 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 15b693128..0cf4c5e37 100644 --- a/README.md +++ b/README.md @@ -55,20 +55,7 @@ You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that ## Sponsorship :two_hearts: -node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) and these featured sponsors: - -
-

- - - -

-

- - - -

-
+node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md). If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable [please consider supporting](https://github.com/sponsors/brianc) its development. diff --git a/packages/pg/README.md b/packages/pg/README.md index b3158b570..e21f34a06 100644 --- a/packages/pg/README.md +++ b/packages/pg/README.md @@ -46,18 +46,7 @@ You can also follow me [@briancarlson](https://twitter.com/briancarlson) if that ## Sponsorship :two_hearts: -node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md) and these featured sponsors: - -
- - - - - - - - -
+node-postgres's continued development has been made possible in part by generous finanical support from [the community](https://github.com/brianc/node-postgres/blob/master/SPONSORS.md). If you or your company are benefiting from node-postgres and would like to help keep the project financially sustainable [please consider supporting](https://github.com/sponsors/brianc) its development. From 20a243e8b30926a348cafc44177e95345618f7bc Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 27 Jan 2023 09:12:49 -0600 Subject: [PATCH 0849/1037] Publish - pg-cursor@2.8.0 - pg-protocol@1.6.0 - pg-query-stream@4.3.0 - pg@8.9.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-protocol/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index c12906abd..5fabf5b28 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.7.4", + "version": "2.8.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.8.0" + "pg": "^8.9.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-protocol/package.json b/packages/pg-protocol/package.json index ae9ba6f52..ff56dc3be 100644 --- a/packages/pg-protocol/package.json +++ b/packages/pg-protocol/package.json @@ -1,6 +1,6 @@ { "name": "pg-protocol", - "version": "1.5.0", + "version": "1.6.0", "description": "The postgres client/server binary protocol, implemented in TypeScript", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 50f6571f4..0c090c4a2 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "4.2.4", + "version": "4.3.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,7 +37,7 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^6.0.1", "mocha": "^7.1.2", - "pg": "^8.8.0", + "pg": "^8.9.0", "stream-spec": "~0.3.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" @@ -46,6 +46,6 @@ "pg": "^8" }, "dependencies": { - "pg-cursor": "^2.7.4" + "pg-cursor": "^2.8.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 37afe6149..6c0f60a38 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.8.0", + "version": "8.9.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -24,7 +24,7 @@ "packet-reader": "1.0.0", "pg-connection-string": "^2.5.0", "pg-pool": "^3.5.2", - "pg-protocol": "^1.5.0", + "pg-protocol": "^1.6.0", "pg-types": "^2.1.0", "pgpass": "1.x" }, From adbe86d4a057b942298cab1d19b341c67a94d922 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Fri, 27 Jan 2023 09:15:30 -0600 Subject: [PATCH 0850/1037] Update changelog --- CHANGELOG.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f017a3d5a..fff8cdf1c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,19 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +## pg@8.9.0 + +- Add support for [stream factory](https://github.com/brianc/node-postgres/pull/2898). +- [Better errors](https://github.com/brianc/node-postgres/pull/2901) for SASL authentication. +- [Use native crypto module](https://github.com/brianc/node-postgres/pull/2815) for SASL authentication. + ## pg@8.8.0 -- Bump minimum required version of [native bindings](https://github.com/brianc/node-postgres/pull/2787) -- Catch previously uncatchable errors thrown in [`pool.query`](https://github.com/brianc/node-postgres/pull/2569) -- Prevent the pool from blocking the event loop if all clients are [idle](https://github.com/brianc/node-postgres/pull/2721) (and `allowExitOnIdle` is enabled) -- Support `lock_timeout` in [client config](https://github.com/brianc/node-postgres/pull/2779) -- Fix errors thrown in callbacks from [interfering with cleanup](https://github.com/brianc/node-postgres/pull/2753) +- Bump minimum required version of [native bindings](https://github.com/brianc/node-postgres/pull/2787). +- Catch previously uncatchable errors thrown in [`pool.query`](https://github.com/brianc/node-postgres/pull/2569). +- Prevent the pool from blocking the event loop if all clients are [idle](https://github.com/brianc/node-postgres/pull/2721) (and `allowExitOnIdle` is enabled). +- Support `lock_timeout` in [client config](https://github.com/brianc/node-postgres/pull/2779). +- Fix errors thrown in callbacks from [interfering with cleanup](https://github.com/brianc/node-postgres/pull/2753). ### pg-pool@3.5.0 From 5703791640ba92558f162120f235b29eaf0e4cf0 Mon Sep 17 00:00:00 2001 From: Cody Greene Date: Mon, 6 Mar 2023 10:10:07 -0800 Subject: [PATCH 0851/1037] fix: double client.end() hang (#2717) * fix: double client.end() hang fixes https://github.com/brianc/node-postgres/issues/2716 `client.end()` will resolve early if the connection is already dead, rather than waiting for an "end" event that will never arrive. * fix: client.end() resolves when socket is fully closed --- packages/pg/lib/client.js | 4 +- packages/pg/lib/connection.js | 3 -- .../test/integration/gh-issues/2716-tests.js | 38 +++++++++++++++++++ 3 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 packages/pg/test/integration/gh-issues/2716-tests.js diff --git a/packages/pg/lib/client.js b/packages/pg/lib/client.js index 2090c4b5f..99c06d661 100644 --- a/packages/pg/lib/client.js +++ b/packages/pg/lib/client.js @@ -37,6 +37,7 @@ class Client extends EventEmitter { this._Promise = c.Promise || global.Promise this._types = new TypeOverrides(c.types) this._ending = false + this._ended = false this._connecting = false this._connected = false this._connectionError = false @@ -132,6 +133,7 @@ class Client extends EventEmitter { clearTimeout(this.connectionTimeoutHandle) this._errorAllQueries(error) + this._ended = true if (!this._ending) { // if the connection is ended without us calling .end() @@ -603,7 +605,7 @@ class Client extends EventEmitter { this._ending = true // if we have never connected, then end is a noop, callback immediately - if (!this.connection._connecting) { + if (!this.connection._connecting || this._ended) { if (cb) { cb() } else { diff --git a/packages/pg/lib/connection.js b/packages/pg/lib/connection.js index 86724c5c5..9e24391b6 100644 --- a/packages/pg/lib/connection.js +++ b/packages/pg/lib/connection.js @@ -108,9 +108,6 @@ class Connection extends EventEmitter { } attachListeners(stream) { - stream.on('end', () => { - this.emit('end') - }) parse(stream, (msg) => { var eventName = msg.name === 'error' ? 'errorMessage' : msg.name if (this._emitMessage) { diff --git a/packages/pg/test/integration/gh-issues/2716-tests.js b/packages/pg/test/integration/gh-issues/2716-tests.js new file mode 100644 index 000000000..62d0942ba --- /dev/null +++ b/packages/pg/test/integration/gh-issues/2716-tests.js @@ -0,0 +1,38 @@ +'use strict' +const helper = require('../test-helper') + +const suite = new helper.Suite() + +// https://github.com/brianc/node-postgres/issues/2716 +suite.testAsync('client.end() should resolve if already ended', async () => { + const client = new helper.pg.Client() + await client.connect() + + // this should resolve only when the underlying socket is fully closed, both + // the readable part ("end" event) & writable part ("close" event). + + // https://nodejs.org/docs/latest-v16.x/api/net.html#event-end + // > Emitted when the other end of the socket signals the end of + // > transmission, thus ending the readable side of the socket. + + // https://nodejs.org/docs/latest-v16.x/api/net.html#event-close_1 + // > Emitted once the socket is fully closed. + + // here: stream = socket + + await client.end() + // connection.end() + // stream.end() + // ... + // stream emits "end" + // not listening to this event anymore so the promise doesn't resolve yet + // stream emits "close"; no more events will be emitted from the stream + // connection emits "end" + // promise resolved + + // This should now resolve immediately, rather than wait for connection.on('end') + await client.end() + + // this should resolve immediately, rather than waiting forever + await client.end() +}) From 8804e5caaf2194e75d0a7b44f7819dfc809ea317 Mon Sep 17 00:00:00 2001 From: Aram Zegerius Date: Mon, 6 Mar 2023 19:30:37 +0100 Subject: [PATCH 0852/1037] Fix typo in URL (#2913) --- docs/pages/features/pooling.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/pages/features/pooling.mdx b/docs/pages/features/pooling.mdx index 4719150be..e291080f2 100644 --- a/docs/pages/features/pooling.mdx +++ b/docs/pages/features/pooling.mdx @@ -19,7 +19,7 @@ The easiest and by far most common way to use node-postgres is through a connect ### Good news -node-postgres ships with built-in connection pooling via the [pg-pool](/api/pool) module. +node-postgres ships with built-in connection pooling via the [pg-pool](/apis/pool) module. ## Examples From 810b12558139d0231a71b9bc81206490f2a27ef3 Mon Sep 17 00:00:00 2001 From: "Ryan B. Harvey" Date: Mon, 6 Mar 2023 12:32:13 -0600 Subject: [PATCH 0853/1037] Emit a 'release' event when a connection is released back to the pool (#2845) --- packages/pg-pool/index.js | 2 ++ packages/pg-pool/test/events.js | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/packages/pg-pool/index.js b/packages/pg-pool/index.js index 00f55b4da..910aee6d2 100644 --- a/packages/pg-pool/index.js +++ b/packages/pg-pool/index.js @@ -330,6 +330,8 @@ class Pool extends EventEmitter { client._poolUseCount = (client._poolUseCount || 0) + 1 + this.emit('release', err, client) + // TODO(bmc): expose a proper, public interface _queryable and _ending if (err || this.ending || !client._queryable || client._ending || client._poolUseCount >= this.options.maxUses) { if (client._poolUseCount >= this.options.maxUses) { diff --git a/packages/pg-pool/test/events.js b/packages/pg-pool/test/events.js index 61979247d..751b14dbc 100644 --- a/packages/pg-pool/test/events.js +++ b/packages/pg-pool/test/events.js @@ -60,6 +60,42 @@ describe('events', function () { }, 100) }) + it('emits release every time a client is released', function (done) { + const pool = new Pool() + let releaseCount = 0 + pool.on('release', function (err, client) { + expect(err instanceof Error).not.to.be(true) + expect(client).to.be.ok() + releaseCount++ + }) + 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(releaseCount).to.be(20) + pool.end(done) + }, 100) + }) + + it('emits release with an error if client is released due to an error', function (done) { + const pool = new Pool() + pool.connect(function (err, client, release) { + expect(err).to.equal(undefined) + const releaseError = new Error('problem') + pool.once('release', function (err, errClient) { + console.log(err, errClient) + expect(err).to.equal(releaseError) + expect(errClient).to.equal(client) + pool.end(done) + }) + release(releaseError) + }) + }) + 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) { From ee302cbcf10437e34fd05d70fc003c357b14c654 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 6 Mar 2023 14:18:02 -0600 Subject: [PATCH 0854/1037] Publish - pg-cursor@2.9.0 - pg-pool@3.6.0 - pg-query-stream@4.4.0 - pg@8.10.0 --- packages/pg-cursor/package.json | 4 ++-- packages/pg-pool/package.json | 2 +- packages/pg-query-stream/package.json | 6 +++--- packages/pg/package.json | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/pg-cursor/package.json b/packages/pg-cursor/package.json index 5fabf5b28..c99c12c29 100644 --- a/packages/pg-cursor/package.json +++ b/packages/pg-cursor/package.json @@ -1,6 +1,6 @@ { "name": "pg-cursor", - "version": "2.8.0", + "version": "2.9.0", "description": "Query cursor extension for node-postgres", "main": "index.js", "directories": { @@ -18,7 +18,7 @@ "license": "MIT", "devDependencies": { "mocha": "^7.1.2", - "pg": "^8.9.0" + "pg": "^8.10.0" }, "peerDependencies": { "pg": "^8" diff --git a/packages/pg-pool/package.json b/packages/pg-pool/package.json index 0bb64b579..38b36708f 100644 --- a/packages/pg-pool/package.json +++ b/packages/pg-pool/package.json @@ -1,6 +1,6 @@ { "name": "pg-pool", - "version": "3.5.2", + "version": "3.6.0", "description": "Connection pool for node-postgres", "main": "index.js", "directories": { diff --git a/packages/pg-query-stream/package.json b/packages/pg-query-stream/package.json index 0c090c4a2..23f5fbd3e 100644 --- a/packages/pg-query-stream/package.json +++ b/packages/pg-query-stream/package.json @@ -1,6 +1,6 @@ { "name": "pg-query-stream", - "version": "4.3.0", + "version": "4.4.0", "description": "Postgres query result returned as readable stream", "main": "./dist/index.js", "types": "./dist/index.d.ts", @@ -37,7 +37,7 @@ "concat-stream": "~1.0.1", "eslint-plugin-promise": "^6.0.1", "mocha": "^7.1.2", - "pg": "^8.9.0", + "pg": "^8.10.0", "stream-spec": "~0.3.5", "ts-node": "^8.5.4", "typescript": "^4.0.3" @@ -46,6 +46,6 @@ "pg": "^8" }, "dependencies": { - "pg-cursor": "^2.8.0" + "pg-cursor": "^2.9.0" } } diff --git a/packages/pg/package.json b/packages/pg/package.json index 6c0f60a38..6e62a04ea 100644 --- a/packages/pg/package.json +++ b/packages/pg/package.json @@ -1,6 +1,6 @@ { "name": "pg", - "version": "8.9.0", + "version": "8.10.0", "description": "PostgreSQL client - pure javascript & libpq with the same API", "keywords": [ "database", @@ -23,7 +23,7 @@ "buffer-writer": "2.0.0", "packet-reader": "1.0.0", "pg-connection-string": "^2.5.0", - "pg-pool": "^3.5.2", + "pg-pool": "^3.6.0", "pg-protocol": "^1.6.0", "pg-types": "^2.1.0", "pgpass": "1.x" From 661f870e1c741a1dd712f5ad7631aa34419b2af9 Mon Sep 17 00:00:00 2001 From: Brian Carlson Date: Mon, 6 Mar 2023 15:48:08 -0600 Subject: [PATCH 0855/1037] Update changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fff8cdf1c..bf05426e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ For richer information consult the commit log on github with referenced pull req We do not include break-fix version release in this file. +## pg-pool@8.10.0 + +- Emit `release` event when client is returned to [the pool](https://github.com/brianc/node-postgres/pull/2845). + ## pg@8.9.0 - Add support for [stream factory](https://github.com/brianc/node-postgres/pull/2898). From 0f76fb3bb70f0cee118d873aeee4283b32f7217f Mon Sep 17 00:00:00 2001 From: Brian C Date: Tue, 7 Mar 2023 13:55:22 -0600 Subject: [PATCH 0856/1037] Update path to documentation in readme (#2925) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0cf4c5e37..967431358 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Each package in this repo should have its own readme more focused on how to deve ### :star: [Documentation](https://node-postgres.com) :star: -The source repo for the documentation is https://github.com/brianc/node-postgres-docs. +The source repo for the documentation is available for contribution [here](https://github.com/brianc/node-postgres/tree/master/docs). ### Features From 65ca2458fd0079f36a99a7752a7931483cd57ed6 Mon Sep 17 00:00:00 2001 From: "Ryan B. Harvey" Date: Thu, 16 Mar 2023 11:34:50 -0500 Subject: [PATCH 0857/1037] Add release event to Pool API docs (#2928) --- docs/pages/apis/pool.mdx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/pages/apis/pool.mdx b/docs/pages/apis/pool.mdx index 497e5253f..6323f2e2d 100644 --- a/docs/pages/apis/pool.mdx +++ b/docs/pages/apis/pool.mdx @@ -271,6 +271,12 @@ The error listener is passed the error as the first argument and the client upon uncaught error and potentially crash your node process. +### release + +`pool.on('release', (err: Error, client: Client) => void) => void` + +Whenever a client is released back into the pool, the pool will emit the `release` event. + ### remove `pool.on('remove', (client: Client) => void) => void` From 92351b5f3ea7d76183e92d9a1461987fd826f60f Mon Sep 17 00:00:00 2001 From: Samuel Durante <44513615+samueldurantes@users.noreply.github.com> Date: Thu, 30 Mar 2023 12:49:28 -0300 Subject: [PATCH 0858/1037] docs(client): improve the Client instance example (#2935) --- docs/pages/apis/client.mdx | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/pages/apis/client.mdx b/docs/pages/apis/client.mdx index 92268bed8..d5f335240 100644 --- a/docs/pages/apis/client.mdx +++ b/docs/pages/apis/client.mdx @@ -34,6 +34,7 @@ const { Client } = require('pg') const client = new Client({ host: 'my.database-server.com', port: 5334, + database: 'database-name', user: 'database-user', password: 'secretpassword!!', }) From 48f4398fa75247f4ed8e2470372d0b77712f73e3 Mon Sep 17 00:00:00 2001 From: Brian C Date: Thu, 30 Mar 2023 11:25:35 -0500 Subject: [PATCH 0859/1037] Update README.md (#2944) Update href to docs --- packages/pg-cursor/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/pg-cursor/README.md b/packages/pg-cursor/README.md index 1b01b3d83..a3fdf4d00 100644 --- a/packages/pg-cursor/README.md +++ b/packages/pg-cursor/README.md @@ -10,7 +10,7 @@ $ npm install pg-cursor ``` ___note___: this depends on _either_ `npm install pg` or `npm install pg.js`, but you __must__ be using the pure JavaScript client. This will __not work__ with the native bindings. -### :star: [Documentation](https://node-postgres.com/api/cursor) :star: +### :star: [Documentation](https://node-postgres.com/apis/cursor) :star: ### license From b357e1884ad25b23a4ab034b443ddfc8c8261951 Mon Sep 17 00:00:00 2001 From: Jan Piotrowski Date: Thu, 20 Apr 2023 16:03:59 +0200 Subject: [PATCH 0860/1037] fix(theme.config.js): Replace default meta description and social title (#2952) Currently still nextra default. Those are shown in Slack and other social apps when sharing the website. --- docs/theme.config.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/theme.config.js b/docs/theme.config.js index 263a26945..00410f791 100644 --- a/docs/theme.config.js +++ b/docs/theme.config.js @@ -30,8 +30,8 @@ export default { head: ( <> - - + +