diff --git a/index.js b/index.js index c98b578..da413c3 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,5 @@ /*eslint no-console: 0 */ +const config = require('npm-package-config').list(); const bootstrapPlv8 = require('./lib/bootstrap') const babel = require('babel-core') const browserify = require('browserify') @@ -55,13 +56,13 @@ module.exports = class PLV8 { }) }) .then(code => { - return this.knex('v8.modules').select('*').where({ name: moduleName }) + return this.knex.withSchema(config.pg_schema).select('*').from(config.pg_modules_table).where({ name: moduleName }) .then(result => { if (result.length > 0) { - return this.knex('v8.modules').update({ code }).where({ name: moduleName }) + return this.knex(`${config.pg_schema}.${config.pg_modules_table}`).update({ code }).where({ name: moduleName }) } else { - return this.knex('v8.modules').insert({ code, name: moduleName }) + return this.knex(`${config.pg_schema}.${config.pg_modules_table}`).insert({ code, name: moduleName }) } }) }) @@ -70,7 +71,7 @@ module.exports = class PLV8 { uninstall (moduleId) { const name = moduleId.replace(/^@\w+\//, '') - return this.knex('v8.modules').where({ name }).del() + return this.knex(`${config.pg_schema}.${config.pg_modules_table}`).where({ name }).del() .then(() => true) } @@ -120,7 +121,7 @@ module.exports = class PLV8 { } const code = es5.code.slice(0, -1) - return this.knex.raw('select v8.eval(?) as val', [ `${code}()` ]) + return this.knex.raw(`select ${config.pg_schema}.eval(?) as val`, [ `${code}()` ]) .then(({ rows: [ result ] }) => { const val = result && result.val if (val && val.error === true) { @@ -135,13 +136,13 @@ module.exports = class PLV8 { } init () { - return this.knex('pg_catalog.pg_namespace').select().where({ nspname: 'v8' }) - .then(([ schema ]) => { - if (schema) { + return this.knex('pg_catalog.pg_namespace').select(this.knex.raw(true)).where({ nspname: config.pg_schema }) + .then(([ exists ]) => { + if (exists) { return } else { - return this.knex.raw('create schema if not exists "v8"') + return this.knex.raw(`create schema if not exists "${config.pg_schema}"`) } }) .then(() => { @@ -156,7 +157,7 @@ module.exports = class PLV8 { }) }) .then(() => { - return this.knex.schema.createTableIfNotExists('v8.modules', table => { + return this.knex.schema.withSchema(config.pg_schema).createTableIfNotExists(config.pg_modules_table, table => { table.increments() table.text('name') table.text('code') diff --git a/lib/bootstrap.js b/lib/bootstrap.js index e2faafa..2ca1aff 100644 --- a/lib/bootstrap.js +++ b/lib/bootstrap.js @@ -9,6 +9,7 @@ const evalOptions = { ast: false, babelrc: false } +const config = require('npm-package-config').list(); function plv8_init () { return ` @@ -34,15 +35,15 @@ function plv8_log (level, message) { function plv8_emit (event, payload) { try { payload = JSON.stringify(payload) - plv8.execute('notify ' + event + ', \'' + payload + '\'') + plv8.execute(`notify ${event}, '${payload}'`) } catch (e) { - plv8.execute('notify ' + event) + plv8.execute(`notify ${event}`) } } function xpressionToBody(code){ - return '(' + code + ')' + return `(${code})` } module.exports = function(knex) { @@ -53,44 +54,44 @@ module.exports = function(knex) { EXCEPTION WHEN OTHERS THEN END; $$;`.replace(/\n/g, '')) .then(() => { - return knex.raw(`SET plv8.start_proc = 'v8.plv8_init';`) + return knex.raw(`SET plv8.start_proc = '${config.pg_schema}.plv8_init';`) }) .then(() => { return knex.raw(` DO $$ BEGIN - CREATE DOMAIN v8.json AS json; + CREATE DOMAIN ${config.pg_schema}.json AS json; EXCEPTION WHEN OTHERS THEN END; $$;`.replace(/\n/g, '')) }) .then(() => { - return knex.raw(createStoredProcedure('v8.plv8_init', { }, 'void', plv8_init(), true)) + return knex.raw(createStoredProcedure(`${config.pg_schema}.plv8_init`, { }, 'void', plv8_init(), true)) }) .then(() => { return Promise.all([ - knex.raw(createStoredProcedure('v8.eval', { + knex.raw(createStoredProcedure(`${config.pg_schema}.eval`, { str: 'text' - }, 'v8.json', plv8_eval)), - knex.raw(createStoredProcedure('v8.apply', { + }, `${config.pg_schema}.json`, plv8_eval)), + knex.raw(createStoredProcedure(`${config.pg_schema}.apply`, { str: 'text', - args: 'v8.json' - }, 'v8.json', plv8_apply)), - knex.raw(createStoredProcedure('v8.json_eval', { + args: `${config.pg_schema}.json` + }, `${config.pg_schema}.json`, plv8_apply)), + knex.raw(createStoredProcedure(`${config.pg_schema}.json_eval`, { code: 'text' - }, 'v8.json', wrapStoredProcedure(0), { + }, `${config.pg_schema}.json`, wrapStoredProcedure(0), { cascade: true, boot: true })), - knex.raw(createStoredProcedure('v8.json_eval', { - data: 'v8.json', + knex.raw(createStoredProcedure(`${config.pg_schema}.json_eval`, { + data: `${config.pg_schema}.json`, code: 'text' - }, 'v8.json', wrapStoredProcedure(-1), { + }, `${config.pg_schema}.json`, wrapStoredProcedure(-1), { cascade: true, boot: true })), - knex.raw(createStoredProcedure('v8.json_eval', { + knex.raw(createStoredProcedure(`${config.pg_schema}.json_eval`, { code: 'text', - data: 'v8.json' - }, 'v8.json', wrapStoredProcedure(1), { + data: `${config.pg_schema}.json` + }, `${config.pg_schema}.json`, wrapStoredProcedure(1), { cascade: true, boot: true })) @@ -101,16 +102,17 @@ function plv8_eval (str) { return eval(str) } function plv8_apply (func, args){ - func = '(function() {return (' + func + ');})()' + func = `(function() {return (${func});})()` return eval(func).apply(null, args) } function plv8_require (name) { - var module = plv8.execute('select name, code from v8.modules where name = $1', [ name ])[0]; + var module = plv8.execute('select name, code from ${config.pg_schema}.${config.pg_modules_table} where name = $1', [ name ])[0]; if (!module) { - plv8.elog(WARNING, 'Cannot find module \'' + name + '\''); - return new Error('Cannot find module \'' + name + '\''); + let msg = `Cannot find module '${name}` + plv8.elog(WARNING, msg); + return new Error(msg); } require.cache[name] = eval(module.code) @@ -137,7 +139,7 @@ function wrapStoredProcedure (type = 1) { function createStoredProcedure (name, paramObj, ret, func, init) { const signature = _.map(paramObj, (type, key) => { return { - arg: (type === 'v8.json') ? `JSON.parse('${key}')` : key, + arg: (type === `${config.pg_schema}.json`) ? `JSON.parse('${key}')` : key, param: `${key} ${type}` } }) @@ -148,11 +150,11 @@ function createStoredProcedure (name, paramObj, ret, func, init) { let statement = `(${code})(${args})` - if (ret === 'v8.json') { + if (ret === `${config.pg_schema}.json`) { statement = `JSON.stringify(${statement})` } - let initStatement = 'plv8.execute("select v8.plv8_init()");' + let initStatement = `plv8.execute("select ${config.pg_schema}.plv8_init()");` if (init) { initStatement = '' } diff --git a/lib/cli.js b/lib/cli.js new file mode 100755 index 0000000..08ca6e1 --- /dev/null +++ b/lib/cli.js @@ -0,0 +1,124 @@ +#!/usr/bin/env node + +'use strict'; + +const config = require('npm-package-config').list(); + +const program = require('commander') + +program + .version('1.0.0') + +program + .command('install ') + .description('install one or more packages into the DB') + .alias('i') + .action((modules, options) => install(modules,options)) + +program + .command('uninstall ') + .description('uninstall one or more packages from the DB') + .alias('u') + .action((modules, options) => uninstall(modules,options)) + +program + .command('list') + .description('list the packages currently installed in the DB') + .alias('l') + .action((options) => list(options)) + +program + .on('--help', () => console.log(` + Environment Configuration Options + (Set with npm config or in your package.json) + + pg_user: The name of the PostgreSQL user with which to authenticate -- default "postgres"; current "${config.pg_user}" + pg_pass: The password of the PostgreSQL user with which to authenticate -- default "postgres"; current "****" + pg_host: The name of the PostgreSQL server with which to connect -- default "localhost"; current "${config.pg_host}" + pg_port: The port number of the PostgreSQL server -- default 5432; current "${config.pg_port}" + pg_database: The database with which to interact -- default "postgres"; current "${config.pg_database}" + pg_schema: the name of the schema in which to store modules -- default "v8"; current "${config.pg_schema}" + pg_modules_table: The name of the table in which to store modules -- default "modules"; current "${config.pg_modules_table}" + `) + ) + +program.parse(process.argv) + +function init(options) { + const PLV8 = require('..'), + knex = require('knex'), + plv8 = new PLV8(knex({ + client: 'pg', + connection: { + host: config.pg_host, + port: config.pg_port, + database: config.pg_database, + user: config.pg_user, + password: config.pg_pass + } + })) + return plv8 +} + + +function list(options) { + const plv8 = init(options) + console.log('Currently installed modules:') + plv8.knex + .select('name') + .from(`${config.pg_schema}.modules`) + .then(result => { + result.forEach(row => console.log(row.name)); + }) + .then(() => plv8.knex.destroy() ) + .catch(err => { + console.log(""+err) + process.exit(1) + }) +} + +function uninstall(modules, options) { + const plv8 = init(options) + modules.forEach(name => { + plv8.knex(`${config.pg_schema}.${config.pg_modules_table}`) + .where({name}) + .del() + .returning({name}) + .then(result => console.log(`${result} removed`) ) + .then(() => plv8.knex.destroy() ) + .catch(err => { + console.log(""+err) + process.exit(1) + }) + }) +} + +function install(modules, options) { + if (!modules.length) { + console.error('One or more package arguments required.') + process.exit(1) + } + + const plv8 = init(options) + let moduleInstalls = modules.reduce((promiseChain, item) => { + return promiseChain.then(() => new Promise((resolve) => { + plv8 + .install({ + modulePath: require.resolve(item), + moduleName: item + }) + .then(moduleName => { + console.log(`module ${moduleName} installed`) + resolve() + }) + .catch(err => { + console.log(""+err) + process.exit(1) + }) + })) + }, Promise.resolve()) + + + moduleInstalls + .then(() => plv8.knex.destroy() ) +} diff --git a/package.json b/package.json index 65e6e81..6ff070f 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "require" ], "main": "index.js", + "bin": "./lib/cli.js", "repository": { "type": "git", "url": "git://github.com/langateam/plv8.git" @@ -27,6 +28,14 @@ "email": "tjwebb@langa.io" } ], + "config": { + "pg_schema": "v8", + "pg_modules_table": "modules", + "pg_user": "postgres", + "pg_host": "localhost", + "pg_port": 5432, + "pg_database": "postgres" + }, "scripts": { "test": "mocha" }, @@ -40,7 +49,9 @@ "babel-preset-es2015": "^6.9.0", "babelify": "^7.3.0", "browserify": "^13.1.0", - "lodash": "^4.13.1" + "commander": "^2.9.0", + "lodash": "^4.13.1", + "npm-package-config": "^0.4.0" }, "devDependencies": { "babel-preset-es2015": "^6.9.0",