-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 18e085f
Showing
6 changed files
with
270 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules | ||
.gooseconrc |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
#!/usr/bin/env node | ||
|
||
var repl = require('repl'); | ||
var fs = require('fs'); | ||
var path = require('path'); | ||
var vm = require('vm'); | ||
var util = require('util'); | ||
var rc = require('rc'); | ||
var _ = require('underscore'); | ||
var chalk = require('chalk'); | ||
|
||
var argv = require('yargs') | ||
.usage('Usage: $0 <command> [options]') | ||
.command('goosecon', 'Run goosecon') | ||
.alias('console') | ||
.demand(1) | ||
.option('mongo-db', { | ||
describe: 'MongoDB URL' | ||
}) | ||
.option('models-path', { | ||
describe: 'Path to models directory' | ||
}) | ||
.option('mongoose-path', { | ||
describe: 'Path to mongoose' | ||
}) | ||
.help('h') | ||
.alias('h', 'help') | ||
.argv; | ||
|
||
// Override options | ||
var config = rc('goosecon', {}, argv); | ||
|
||
// console.log(config); | ||
|
||
var mongoosePath = config.mongoosePath ? path.resolve(process.cwd() + config.mongoosePath) : 'mongoose'; | ||
var mongoose = require(mongoosePath); | ||
var replServer; | ||
|
||
mongoose.connect(config.mongoDb); | ||
|
||
mongoose.connection.on('error', function(err) { | ||
console.error('Unable to connect to db ' + config.mongoDb + '\n' + err); | ||
process.exit(1); | ||
}); | ||
|
||
function startReplServer () { | ||
replServer = repl.start({ | ||
eval: function(cmd, context, filename, cb) { | ||
var result; | ||
|
||
try { | ||
result = vm.runInContext(cmd, context, filename); | ||
} | ||
catch(err) { return cb(err); } | ||
|
||
// instanceof doesn't work when mongoose version < 4 | ||
if (_.isObject(result) && (result instanceof mongoose.Query || result.constructor.name === 'Query')) { | ||
result.exec(function(err, doc) { | ||
if (err) return cb(err); | ||
return cb(null, doc); | ||
}); | ||
} else { | ||
cb(null, result); | ||
} | ||
}, | ||
writer: function(val) { | ||
if (!val) return ''; | ||
|
||
try { | ||
val = JSON.parse(JSON.stringify(val)); | ||
console.log(util.inspect(val, { colors: true })); | ||
return ''; | ||
} | ||
catch(err) { console.error('Unable to stringify JSON'); } | ||
|
||
console.log(val); | ||
return ''; // Prevents 'undefined' output | ||
} | ||
}); | ||
} | ||
|
||
function addModulesToContext() { | ||
var moduleNames = []; | ||
var files = _.compact(_.flatten([findModelFiles(), findOtherModules()])); | ||
|
||
// Add models to repl context | ||
files.forEach(function(file) { | ||
var module; | ||
try { module = require(file); } | ||
catch(err) { return; } | ||
|
||
// Get module name and capitalize first letter | ||
var moduleName = path.basename(file, '.js'); | ||
moduleName = moduleName.charAt(0).toUpperCase() + moduleName.slice(1); | ||
|
||
replServer.context[moduleName] = module; | ||
moduleNames.push(moduleName); | ||
}); | ||
|
||
if (moduleNames) | ||
console.log(chalk.grey('** Loaded: ') + chalk.red(moduleNames.join(', '))); | ||
replServer.displayPrompt(); | ||
} | ||
|
||
function findModelFiles() { | ||
var modelsPath = config.modelsPath; | ||
var files; | ||
|
||
if (!modelsPath) { | ||
var cwdFiles = fs.readdirSync(process.cwd()); | ||
|
||
// Search working directory for models directory | ||
if (_.contains(cwdFiles, 'models')) | ||
modelsPath = path.resolve(process.cwd() + '/' + 'models'); | ||
else | ||
return; | ||
} | ||
|
||
files = fs.readdirSync(modelsPath); | ||
files = files.map(function(file) { return path.resolve(modelsPath + '/' + file); }); | ||
|
||
return files; | ||
} | ||
|
||
function findOtherModules() { | ||
if (!config.modules) return; | ||
|
||
// Convert command line argument to array | ||
var modulesDirectories = typeof config.modules === 'string' ? [config.modules] : config.modules; | ||
|
||
var modules = modulesDirectories.map(function(modulesDirPath) { | ||
var files = fs.readdirSync(modulesDirPath); | ||
return files.map(function(file) { return path.resolve(modulesDirPath + '/' + file); }); | ||
}); | ||
|
||
return modules; | ||
} | ||
|
||
startReplServer(); | ||
addModulesToContext(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
{ | ||
"name": "goosecon", | ||
"version": "0.1.0", | ||
"description": "A Mongoose console that auto-loads models and other modules", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"license": "ISC", | ||
"dependencies": { | ||
"chalk": "^1.1.0", | ||
"mongoose": "^4.1.2", | ||
"rc": "^1.1.0", | ||
"underscore": "^1.8.3", | ||
"yargs": "^3.18.0" | ||
}, | ||
"devDependencies": { | ||
"chai": "^3.2.0", | ||
"mocha": "^2.2.5" | ||
}, | ||
"bin": { | ||
"console": "./bin/goosecon.js" | ||
}, | ||
"engines": { | ||
"node": ">=0.10.x" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
var spawn = require('child_process').spawn; | ||
var expect = require('chai').expect; | ||
var path = require('path'); | ||
var chalk = require('chalk'); | ||
|
||
describe('mongoose-console', function() { | ||
var replServer; | ||
var filePath = path.resolve(__dirname + "/../bin/console.js"); | ||
|
||
before(function() { | ||
replServer = spawn('node', [filePath, 'console', '--mongo-db', 'mongodb://localhost/test', '--models-path', './test/models', '--modules', './test/modules']); | ||
|
||
var result = ''; | ||
var err = ''; | ||
|
||
replServer.stdout.on('data', function(data) { | ||
result += data; | ||
// console.log(result); | ||
}); | ||
replServer.stderr.on('data', function(data) { | ||
err += data; | ||
// console.log(err); | ||
}); | ||
}); | ||
|
||
after(function() { | ||
replServer.kill(); | ||
}); | ||
|
||
it('Throws error if not connected to db', function(done) { | ||
var cp = spawn('node', [filePath, 'console']); | ||
|
||
var err = ''; | ||
cp.stderr.on('data', function(data) { err += data; }); | ||
cp.on('exit', function (code) { | ||
expect(err).contains('Unable to connect to db'); | ||
expect(code).to.equal(1); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('Loads models into context', function(done) { | ||
test('Person.name', function(err, result) { | ||
expect(err).to.be.empty; | ||
expect(result).to.equal('model'); | ||
done(); | ||
}); | ||
}); | ||
|
||
it('Loads modules into context', function(done) { | ||
test('typeof Service', function(err, result) { | ||
expect(err).to.be.empty; | ||
expect(result).to.equal('object'); | ||
done(); | ||
}); | ||
}); | ||
|
||
function test(cmd, cb) { | ||
var result = ''; | ||
var err = ''; | ||
var timer; | ||
|
||
replServer.stdout.on('data', function(data) { result += data; }); | ||
replServer.stderr.on('data', function(data) { err += data; }); | ||
|
||
replServer.stdin.write(cmd + '\n'); | ||
|
||
function finish() { | ||
if (result.length === 0 && err.length === 0) { | ||
timer = setTimeout(finish, 500); | ||
return; | ||
} | ||
|
||
replServer.stdout.removeAllListeners('data'); | ||
replServer.stderr.removeAllListeners('data'); | ||
return cb(err, clean(result)); | ||
} | ||
timer = setTimeout(finish, 500); | ||
} | ||
|
||
// Removes ANSI colors and extracts output between quotes | ||
function clean(string) { | ||
string = chalk.stripColor(string); | ||
var substringMatches = string.match(/'([^']+)'/); | ||
|
||
if (substringMatches.length > 1) | ||
string = substringMatches[1]; | ||
|
||
return string; | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
var mongoose = require('mongoose') | ||
var Schema = mongoose.Schema; | ||
|
||
var personSchema = new Schema({ | ||
name: String | ||
}); | ||
|
||
module.exports = mongoose.model('Person', personSchema); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module.exports.hello = function() { | ||
console.log('Hello World'); | ||
}; |