heroku/heroku-pg

View on GitHub
lib/psql.js

Summary

Maintainability
C
1 day
Test Coverage
'use strict'
 
const co = require('co')
const bastion = require('./bastion')
const debug = require('./debug')
 
function handlePsqlError (reject, psql) {
psql.on('error', (err) => {
if (err.code === 'ENOENT') {
reject(`The local psql command could not be located. For help installing psql, see https://devcenter.heroku.com/articles/heroku-postgresql#local-setup`)
} else {
reject(err)
}
})
}
 
Similar blocks of code found in 2 locations. Consider refactoring.
function execPsql (query, dbEnv) {
const {spawn} = require('child_process')
return new Promise((resolve, reject) => {
let result = ''
debug('Running query: %s', query.trim())
let psql = spawn('psql', ['-c', query], {env: dbEnv, encoding: 'utf8', stdio: [ 'ignore', 'pipe', 'inherit' ]})
psql.stdout.on('data', function (data) {
result += data.toString()
})
psql.on('close', function (code) {
resolve(result)
})
handlePsqlError(reject, psql)
})
}
 
Similar blocks of code found in 2 locations. Consider refactoring.
function execPsqlWithFile (file, dbEnv) {
const {spawn} = require('child_process')
return new Promise((resolve, reject) => {
let result = ''
debug('Running sql file: %s', file.trim())
let psql = spawn('psql', ['-f', file], {env: dbEnv, encoding: 'utf8', stdio: [ 'ignore', 'pipe', 'inherit' ]})
psql.stdout.on('data', function (data) {
result += data.toString()
})
psql.on('close', function (code) {
resolve(result)
})
handlePsqlError(reject, psql)
})
}
 
function psqlInteractive (dbEnv, prompt) {
const {spawn} = require('child_process')
return new Promise((resolve, reject) => {
let psql = spawn('psql',
['--set', `PROMPT1=${prompt}`, '--set', `PROMPT2=${prompt}`],
{env: dbEnv, stdio: 'inherit'})
handlePsqlError(reject, psql)
psql.on('close', (data) => {
resolve()
})
})
}
 
function handleSignals () {
process.removeAllListeners('SIGINT')
process.on('SIGINT', () => {})
}
 
function * exec (db, query) {
handleSignals()
let configs = bastion.getConfigs(db)
 
yield bastion.sshTunnel(db, configs.dbTunnelConfig)
return yield execPsql(query, configs.dbEnv)
}
 
async function execFile (db, file) {
handleSignals()
let configs = bastion.getConfigs(db)
 
await bastion.sshTunnel(db, configs.dbTunnelConfig)
return execPsqlWithFile(file, configs.dbEnv)
}
 
function * interactive (db) {
let name = db.attachment.name
let prompt = `${db.attachment.app.name}::${name}%R%# `
handleSignals()
let configs = bastion.getConfigs(db)
 
yield bastion.sshTunnel(db, configs.dbTunnelConfig)
return yield psqlInteractive(configs.dbEnv, prompt)
}
 
module.exports = {
exec: co.wrap(exec),
execFile: execFile,
interactive: co.wrap(interactive)
}