├── .gitignore ├── pg.js ├── package.json ├── README.md └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | -------------------------------------------------------------------------------- /pg.js: -------------------------------------------------------------------------------- 1 | module.exports = require('pg') 2 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "systemic-pg", 3 | "version": "2.0.0", 4 | "description": "A systemic postgres component", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "systemic", 11 | "postgres" 12 | ], 13 | "author": "GuideSmiths Ltd", 14 | "license": "ISC", 15 | "dependencies": { 16 | "async": "^2.6.0", 17 | "lodash.get": "^4.4.2", 18 | "pg": "^8.4.1" 19 | }, 20 | "devDependencies": {}, 21 | "repository": { 22 | "type": "git", 23 | "url": "git+https://github.com/guidesmiths/systemic-pg.git" 24 | }, 25 | "bugs": { 26 | "url": "https://github.com/guidesmiths/systemic-pg/issues" 27 | }, 28 | "homepage": "https://github.com/guidesmiths/systemic-pg#readme" 29 | } 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # systemic-pg 2 | A [systemic](https://github.com/guidesmiths/systemic) pg component 3 | 4 | ## Usage 5 | ```js 6 | const System = require('systemic') 7 | const postgres = require('systemic-pg') 8 | 9 | new System() 10 | .configure({ 11 | postgres: { 12 | host: 'localhost', 13 | database: 'example' 14 | onConnect: [ 15 | "SET client_min_messages = WARNING", 16 | "SET search_path = custom,public" 17 | ] 18 | } 19 | }) 20 | .add('logger', console) 21 | .add('postgres', postgres()).dependsOn('config', 'logger') 22 | .start((err, components) => { 23 | // Do stuff with components.pg 24 | }) 25 | ``` 26 | 27 | ### <= 0.12 28 | systemic-pg relies on the underlying [pg](https://github.com/brianc/node-postgres) library, which uses native promises and is therefore incompatible with node 0.12 and below. You can monkey patch Promise or use an alternative promise implementation by following [these](https://github.com/brianc/node-pg-pool#bring-your-own-promise) instructions. 29 | 30 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var async = require('async') 2 | var get = require('lodash.get') 3 | var format = require('util').format 4 | 5 | module.exports = function(options) { 6 | 7 | var pg = get(options, 'pg') || require('pg') 8 | var pool 9 | var config 10 | var logger 11 | 12 | function init(dependencies, cb) { 13 | config = dependencies.config 14 | logger = dependencies.logger || console 15 | cb() 16 | } 17 | 18 | function validate(cb) { 19 | if (!config) return cb(new Error('config is required')) 20 | cb() 21 | } 22 | 23 | function start(cb) { 24 | logger.info(format('Connecting to %s', getConnectionUrl())) 25 | pool = new pg.Pool(config) 26 | pool.on('connect', client => { 27 | /* 28 | pg maintains the order of queued requests. Since the connect event is synchronous 29 | we can be sure the following statements will be executed before any other queries 30 | */ 31 | client.on('notice', function(notice) { 32 | switch (notice.severity) { 33 | case 'DEBUG': { 34 | logger.debug(notice.message) 35 | break; 36 | } 37 | case 'LOG': { 38 | logger.info(notice.message) 39 | break; 40 | } 41 | case 'INFO': { 42 | logger.info(notice.message) 43 | break; 44 | } 45 | case 'NOTICE': { 46 | logger.info(notice.message) 47 | break; 48 | } 49 | case 'WARNING': { 50 | logger.warn(notice.message) 51 | break; 52 | } 53 | case 'EXCEPTION': { 54 | logger.error(notice.message) 55 | break; 56 | } 57 | default: { 58 | logger.error(notice.message) 59 | break; 60 | } 61 | } 62 | }) 63 | async.eachSeries(config.onConnect || [], function(query, cb) { 64 | client.query(query, function(err) { 65 | if (err) logger.error(format('Error running query: %s', query), err) 66 | cb() 67 | }) 68 | }) 69 | }) 70 | pool.on('error', function(err) { 71 | logger.warn(format('An idle client has experienced an error'), err) 72 | }) 73 | cb(null, pool); 74 | } 75 | 76 | function stop(cb) { 77 | if (!pool) return cb() 78 | logger.info(format('Disconnecting from %s', getConnectionUrl())) 79 | pool.end(cb) 80 | } 81 | 82 | function getConnectionUrl() { 83 | return format('postgres://%s:%s/%s', config.host || 'localhost', config.port || 5432, config.database || '') 84 | } 85 | 86 | return { 87 | start: async.seq(init, validate, start), 88 | stop: stop 89 | } 90 | } 91 | --------------------------------------------------------------------------------