From 2706357608825721a46b48003116e5906781a28f Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Sat, 6 Jul 2019 10:45:31 +0100 Subject: [PATCH 01/21] fixing tests for windows --- .idea/misc.xml | 6 ++++++ .idea/modules.xml | 8 ++++++++ .idea/pg-connection-string.iml | 12 ++++++++++++ .idea/vcs.xml | 6 ++++++ .idea/workspace.xml | 16 ++++++++++++++++ package.json | 4 ++-- test/parse.js | 7 ++++--- 7 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/pg-connection-string.iml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..28a804d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..1a451be --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/pg-connection-string.iml b/.idea/pg-connection-string.iml new file mode 100644 index 0000000..24643cc --- /dev/null +++ b/.idea/pg-connection-string.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..ce81e6c --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/package.json b/package.json index 415638f..e1497eb 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "./index.js", "types": "./index.d.ts", "scripts": { - "test": "istanbul cover _mocha && npm run check-coverage", + "test": "istanbul cover node_modules/mocha/bin/_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" }, @@ -30,7 +30,7 @@ "chai": "^4.1.1", "coveralls": "^3.0.4", "istanbul": "^0.4.5", - "mocha": "^3.5.0" + "mocha": "^6.1.4" }, "files": [ "index.js", diff --git a/test/parse.js b/test/parse.js index 4de2871..a757153 100644 --- a/test/parse.js +++ b/test/parse.js @@ -1,5 +1,6 @@ 'use strict'; +var EOL = require('os').EOL; var chai = require('chai'); var expect = chai.expect; chai.should(); @@ -165,7 +166,7 @@ describe('parse', function(){ var connectionString = 'pg:///?sslcert=' + __dirname + '/example.cert'; var subject = parse(connectionString); subject.ssl.should.eql({ - cert: 'example cert\n' + cert: 'example cert' + EOL }); }); @@ -173,7 +174,7 @@ describe('parse', function(){ var connectionString = 'pg:///?sslkey=' + __dirname + '/example.key'; var subject = parse(connectionString); subject.ssl.should.eql({ - key: 'example key\n' + key: 'example key' + EOL }); }); @@ -181,7 +182,7 @@ describe('parse', function(){ var connectionString = 'pg:///?sslrootcert=' + __dirname + '/example.ca'; var subject = parse(connectionString); subject.ssl.should.eql({ - ca: 'example ca\n' + ca: 'example ca' + EOL }); }); From bb5fbebdfbae0da7b7995035210b9590107b8630 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Sat, 6 Jul 2019 10:46:32 +0100 Subject: [PATCH 02/21] fixing tests for windows --- .idea/misc.xml | 6 ------ .idea/modules.xml | 8 -------- .idea/pg-connection-string.iml | 12 ------------ .idea/vcs.xml | 6 ------ .idea/workspace.xml | 16 ---------------- 5 files changed, 48 deletions(-) delete mode 100644 .idea/misc.xml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/pg-connection-string.iml delete mode 100644 .idea/vcs.xml delete mode 100644 .idea/workspace.xml diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index 28a804d..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 1a451be..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/pg-connection-string.iml b/.idea/pg-connection-string.iml deleted file mode 100644 index 24643cc..0000000 --- a/.idea/pg-connection-string.iml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 94a25f7..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index ce81e6c..0000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file From 8d14f2340b93cef5a33c50a4ccf4b5d729d02068 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Sat, 6 Jul 2019 10:50:23 +0100 Subject: [PATCH 03/21] Update package.json Reverting the mocha version, because the latest does not support Node.js 0.10 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e1497eb..57b0d2c 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "chai": "^4.1.1", "coveralls": "^3.0.4", "istanbul": "^0.4.5", - "mocha": "^6.1.4" + "mocha": "^3.5.0" }, "files": [ "index.js", From 248cd974fb51487b73a6bff1975333fb6be5625e Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Sat, 6 Jul 2019 14:54:31 +0100 Subject: [PATCH 04/21] integrating generic connection-string --- .gitignore | 5 +- .travis.yml | 13 +- index.js | 117 ++++++-------- package.json | 6 +- test/parse.js | 427 +++++++++++++++++++++++++------------------------- 5 files changed, 279 insertions(+), 289 deletions(-) diff --git a/.gitignore b/.gitignore index f28f01f..5478e79 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,7 @@ 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 +package-lock.json + +# IDE files and folders: +.idea/ diff --git a/.travis.yml b/.travis.yml index daf50ba..3902f13 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,9 @@ language: node_js -node_js: - - '0.10' - - '6.9' - - '8' -after_success: 'npm run coveralls' +matrix: + include: + - node_js: "4" + script: "npm test" + - node_js: "8" + script: "npm run coveralls" + - node_js: "12" + script: "npm run coveralls" diff --git a/index.js b/index.js index 3cabb37..e57b786 100644 --- a/index.js +++ b/index.js @@ -1,78 +1,65 @@ 'use strict'; -var url = require('url'); -var fs = require('fs'); +const fs = require('fs'); +const ConnectionString = require('connection-string'); -//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 +// parses a connection string function parse(str) { - //unix socket - 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; - for (var k in config) { - if (Array.isArray(config[k])) { - config[k] = config[k][config[k].length-1]; + + const cs = new ConnectionString(str); + + const config = cs.params ? Object.assign({}, cs.params) : {}; + + // In this version we ignore multi-host support, using compatibility properties for the first host + port: + config.host = cs.hostname; + config.port = cs.port; + + config.database = cs.path && cs.path[0]; + config.user = cs.user; + config.password = cs.password; + + if (config.encoding) { + config.client_encoding = config.encoding; + } + + // primary sockets support, via parameter 'socket', which also allows use of '/' in the socket name: + if (config.socket) { + config.host = config.socket; + return config; + } + + // secondary support for unix sockets, when host name ends with '.socket': + if (cs.hosts && cs.hosts[0].type === 'socket') { + return config; + } + + if (config.ssl === 'true' || config.ssl === '1') { + config.ssl = true; + } + + if (config.ssl === '0') { + config.ssl = false; } - } - var auth = (result.auth || ':').split(':'); - config.user = auth[0]; - config.password = auth.splice(1).join(':'); + 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(); + } - 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.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. - var pathname = result.pathname; - if (pathname && pathname.charAt(0) === '/') { - pathname = result.pathname.slice(1) || null; - } - config.database = pathname && decodeURI(pathname); - - if (config.ssl === 'true' || config.ssl === '1') { - config.ssl = true; - } - - if (config.ssl === '0') { - config.ssl = false; - } - - 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; } - module.exports = parse; parse.parse = parse; diff --git a/package.json b/package.json index e1497eb..cc0a0be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pg-connection-string", - "version": "2.1.0", + "version": "3.0.0", "description": "Functions for dealing with a PostgresSQL connection string", "main": "./index.js", "types": "./index.d.ts", @@ -25,7 +25,9 @@ "url": "https://github.com/iceddev/pg-connection-string/issues" }, "homepage": "https://github.com/iceddev/pg-connection-string", - "dependencies": {}, + "dependencies": { + "connection-string": "^2.4.3" + }, "devDependencies": { "chai": "^4.1.1", "coveralls": "^3.0.4", diff --git a/test/parse.js b/test/parse.js index a757153..17db773 100644 --- a/test/parse.js +++ b/test/parse.js @@ -1,221 +1,216 @@ 'use strict'; -var EOL = require('os').EOL; -var chai = require('chai'); -var expect = chai.expect; +const path = require('path'); +const EOL = require('os').EOL; +const chai = require('chai'); 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', - 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('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); - }); - - 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' + EOL - }); - }); - - 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' + EOL - }); - }); - - 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' + EOL - }); - }); - - 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'); - }); +const parse = require('../').parse; + +describe('parse', () => { + + it('using connection string in client constructor', () => { + const 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 and pluses if present', () => { + const subject1 = parse('postgres://localhost/post+gres'); + subject1.database.should.equal('post gres'); + const subject2 = parse('postgres://localhost/post%20gres'); + subject2.database.should.equal('post gres'); + }); + + it('do not double escape spaces', () => { + const subject = parse('postgres://localhost/post%20gres'); + subject.database.should.equal('post gres'); + }); + + it('initializing with unix domain socket', () => { + const subject1 = parse('?socket=' + encodeURIComponent('/const/run/')); + subject1.host.should.equal('/const/run/'); + const subject2 = parse('test.domain.sock'); + subject2.host.should.equal('test.domain.sock'); + }); + + it('initializing with unix domain socket and a specific database, the simple way', () => { + const subject = parse('/mydb?socket=' + encodeURIComponent('/const/run/')); + subject.host.should.equal('/const/run/'); + subject.database.should.equal('mydb'); + }); + + it('initializing with unix domain socket, the healthy way', () => { + const subject = parse('//my%5Bdb%5D?encoding=utf8&socket=' + encodeURIComponent('/some path/')); + 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', () => { + const subject = parse('//my%2Bdb?encoding=utf8&socket=' + encodeURIComponent('/some path/')); + 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', () => { + const subject = parse('postgres://brian:pw@/mydb?socket=' + encodeURIComponent('/const/run/')); + subject.user.should.equal('brian'); + subject.password.should.equal('pw'); + subject.host.should.equal('/const/run/'); + subject.database.should.equal('mydb'); + }); + + it('password contains < and/or > characters', () => { + const sourceConfig = { + user: 'brian', + password: 'helloe', + port: 5432, + host: 'localhost', + database: 'postgres' + }; + const connectionString = 'postgres://' + sourceConfig.user + ':' + encodeURIComponent(sourceConfig.password) + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database; + const subject = parse(connectionString); + subject.password.should.equal(sourceConfig.password); + }); + + it('password contains colons', () => { + const sourceConfig = { + user: 'brian', + password: 'hello:pass:world', + port: 5432, + host: 'localhost', + database: 'postgres' + }; + const connectionString = 'postgres://' + sourceConfig.user + ':' + encodeURIComponent(sourceConfig.password) + '@' + sourceConfig.host + ':' + sourceConfig.port + '/' + sourceConfig.database; + const subject = parse(connectionString); + subject.password.should.equal(sourceConfig.password); + }); + + it('url is properly encoded', () => { + const encoded = 'pg://bi%25na%25%25ry%20:s%40f%23@localhost/%20u%2520rl'; + const 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', () => { + const relative = '/different_db_on_default_host'; + const subject = parse(relative); + subject.database.should.equal('different_db_on_default_host'); + }); + + it('no pathname returns undefined database', () => { + const subject = parse('pg://myhost'); + (subject.database === undefined).should.equal(true); + }); + + it('pathname of "/" returns undefined database', () => { + const subject = parse('pg://myhost/'); + subject.host.should.equal('myhost'); + (subject.database === undefined).should.equal(true); + }); + + it('configuration parameter application_name', () => { + const connectionString = 'pg:///?application_name=TheApp'; + const subject = parse(connectionString); + subject.application_name.should.equal('TheApp'); + }); + + it('configuration parameter fallback_application_name', () => { + const connectionString = 'pg:///?fallback_application_name=TheAppFallback'; + const subject = parse(connectionString); + subject.fallback_application_name.should.equal('TheAppFallback'); + }); + + it('configuration parameter fallback_application_name', () => { + const connectionString = 'pg:///?fallback_application_name=TheAppFallback'; + const subject = parse(connectionString); + subject.fallback_application_name.should.equal('TheAppFallback'); + }); + + it('configuration parameter ssl=true', () => { + const connectionString = 'pg:///?ssl=true'; + const subject = parse(connectionString); + subject.ssl.should.equal(true); + }); + + it('configuration parameter ssl=1', () => { + const connectionString = 'pg:///?ssl=1'; + const subject = parse(connectionString); + subject.ssl.should.equal(true); + }); + + it('configuration parameter ssl=0', () => { + const connectionString = 'pg:///?ssl=0'; + const subject = parse(connectionString); + subject.ssl.should.equal(false); + }); + + it('set ssl', () => { + const subject = parse('pg://myhost/db?ssl=1'); + subject.ssl.should.equal(true); + }); + + it('configuration parameter sslcert=/path/to/cert', () => { + const connectionString = 'pg:///?sslcert=' + encodeURIComponent(path.join(__dirname, '/example.cert')); + const subject = parse(connectionString); + subject.ssl.should.eql({ + cert: 'example cert' + EOL + }); + }); + + it('configuration parameter sslkey=/path/to/key', () => { + const connectionString = 'pg:///?sslkey=' + encodeURIComponent(path.join(__dirname, 'example.key')); + const subject = parse(connectionString); + subject.ssl.should.eql({ + key: 'example key' + EOL + }); + }); + + it('configuration parameter sslrootcert=/path/to/ca', () => { + const connectionString = 'pg:///?sslrootcert=' + encodeURIComponent(path.join(__dirname, 'example.ca')); + const subject = parse(connectionString); + subject.ssl.should.eql({ + ca: 'example ca' + EOL + }); + }); + + it('allow other params like max, ...', () => { + const subject = parse('pg://myhost/db?max=18&min=4'); + subject.max.should.equal('18'); + subject.min.should.equal('4'); + }); + + + it('configuration parameter keepalives', () => { + const connectionString = 'pg:///?keepalives=1'; + const subject = parse(connectionString); + subject.keepalives.should.equal('1'); + }); + + it('unknown configuration parameter is passed into client', () => { + const connectionString = 'pg:///?ThereIsNoSuchPostgresParameter=1234'; + const subject = parse(connectionString); + subject.ThereIsNoSuchPostgresParameter.should.equal('1234'); + }); + + it('do not override a config field with value from query string', () => { + const subject = parse('postgres://some-path.socket/my%5Bdb%5D?encoding=utf8&client_encoding=bogus'); + subject.host.should.equal('some-path.socket'); + 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', () => { + const connectionString = 'pg:///?keepalives=1&keepalives=0'; + const subject = parse(connectionString); + subject.keepalives.should.equal('0'); + }); }); From 12ffac86777a6cf317e1141c7b65bbd5175d520c Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Sat, 6 Jul 2019 14:57:23 +0100 Subject: [PATCH 05/21] integrating generic connection-string --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7b0426e..cc0a0be 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "chai": "^4.1.1", "coveralls": "^3.0.4", "istanbul": "^0.4.5", - "mocha": "^3.5.0" + "mocha": "^6.1.4" }, "files": [ "index.js", From 17ca678a627649f4235b042e2444a42dbb7a1a0f Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Sat, 6 Jul 2019 15:05:21 +0100 Subject: [PATCH 06/21] fixing travis integration. --- .travis.yml | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3902f13..ed2578d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,6 @@ language: node_js -matrix: - include: - - node_js: "4" - script: "npm test" - - node_js: "8" - script: "npm run coveralls" - - node_js: "12" - script: "npm run coveralls" +node_js: + - '6' + - '8' + - '12' +after_success: 'npm run coveralls' From f031cf6803f75f33f623be8c8f19dfbc5f326096 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Sat, 6 Jul 2019 16:03:12 +0100 Subject: [PATCH 07/21] Update index.js correcting comment for `.sock` ending. --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index e57b786..2262970 100644 --- a/index.js +++ b/index.js @@ -28,7 +28,7 @@ function parse(str) { return config; } - // secondary support for unix sockets, when host name ends with '.socket': + // secondary support for unix sockets, when host name ends with '.sock': if (cs.hosts && cs.hosts[0].type === 'socket') { return config; } From 604740e9d393a3cebee141cf6eada71f6163e5bb Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Sat, 6 Jul 2019 16:26:22 +0100 Subject: [PATCH 08/21] Update index.js Improving comments, not to mention `/` support, as both primary and secondary syntax support it the same - encoded. --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 2262970..688501a 100644 --- a/index.js +++ b/index.js @@ -22,7 +22,7 @@ function parse(str) { config.client_encoding = config.encoding; } - // primary sockets support, via parameter 'socket', which also allows use of '/' in the socket name: + // primary sockets support, via parameter 'socket': if (config.socket) { config.host = config.socket; return config; From 7ab78a3dde950ad14b95acab8d1a271407f719e2 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Sat, 6 Jul 2019 18:45:06 +0100 Subject: [PATCH 09/21] Update parse.js improving tests. --- test/parse.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/parse.js b/test/parse.js index 17db773..9f65bbe 100644 --- a/test/parse.js +++ b/test/parse.js @@ -44,14 +44,14 @@ describe('parse', () => { }); it('initializing with unix domain socket, the healthy way', () => { - const subject = parse('//my%5Bdb%5D?encoding=utf8&socket=' + encodeURIComponent('/some path/')); + const subject = parse('/my%5Bdb%5D?encoding=utf8&socket=' + encodeURIComponent('/some path/')); 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', () => { - const subject = parse('//my%2Bdb?encoding=utf8&socket=' + encodeURIComponent('/some path/')); + it('initializing with unix domain socket, the escaped healthy way', () => { + const subject = parse('/my%2Bdb?encoding=utf8&socket=' + encodeURIComponent('/some path/')); subject.host.should.equal('/some path/'); subject.database.should.equal('my+db'); subject.client_encoding.should.equal('utf8'); From bc6f7c0dcd07c1de5f94f0812a1f0c97ac9dd35b Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Sun, 7 Jul 2019 17:14:07 +0100 Subject: [PATCH 10/21] Update package.json updating connection-string version. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cc0a0be..ed2a465 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ }, "homepage": "https://github.com/iceddev/pg-connection-string", "dependencies": { - "connection-string": "^2.4.3" + "connection-string": "^2.4.4" }, "devDependencies": { "chai": "^4.1.1", From ac29740c372e3c5ac1bc15a540faafdc9d7f3dea Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Sun, 7 Jul 2019 18:50:56 +0100 Subject: [PATCH 11/21] Update package.json dependency update. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ed2a465..330e6bf 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ }, "homepage": "https://github.com/iceddev/pg-connection-string", "dependencies": { - "connection-string": "^2.4.4" + "connection-string": "^2.4.5" }, "devDependencies": { "chai": "^4.1.1", From 4c72f9448cb44d52206c82fb0f1a717d169a144e Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Mon, 8 Jul 2019 04:10:26 +0100 Subject: [PATCH 12/21] Update package.json dependency update. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 330e6bf..6deb996 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ }, "homepage": "https://github.com/iceddev/pg-connection-string", "dependencies": { - "connection-string": "^2.4.5" + "connection-string": "^2.5.0" }, "devDependencies": { "chai": "^4.1.1", From 0e7c30bee880cb3be4072c806920544e7cf1ec39 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Mon, 8 Jul 2019 14:41:03 +0100 Subject: [PATCH 13/21] Update parse.js fixing tests. --- test/parse.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/parse.js b/test/parse.js index 9f65bbe..e267ab1 100644 --- a/test/parse.js +++ b/test/parse.js @@ -5,6 +5,7 @@ const EOL = require('os').EOL; const chai = require('chai'); chai.should(); +const expect = chai.expect; const parse = require('../').parse; describe('parse', () => { @@ -208,9 +209,10 @@ describe('parse', () => { subject.client_encoding.should.equal('utf8'); }); - it('return last value of repeated parameter', () => { + it('must throw on repeated parameters', () => { const connectionString = 'pg:///?keepalives=1&keepalives=0'; - const subject = parse(connectionString); - subject.keepalives.should.equal('0'); + expect(() => { + parse(connectionString); + }).throw('Parameter "keepalives" is repeated.'); }); }); From 89fc2f1c1d6bcadc5cceb0803cc068af96f1aed2 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Tue, 9 Jul 2019 01:10:20 +0100 Subject: [PATCH 14/21] Update package.json Upgrading the dependency, for better Unix sockets support. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 6deb996..e1e8fc3 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ }, "homepage": "https://github.com/iceddev/pg-connection-string", "dependencies": { - "connection-string": "^2.5.0" + "connection-string": "^2.6.0" }, "devDependencies": { "chai": "^4.1.1", From 8daf384331c09744d3e6a8fe7b034e45ecea87b1 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Tue, 9 Jul 2019 01:12:12 +0100 Subject: [PATCH 15/21] Update index.js Simplifying support for Unix sockets. --- index.js | 7 ------- 1 file changed, 7 deletions(-) diff --git a/index.js b/index.js index 688501a..aeaf723 100644 --- a/index.js +++ b/index.js @@ -22,13 +22,6 @@ function parse(str) { config.client_encoding = config.encoding; } - // primary sockets support, via parameter 'socket': - if (config.socket) { - config.host = config.socket; - return config; - } - - // secondary support for unix sockets, when host name ends with '.sock': if (cs.hosts && cs.hosts[0].type === 'socket') { return config; } From 36bd3791f52b57d6fa77e020feafc92d366cf2ef Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Tue, 9 Jul 2019 01:22:32 +0100 Subject: [PATCH 16/21] Update parse.js Fixing tests for the new sockets syntax. --- test/parse.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/parse.js b/test/parse.js index e267ab1..b1f1935 100644 --- a/test/parse.js +++ b/test/parse.js @@ -32,34 +32,34 @@ describe('parse', () => { }); it('initializing with unix domain socket', () => { - const subject1 = parse('?socket=' + encodeURIComponent('/const/run/')); + const subject1 = parse('%2Fconst%2Frun%2F'); subject1.host.should.equal('/const/run/'); const subject2 = parse('test.domain.sock'); subject2.host.should.equal('test.domain.sock'); }); it('initializing with unix domain socket and a specific database, the simple way', () => { - const subject = parse('/mydb?socket=' + encodeURIComponent('/const/run/')); + const subject = parse('%2Fconst%2Frun%2F/mydb'); subject.host.should.equal('/const/run/'); subject.database.should.equal('mydb'); }); it('initializing with unix domain socket, the healthy way', () => { - const subject = parse('/my%5Bdb%5D?encoding=utf8&socket=' + encodeURIComponent('/some path/')); + const subject = parse('%2Fsome%20path%2F/my%5Bdb%5D?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.database.should.equal('my[db]', 'must be escaped and unescaped trough "my%5Bdb%5D"'); subject.client_encoding.should.equal('utf8'); }); it('initializing with unix domain socket, the escaped healthy way', () => { - const subject = parse('/my%2Bdb?encoding=utf8&socket=' + encodeURIComponent('/some path/')); + const subject = parse('%2Fsome%20path%2F/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', () => { - const subject = parse('postgres://brian:pw@/mydb?socket=' + encodeURIComponent('/const/run/')); + const subject = parse('postgres://brian:pw@%2Fconst%2Frun%2F/mydb'); subject.user.should.equal('brian'); subject.password.should.equal('pw'); subject.host.should.equal('/const/run/'); From a063df16d0410add03312ce13ef5a48b3b256a51 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Wed, 10 Jul 2019 15:18:42 +0100 Subject: [PATCH 17/21] Update package.json dependency update --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e1e8fc3..0a87d0c 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ }, "homepage": "https://github.com/iceddev/pg-connection-string", "dependencies": { - "connection-string": "^2.6.0" + "connection-string": "^2.6.2" }, "devDependencies": { "chai": "^4.1.1", From d3ea7f91270978b107e2225bec9c0f98402053b9 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Wed, 10 Jul 2019 17:10:43 +0100 Subject: [PATCH 18/21] Update package.json dependency update --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0a87d0c..c737a80 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ }, "homepage": "https://github.com/iceddev/pg-connection-string", "dependencies": { - "connection-string": "^2.6.2" + "connection-string": "^2.7.0" }, "devDependencies": { "chai": "^4.1.1", From be79f093d84a1fd9b1482d8e10f79e3a353c0db4 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Tue, 20 Aug 2019 17:25:39 +0100 Subject: [PATCH 19/21] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c737a80..2e97190 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ }, "homepage": "https://github.com/iceddev/pg-connection-string", "dependencies": { - "connection-string": "^2.7.0" + "connection-string": "^2.8.0" }, "devDependencies": { "chai": "^4.1.1", From 769cafea7a101dd54867b3549b042c3b4cca74d4 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Fri, 30 Aug 2019 03:53:31 +0100 Subject: [PATCH 20/21] Update package.json updating `connection-string` dependency. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2e97190..2ba59a5 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ }, "homepage": "https://github.com/iceddev/pg-connection-string", "dependencies": { - "connection-string": "^2.8.0" + "connection-string": "^3.0.2" }, "devDependencies": { "chai": "^4.1.1", From f08ae09d1cac54d359a6b50cda03a17ebe87c4a5 Mon Sep 17 00:00:00 2001 From: Vitaly Tomilov Date: Fri, 30 Aug 2019 03:54:33 +0100 Subject: [PATCH 21/21] Update index.js updating for use of the latest `connection-string` as a class-only. --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index aeaf723..3bcd37a 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,7 @@ 'use strict'; const fs = require('fs'); -const ConnectionString = require('connection-string'); +const ConnectionString = require('connection-string').ConnectionString; // parses a connection string function parse(str) {