Comparing version
@@ -26,3 +26,3 @@ #!/usr/local/bin/node | ||
app.cli(['/hello','/helloworld'], function(req,res,next) { | ||
app.cli(['hello','/helloworld'], function(req,res,next) { | ||
res.info('hello world!'); | ||
@@ -29,0 +29,0 @@ }); |
120
lib/clip.js
@@ -19,34 +19,15 @@ var optimist = require('optimist'); | ||
clip.prototype.configure = function configure(name, handler) { | ||
this.middleware.push(function(req,res,next) { | ||
if(req.env.NODE_ENV === name) { | ||
handler(req,res,next) | ||
this.middleware.push(function(cmd,tty,next) { | ||
if(cmd.env.NODE_ENV === name) { | ||
handler(cmd,tty,next) | ||
} | ||
}) | ||
} | ||
clip.prototype.mixin = function mixin(prefix,exports) { | ||
if(!exports) { | ||
exports = prefix; | ||
prefix = ''; | ||
} | ||
for(var method in exports) { | ||
var handler = exports[method] | ||
var signature = prefix + '/' + method | ||
if(typeof handler === 'function' || typeof handler.handler === 'function') { | ||
this.cli(signature, handler.handler || handler) | ||
} | ||
if(handler.usage) { | ||
this.usage(signature, handler.usage) | ||
} | ||
if(handler.mixin) { | ||
this.mixin(signature, handler.mixin) | ||
} | ||
} | ||
} | ||
clip.prototype.params = function params (name, handler) { | ||
var names = [].concat(name) | ||
this.middleware.push(function(req,res,next) { | ||
this.middleware.push(function(cmd,tty,next) { | ||
for(var i = 0; i < names.length; i++) { | ||
var name = names[i]; | ||
if(hasOwnProperty.call(req.params,name)) { | ||
handler(req,res,next) | ||
if(hasOwnProperty.call(cmd.params,name)) { | ||
handler(cmd,tty,next) | ||
return | ||
@@ -60,7 +41,7 @@ } | ||
var names = [].concat(name) | ||
this.middleware.push(function(req,res,next) { | ||
this.middleware.push(function(cmd,tty,next) { | ||
for(var i = 0; i < names.length; i++) { | ||
var name = names[i]; | ||
if(hasOwnProperty.call(req.flags,name)) { | ||
handler(req,res,next) | ||
if(hasOwnProperty.call(cmd.flags,name)) { | ||
handler(cmd,tty,next) | ||
return; | ||
@@ -73,10 +54,11 @@ } | ||
clip.prototype.config = function config (file,options) { | ||
options = options || {}; | ||
var flags = options.flags || []; | ||
var defaults = options.defaults || {}; | ||
var overrides = options.overrides || undefined; | ||
this.use(function configuration(req,res,next) { | ||
this.use(function configuration(cmd,tty,next) { | ||
var filename = file; | ||
for(var i = 0; i < flags.length; i++) { | ||
var flagname = flags[i]; | ||
var value = req.flags[flagname]; | ||
var value = cmd.flags[flagname]; | ||
if (value) { | ||
@@ -89,3 +71,3 @@ filename = value; | ||
config.load(); | ||
req.config = config; | ||
cmd.config = config; | ||
next(); | ||
@@ -105,15 +87,14 @@ }) | ||
cb = function() { | ||
process.exit(res.statusCode); | ||
process.exit(tty.statusCode); | ||
} | ||
} | ||
} | ||
var req = {}; | ||
req.env = cli.env; | ||
req.flags = argv; | ||
req.url = '/' + argv._.map(function encode(component) { | ||
var cmd = {}; | ||
cmd.env = cli.env; | ||
cmd.flags = argv; | ||
cmd.url = '/' + argv._.map(function encode(component) { | ||
return encodeURIComponent(component) | ||
}).join('/'); | ||
req.prompt = prompt; | ||
var res = new CLIResponse(); | ||
this.handle(req, res, cb); | ||
var tty = new TTYHelper(); | ||
this.handle(cmd, tty, cb); | ||
} | ||
@@ -131,2 +112,5 @@ clip.prototype.cli = function cli(routes, handler) { | ||
else { | ||
if(routes[0] !== '/') { | ||
routes = '/' + routes; | ||
} | ||
this.routers.push({ | ||
@@ -149,2 +133,5 @@ matcher: router(routes), | ||
else { | ||
if(routes[0] !== '/') { | ||
routes = '/' + routes; | ||
} | ||
this.usages.push({ | ||
@@ -160,26 +147,26 @@ matcher: router(routes), | ||
function noop() {} | ||
clip.prototype.handle = function handle(req,res,cb) { | ||
if (typeof req === 'string') { | ||
req = { | ||
url: req, | ||
clip.prototype.handle = function handle(cmd,tty,cb) { | ||
if (typeof cmd === 'string') { | ||
cmd = { | ||
url: cmd, | ||
params: optimist.argv | ||
}; | ||
} | ||
req.flags = req.flags || {} | ||
var routers = req.flags.h || req.flags.help ? this.usages : this.routers | ||
cmd.flags = cmd.flags || {} | ||
var routers = cmd.flags.h || cmd.flags.help ? this.usages : this.routers | ||
for(var i = 0; i < routers.length; i++) { | ||
var route = routers[i], match; | ||
if (match = route.matcher(req.url)) { | ||
//matching route, fire off all the middlewares | ||
req.params = match; | ||
res = res || new CLIResponse(); | ||
if (match = route.matcher(cmd.url)) { | ||
//matching route, fire off all the middleware | ||
cmd.params = match; | ||
tty = tty || new CLIResponse(); | ||
if (this.middleware.length) { | ||
var i = 1, $this = this; | ||
this.middleware[0](req,res,function next() { | ||
this.middleware[0](cmd,tty,function next() { | ||
var l = $this.middleware.length; | ||
if (i === l) { | ||
route.handler(req,res,cb||noop); | ||
route.handler(cmd,tty,cb||noop); | ||
} | ||
else if (i < l) { | ||
$this.middleware[i++](req,res,next); | ||
$this.middleware[i++](cmd,tty,next); | ||
} | ||
@@ -189,3 +176,3 @@ }) | ||
else { | ||
route.handler(req,res,cb||noop); | ||
route.handler(cmd,tty,cb||noop); | ||
} | ||
@@ -195,14 +182,20 @@ return; | ||
} | ||
if(!req.flags.h) { | ||
req.flags.h = true; | ||
res.end(404); | ||
this.handle(req, res, cb); | ||
if(!cmd.flags.h) { | ||
if(cmd.url.length > 1 && cmd.url.slice(-1) == '/') { | ||
cmd.url = cmd.url.slice(0,-1); | ||
this.handle(cmd, tty, cb); | ||
} | ||
else { | ||
cmd.flags.h = true; | ||
tty.end(404); | ||
this.handle(cmd, tty, cb); | ||
} | ||
} | ||
else if(req.url) { | ||
req.url = req.url.replace(/([\/]|^)[^\/]*$/,''); | ||
this.handle(req, res, cb); | ||
else if(cmd.url) { | ||
cmd.url = cmd.url[0] + cmd.url.slice(1).replace(/([\/]|^)[^\/]*$/,''); | ||
this.handle(cmd, tty, cb); | ||
} | ||
} | ||
function CLIResponse() { | ||
function TTYHelper() { | ||
this.statusCode = 0; | ||
@@ -216,7 +209,8 @@ for(var key in cliff) { | ||
} | ||
CLIResponse.prototype = winston; | ||
CLIResponse.prototype.end = function end(statusCode) { | ||
TTYHelper.prototype = winston; | ||
TTYHelper.prototype.end = function end(statusCode) { | ||
this.statusCode = statusCode | ||
} | ||
TTYHelper.prototype.prompt = prompt; | ||
module.exports = clip; |
@@ -31,3 +31,3 @@ var partsPattern = '([\\*])|(\\:\\w+)'; | ||
for(var id in ids) { | ||
params[id] = match[ids[id]] | ||
params[id] = decodeURIComponent(match[ids[id]]) | ||
} | ||
@@ -34,0 +34,0 @@ return params; |
@@ -5,6 +5,9 @@ { | ||
"author": "bradleymeck", | ||
"version": "0.1.2", | ||
"keywords": ["CLI"], | ||
"version": "0.1.4", | ||
"keywords": [ | ||
"CLI" | ||
], | ||
"dependencies": { | ||
"reconf": "0.1.x", | ||
"colors": "0.5.x", | ||
"optimist": "0.2.x", | ||
@@ -15,3 +18,6 @@ "prompt": "0.1.x", | ||
}, | ||
"main": "lib/clip.js" | ||
"main": "lib/clip.js", | ||
"bin": { | ||
"clip": "./bin/clip.js" | ||
} | ||
} |
@@ -1,2 +0,2 @@ | ||
Clip is a port of most of the features of Express to CLI programming. | ||
Clip is a port of most of the featutty of Express to CLI programming. | ||
@@ -6,2 +6,15 @@ Many times we want to have complex use cases that are hard to express and routing along Express and Sugarskull seem to be an apt way of doing this. | ||
# Why | ||
Sharing routes between express and cli, since most often they should look the same | ||
Some basic things should be done for you. | ||
Configuration files. | ||
Help for commands should always use the same flags. | ||
# No repl? | ||
You can make a repl by posting urls, not too hard. | ||
Most applications should not need internal repls. | ||
# URLs | ||
@@ -13,3 +26,3 @@ | ||
Request follow the `req,res,next` methodology. | ||
Request follow the `cmd,tty,next` methodology except with `cmd,tty,next` since we are talking about command information, the terminal, and next stays the same. | ||
In the future chaining CLI requests should be easier (ie a clean + build could be done through clip by calling the corresponding urls). | ||
@@ -19,9 +32,9 @@ | ||
``` | ||
req.env = process.env | ||
req.flags = require('optimist').argv | ||
req.config = require('nconf') + app.config(...) | ||
req.prompt = require('prompt') | ||
req.params = app.cli(':param') ... | ||
cmd.env = process.env | ||
cmd.flags = require('optimist').argv | ||
cmd.config = require('nconf') + app.config(...) | ||
cmd.prompt = require('prompt') | ||
cmd.params = app.cli(':param') ... | ||
res = require('winston') + require('cliff') | ||
tty = require('winston') + require('cliff') | ||
``` | ||
@@ -55,26 +68,26 @@ | ||
// | ||
// Recursively find an 'app.json' file with reconf and add it to req.config | ||
// Recursively find an 'app.json' file with reconf and add it to cmd.config | ||
app.config('app.json',{flags:['conf']}); | ||
// Dont print stuff to console if --silent is set | ||
app.flag('silent',function(req,res,next){ | ||
res.remove(res.transports.Console); | ||
app.flag('silent',function(cmd,tty,next){ | ||
tty.remove(tty.transports.Console); | ||
next(); | ||
}); | ||
// Always print out the app info (middleware) | ||
app.use(function(req,res,next){ | ||
res.info('App.js '+version); | ||
app.use(function(cmd,tty,next){ | ||
tty.info('App.js '+version); | ||
next(); | ||
}); | ||
app.usage(function(req,res,next) { | ||
res.info('commands: helloworld, info'); | ||
app.usage(function(cmd,tty,next) { | ||
tty.info('commands: helloworld, info'); | ||
}); | ||
app.cli(['/hello','/helloworld'], function(req,res,next) { | ||
res.info('hello world!'); | ||
app.cli(['/hello','/helloworld'], function(cmd,tty,next) { | ||
tty.info('hello world!'); | ||
}); | ||
var utils = require('util'); | ||
app.cli(['/info','/dump'], function(req,res,next) { | ||
res.data(utils.inspect(req)); | ||
app.cli(['/info','/dump'], function(cmd,tty,next) { | ||
tty.data(utils.inspect(cmd)); | ||
}); | ||
@@ -81,0 +94,0 @@ |
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
18939
49.85%11
37.5%534
57.52%93
16.25%6
20%2
100%+ Added
+ Added