pg-view-grabber
Advanced tools
Comparing version 1.0.0 to 1.1.0
208
index.js
@@ -5,15 +5,8 @@ /* jshint node:true */ | ||
var config = require('config'); | ||
var pg = require('pg'); | ||
var Promise = require('bluebird'); | ||
var ACTIONS = [ | ||
'INSERT', | ||
'SELECT', | ||
'UPDATE', | ||
'DELETE', | ||
'TRUNCATE', | ||
'REFERENCES', | ||
'TRIGGER' | ||
]; | ||
var hasAllPrivileges = require('./utils/has-all-privileges.js'); | ||
var removeEmptiesAndDuplicates = | ||
require('./utils/remove-empties-and-duplicates.js'); | ||
@@ -24,32 +17,2 @@ /** Hold a reference to a `pg.Client`. Configured in the module's export. */ | ||
/** | ||
* Get a connection string from a configuration object. | ||
* | ||
* @param {object} config | ||
* @param {string} config.username | ||
* @param {string} config.password | ||
* @param {(number|string)=} config.port | ||
* @param {string} config.database | ||
* @return {string} Postgres connection string | ||
*/ | ||
function getConnectionString(config) { | ||
return [ | ||
'postgres://' + config.username + ':' + config.password + '@', | ||
config.hostname + (config.port ? ':' + config.port : '') + '/', | ||
config.database, | ||
].join(''); | ||
} | ||
/** | ||
* Does a privileges list contain all priveleges? | ||
* | ||
* @param {string} priveleges | ||
* @return {boolean} | ||
*/ | ||
function hasAllPriveleges(priveleges) { | ||
return ACTIONS.every(function(action) { | ||
return priveleges.indexOf(action) !== -1; | ||
}); | ||
} | ||
/** | ||
* Get view permissions | ||
@@ -61,12 +24,15 @@ * | ||
function getViewPermissions(viewName) { | ||
var queryString = [ | ||
'SELECT grantee, string_agg(privilege_type, \', \') AS privileges', | ||
'FROM information_schema.role_table_grants', | ||
'WHERE table_name=\'' + viewName + '\'', | ||
'GROUP BY grantee;', | ||
].join('\n'); | ||
return new Promise(function(resolve, reject) { | ||
client.query([ | ||
'SELECT grantee, string_agg(privilege_type, \', \') AS privileges', | ||
'FROM information_schema.role_table_grants', | ||
'WHERE table_name=\'' + viewName + '\'', | ||
'GROUP BY grantee;' | ||
].join('\n'), function(error, response) { | ||
client.query(queryString, function(error, response) { | ||
if (error) { | ||
resolve(error); | ||
return reject(error); | ||
} | ||
resolve(response.rows); | ||
@@ -83,3 +49,3 @@ }); | ||
if (hasAllPriveleges(permission.privileges)) { | ||
if (hasAllPrivileges(permission.privileges)) { | ||
output += 'ALL '; | ||
@@ -118,5 +84,4 @@ } else { | ||
if (error) { | ||
reject(error); | ||
return reject(error); | ||
} | ||
resolve(response.rows); | ||
@@ -174,3 +139,3 @@ }); | ||
if (error) { | ||
reject(error); | ||
return reject(error); | ||
} | ||
@@ -182,5 +147,9 @@ | ||
.then(function(rows) { | ||
return rows.map(function(row) { | ||
return row.view_name; | ||
}); | ||
return rows | ||
.map(function(row) { | ||
return row.view_name; | ||
}) | ||
.filter(function(viewName) { | ||
return viewName !== tableName; | ||
}); | ||
}); | ||
@@ -214,3 +183,3 @@ } | ||
if (error) { | ||
reject(error); | ||
return reject(error); | ||
} | ||
@@ -232,22 +201,23 @@ resolve(response.rows); | ||
/** | ||
* Get view data from tablename. | ||
* @see getViewData | ||
* | ||
* @param {object|string} tableName | ||
* @param {array} viewNames | ||
* @return {Promise} Resolves to an array of 'view data' objects. | ||
*/ | ||
function mapViewNamesToViewData(viewNames) { | ||
return Promise.all(viewNames.map(function(viewName) { | ||
return getViewData(viewName); | ||
})); | ||
} | ||
/** | ||
* Initiate a client connect. | ||
* | ||
* @return {Promise} | ||
*/ | ||
module.exports = function getViewDataFromTableName( | ||
connectionConfig, | ||
tableName | ||
) { | ||
if (!connectionConfig) { | ||
throw new Error('PG connection configuration required'); | ||
function getConnectedClient() { | ||
if (!client) { | ||
return Promise.reject(new Error('PG client not configured')); | ||
} | ||
var connectionString = connectionConfig instanceof Object ? | ||
getConnectionString(connectionConfig) : | ||
connectionConfig; | ||
/** Mutate module-level `client` for internal use */ | ||
client = new pg.Client(connectionString); | ||
return new Promise(function(resolve, reject) { | ||
@@ -260,46 +230,66 @@ client.connect(function(error) { | ||
}); | ||
}) | ||
.then(function() { | ||
return getDependentViewsFromTableName(tableName); | ||
}) | ||
.then(function(viewNames) { | ||
var dependentViews = viewNames.map(function(viewName) { | ||
return getDependentViewsFromViewName(viewName); | ||
}); | ||
}); | ||
} | ||
return Promise.all( | ||
[Promise.resolve(viewNames)].concat(dependentViews) | ||
); | ||
}) | ||
/** | ||
* Configure the `pg.Client`. | ||
* | ||
* @{@link https://github.com/brianc/node-postgres/wiki/Client#new-clientobject-config--client} | ||
* | ||
* @param {object|string} tableName | ||
* @return {undefined} | ||
*/ | ||
function configureClient(clientConfig) { | ||
if (!clientConfig) { | ||
throw new Error('PG client configuration required'); | ||
} | ||
/** Mutate module-level `client` for internal use */ | ||
client = new pg.Client(clientConfig); | ||
} | ||
/** | ||
* Get view data from a table's name. | ||
* | ||
* @param {string} tableName | ||
* @return {Promise} Resolves to an array of 'view data' objects | ||
*/ | ||
function getViewDataFromTableName(tableName) { | ||
return getConnectedClient() | ||
.then(getDependentViewsFromTableName.bind(null, tableName)) | ||
.then(removeEmptiesAndDuplicates) | ||
.then(mapViewNamesToViewData) | ||
.then(function(results) { | ||
var viewNames = results[0]; | ||
var dependentViews = results.slice(1).filter(function(views) { | ||
return views.length > 0; | ||
}); | ||
client.end(); | ||
return results; | ||
}, function(error) { | ||
client.end(); | ||
console.error(error); | ||
}); | ||
} | ||
// Remove duplicates | ||
return [].concat.apply(viewNames, dependentViews) | ||
.reduce(function(singles, viewName) { | ||
if (singles.indexOf(viewName) === -1) { | ||
singles.push(viewName); | ||
} | ||
return singles; | ||
}, []); | ||
}) | ||
.then(function(viewNames) { | ||
return Promise.all(viewNames.map(function(viewName) { | ||
return getViewData(viewName); | ||
})); | ||
}) | ||
.then(function(viewDatas) { | ||
// Do something useful | ||
console.log(viewDatas); | ||
}) | ||
.catch(function(error) { | ||
/** | ||
* Get view data from view's name. | ||
* | ||
* @param {string} viewName | ||
* @return {Promise} Resolves to an array of 'view data' objects | ||
*/ | ||
function getViewDataFromViewName(viewName) { | ||
return getConnectedClient() | ||
.then(getDependentViewsFromViewName.bind(null, viewName)) | ||
.then(removeEmptiesAndDuplicates) | ||
.then(mapViewNamesToViewData) | ||
.then(function(results) { | ||
client.end(); | ||
return results; | ||
}, function(error) { | ||
client.end(); | ||
console.error(error); | ||
}) | ||
.then(function() { | ||
client.end(); | ||
}); | ||
} | ||
module.exports = { | ||
config: configureClient, | ||
fromTable: getViewDataFromTableName, | ||
fromView: getViewDataFromViewName, | ||
}; | ||
{ | ||
"name": "pg-view-grabber", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Grab view information from a Postgres database.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
10108
6
297