Comparing version 0.2.2 to 0.2.3
@@ -1,2 +0,2 @@ | ||
require('coffee-script') | ||
require('coffee-script'); | ||
@@ -6,2 +6,3 @@ // Core | ||
Shell.styles = require('./lib/Styles'); | ||
Shell.NullStream = require('./lib/NullStream'); | ||
@@ -30,2 +31,2 @@ // Plugins | ||
return new Shell( settings ); | ||
} | ||
}; |
{ | ||
"name": "shell", | ||
"version": "0.2.2", | ||
"version": "0.2.3", | ||
"description": "Full features and pretty console applications", | ||
@@ -9,2 +9,8 @@ "author": "David Worms <david@adaltas.com>", | ||
"email": "david@adaltas.com" | ||
},{ | ||
"name": "Tony", | ||
"email": "https://github.com/Zearin" | ||
},{ | ||
"name": "Russ Frank", | ||
"email": "https://github.com/russfrank" | ||
}], | ||
@@ -17,4 +23,3 @@ "engines": { | ||
"each": "latest", | ||
"pad": "latest", | ||
"coffeekup": "latest" | ||
"pad": "latest" | ||
}, | ||
@@ -21,0 +26,0 @@ "keywords": ["cli", "console", "colors", "xterm"], |
465
README.md
@@ -1,49 +0,53 @@ | ||
# Shell - Nice looking shell applications with pluggable middlewares. | ||
# Shell: applications with pluggable middleware | ||
The project brings a Connect/Express inspired API and similar functionnalities to console based applications. | ||
Shell brings a Connect inspired API, Express inspired routing, and other | ||
similar functionality to console based applications. | ||
## Quick Example, a redis client | ||
## Example: a simple Redis client | ||
```javascript | ||
var shell = require('shell'); | ||
// Initialization | ||
var app = new shell(); | ||
// Plugins registration | ||
app.configure(function() { | ||
app.use(shell.history({ | ||
shell: app | ||
})); | ||
app.use(shell.completer({ | ||
shell: app | ||
})); | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
app.use(shell.redis({ | ||
shell: app, | ||
config: 'redis.conf', | ||
pidfile: 'redis.pid' | ||
})); | ||
app.use(shell.help({ | ||
shell: app, | ||
introduction: true | ||
})); | ||
var shell = require('shell'); | ||
// Initialization | ||
var app = new shell(); | ||
// Middleware registration | ||
app.configure(function() { | ||
app.use(shell.history({ | ||
shell: app | ||
})); | ||
app.use(shell.completer({ | ||
shell: app | ||
})); | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
app.use(shell.redis({ | ||
shell: app, | ||
config: 'redis.conf', | ||
pidfile: 'redis.pid' | ||
})); | ||
app.use(shell.help({ | ||
shell: app, | ||
introduction: true | ||
})); | ||
}); | ||
// Command registration | ||
app.cmd('redis keys :pattern', 'Find keys', function(req, res, next){ | ||
if(!app.client){ | ||
app.client = require('redis').createClient(); | ||
} | ||
app.client.keys(req.params.pattern, function(err, keys){ | ||
if(err){ return res.styles.red(err.message), next(); } | ||
res.cyan(keys.join('\n')||'no keys'); | ||
res.prompt(); | ||
}); | ||
// Command registration | ||
app.cmd('redis keys :pattern', 'Find keys', function(req, res, next){ | ||
if(!app.client){ | ||
app.client = require('redis').createClient(); | ||
} | ||
app.client.keys(req.params.pattern, function(err, keys){ | ||
if(err){ return res.styles.red(err.message), next(); } | ||
res.cyan(keys.join('\n')||'no keys'); | ||
res.prompt(); | ||
}); | ||
}); | ||
// Event notification | ||
app.on('redis quit', function(){ | ||
if(app.client){ | ||
app.client.quit(); | ||
} | ||
}); | ||
}); | ||
// Event notification | ||
app.on('redis quit', function(){ | ||
if(app.client){ | ||
app.client.quit(); | ||
} | ||
}); | ||
``` | ||
@@ -54,3 +58,3 @@ | ||
```bash | ||
npm install shell | ||
npm install shell | ||
``` | ||
@@ -61,89 +65,105 @@ | ||
```javascript | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.history({shell: app})); | ||
app.use(shell.completer({shell: app})); | ||
app.use(shell.help({shell: app, introduction: true})); | ||
}); | ||
app.configure('prod', function() { | ||
app.set('title', 'Production Mode'); | ||
}); | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.history({shell: app})); | ||
app.use(shell.completer({shell: app})); | ||
app.use(shell.help({shell: app, introduction: true})); | ||
}); | ||
app.configure('prod', function() { | ||
app.set('title', 'Production Mode'); | ||
}); | ||
``` | ||
The constructor `shell` take an optional object. Options are: | ||
## Shell settings | ||
- `env` , Running environment (eg: `production`, `develepment`) | ||
- `prompt`, Character for command prompt, Defaults to ">>" | ||
- `stdin` , Source to read from | ||
- `stdout`, Destination to write to | ||
The constructor `shell` takes an optional object. Options are: | ||
As with Express, `app.configure` allows the customization of plugins for all or specific environments, while `app.use` registers plugins. | ||
- `chdir` , Changes the current working directory of the process, a string of the directory, boolean true will default to the `workspace` (in which case `workspace` must be provided or discoverable) | ||
- `prompt` , Character for command prompt, Defaults to ">>" | ||
- `stdin` , Source to read from | ||
- `stdout` , Destination to write to | ||
- `env` , Running environment, Defaults to the `env` setting (or `NODE_ENV` if defined, eg: `production`, `develepment`). | ||
- `isShell` , Detect whether the command is runned inside a shell are as a single command. | ||
- `noPrompt` , Do not prompt the user for a command, usefull to plug your own starting mechanisme (eg: starting with a question). | ||
- `workspace` , Project root directory or null if none was found. The discovery strategy start from the current working directory and traverse each parent dir looking for a `node_module` directory or a `package.json` file. | ||
If `app.configure` is called without specifying the environment as the first argument, the provided callback is always called. Otherwise, the environment must match the `env` setting or the global variable `NODE_ENV`. | ||
## Shell settings | ||
Shell settings may be set by calling `app.set('key', value)`. They can be retrieved by calling the same function without a second argument. | ||
```javascript | ||
var app = new shell(); | ||
app.set('env', 'prod'); | ||
app.configure('prod', function() { | ||
console.log(app.set('env')); | ||
}); | ||
var app = new shell({ | ||
chdir: true | ||
}); | ||
app.set('env', 'prod'); | ||
app.configure('prod', function() { | ||
console.log(app.set('env')); | ||
}); | ||
``` | ||
- `env` , Running environment, Defaults to the `env` setting (or `NODE_ENV` if defined). | ||
- `isShell` , Detect whether the command is runned inside a shell are as a single command. | ||
- `noPrompt` , Do not prompt the user for a command, usefull to plug your own starting mechanisme (eg: starting with a question). | ||
- `workspace` , Project root directory or null if none was found. The discovery strategy start from the current working directory and traverse each parent dir looking for a `node_module` directory or a `package.json` file. | ||
As with Express, `app.configure` allows the customization of plugins for all or specific environments, while `app.use` registers plugins. | ||
If `app.configure` is called without specifying the environment as the first argument, the provided callback is always called. Otherwise, the environment must match the `env` setting or the global variable `NODE_ENV`. | ||
## Shell events | ||
By extending `EventEmitter`, the following events are emitted: | ||
The following events may be emitted: | ||
- `"command"`, listen to all executed commands, provide the command name as first argument | ||
- `#{command}`, listen to a particular event | ||
- `"exit"`, called on application exit | ||
- `"command"` , listen to all executed commands, provide the command name as first argument. | ||
- `#{command}` , listen to a particular event. | ||
- `"quit"` , called when the application is about to quit. | ||
- `"error"` , called on error providing the error object as the first callback argument. | ||
- `"exit"` , called when the process exit. | ||
## Routes plugin | ||
## Router plugin | ||
The functionalities are a full transcription of the ones present Express. Options passed during creation are: | ||
The functionality provided by the 'routes' module is very similar to that of | ||
express. Options passed during creation are: | ||
- `shell` , (required) A reference to your shell application. | ||
- `sensitive` , (optional) Defaults to `false`, set to `true` if the match should be case sensitive. | ||
- `sensitive` , (optional) Defaults to `false`, set to `true` if the match should be case sensitive. | ||
New routes are defined with the `cmd` method. A route is made of pattern against which the user command is matched, an optional description and one or more route specific middlewares to handle the command. The pattern is either a string or a regular expression. Middlewares receive three parameters: a request object, a response object, and a function. Command parameters are substituted and made available in the `params` object of the request parameter. | ||
Parameters can have restrictions in parenthesis immediately following the | ||
keyword, as in express: `:id([0-9]+)`. See the `list` route in the example: | ||
```javascript | ||
var app = new shell(); | ||
app.configure(function(){ | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
}); | ||
// Route middleware | ||
var auth = function(req, res, next){ | ||
if(req.params.uid == process.getuid()){ | ||
next() | ||
}else{ | ||
throw new Error('Not me'); | ||
} | ||
} | ||
// Global parameter substitution | ||
app.param('uid', function(req, res, next){ | ||
exec('whoami', function(err, stdout, sdterr){ | ||
req.params.username = stdout; | ||
next(); | ||
}); | ||
}); | ||
// Simple command | ||
app.cmd('help', function(req, res){ | ||
res.cyan('Run this command `./ami user ' + process.getuid() + '`'); | ||
res.prompt() | ||
}); | ||
// Command with parameter and two route middlewares | ||
app.cmd('user :uid', auth, function(req, res){ | ||
res.cyan('Yes, you are ' + req.params.username); | ||
}); | ||
var app = new shell(); | ||
app.configure(function(){ | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
}); | ||
// Route middleware | ||
var auth = function(req, res, next){ | ||
if(req.params.uid == process.getuid()){ | ||
next() | ||
}else{ | ||
throw new Error('Not me'); | ||
} | ||
} | ||
// Global parameter substitution | ||
app.param('uid', function(req, res, next){ | ||
exec('whoami', function(err, stdout, sdterr){ | ||
req.params.username = stdout; | ||
next(); | ||
}); | ||
}); | ||
// Simple command | ||
app.cmd('help', function(req, res){ | ||
res.cyan('Run this command `./ami user ' + process.getuid() + '`'); | ||
res.prompt() | ||
}); | ||
// Command with parameter and two route middlewares | ||
app.cmd('user :uid', auth, function(req, res){ | ||
res.cyan('Yes, you are ' + req.params.username); | ||
}); | ||
app.cmd('list :id([0-9]+)', function(req, res) { | ||
res.cyan('List: foo bar'); | ||
res.prompt(); | ||
}); | ||
``` | ||
@@ -155,6 +175,37 @@ | ||
- `command` , Command entered by the user | ||
- `params` , parameters object extracted from the command, defined by the `shell.router` middleware | ||
- `params` , Parameters object extracted from the command, defined by the `shell.router` middleware | ||
The response object inherits from styles containing various utilities for printing, coloring and bolding. | ||
The response object inherits from styles containing methods for printing, coloring and bolding: | ||
Colors: | ||
- `black` | ||
- `white` | ||
- `yellow` | ||
- `blue` | ||
- `cyan` | ||
- `green` | ||
- `magenta` | ||
- `red` | ||
- `bgcolor` | ||
- `color` | ||
- `nocolor` | ||
Style: | ||
- `regular` | ||
- `weight` | ||
- `bold` | ||
Display: | ||
- `prompt` , Exits the current command and return user to the prompt. | ||
- `ln` | ||
- `print` | ||
- `println` | ||
- `constructor` | ||
- `reset` | ||
- `pad` | ||
- `raw` | ||
## History plugin | ||
@@ -197,15 +248,15 @@ | ||
```javascript | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
app.use(shell.http({ | ||
shell: app | ||
})); | ||
app.use(shell.help({ | ||
shell: app, | ||
introduction: true | ||
})); | ||
}); | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
app.use(shell.http({ | ||
shell: app | ||
})); | ||
app.use(shell.help({ | ||
shell: app, | ||
introduction: true | ||
})); | ||
}); | ||
``` | ||
@@ -226,16 +277,16 @@ | ||
```javascript | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
app.use(shell.redis({ | ||
shell: app, | ||
config: __dirname+'/redis.conf') | ||
})); | ||
app.use(shell.help({ | ||
shell: app, | ||
introduction: true | ||
})); | ||
}); | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
app.use(shell.redis({ | ||
shell: app, | ||
config: __dirname+'/redis.conf') | ||
})); | ||
app.use(shell.help({ | ||
shell: app, | ||
introduction: true | ||
})); | ||
}); | ||
``` | ||
@@ -264,16 +315,16 @@ | ||
```javascript | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
app.use(shell.cloud9({ | ||
shell: app, | ||
ip: '0.0.0.0' | ||
})); | ||
app.use(shell.help({ | ||
shell: app, | ||
introduction: true | ||
})); | ||
}); | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
app.use(shell.cloud9({ | ||
shell: app, | ||
ip: '0.0.0.0' | ||
})); | ||
app.use(shell.help({ | ||
shell: app, | ||
introduction: true | ||
})); | ||
}); | ||
``` | ||
@@ -286,7 +337,7 @@ | ||
``` | ||
git clone https://github.com/ajaxorg/cloud9.git | ||
cd cloud9 | ||
git checkout -b devel origin/devel | ||
git submodule update --init --recursive | ||
npm link | ||
git clone https://github.com/ajaxorg/cloud9.git | ||
cd cloud9 | ||
git checkout -b devel origin/devel | ||
git submodule update --init --recursive | ||
npm link | ||
``` | ||
@@ -313,15 +364,15 @@ | ||
```javascript | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
app.use(shell.coffee({ | ||
shell: app | ||
})); | ||
app.use(shell.help({ | ||
shell: app, | ||
introduction: true | ||
})); | ||
}); | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
app.use(shell.coffee({ | ||
shell: app | ||
})); | ||
app.use(shell.help({ | ||
shell: app, | ||
introduction: true | ||
})); | ||
}); | ||
``` | ||
@@ -334,13 +385,13 @@ | ||
```javascript | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
}); | ||
app.cmd('install', [ | ||
my_app.routes.download, | ||
my_app.routes.configure, | ||
shell.routes.prompt('Installation is finished') | ||
]); | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
}); | ||
app.cmd('install', [ | ||
my_app.routes.download, | ||
my_app.routes.configure, | ||
shell.routes.prompt('Installation is finished') | ||
]); | ||
``` | ||
@@ -353,13 +404,13 @@ | ||
```javascript | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
}); | ||
app.cmd('install', [ | ||
shell.routes.confirm('Do you confirm?'), | ||
my_app.routes.download, | ||
my_app.routes.configure | ||
]); | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
}); | ||
app.cmd('install', [ | ||
shell.routes.confirm('Do you confirm?'), | ||
my_app.routes.download, | ||
my_app.routes.configure | ||
]); | ||
``` | ||
@@ -372,13 +423,21 @@ | ||
```javascript | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
}); | ||
app.cmd('restart', [ | ||
my_app.routes.stop, | ||
shell.routes.timeout(1000), | ||
my_app.routes.start | ||
]); | ||
var app = new shell(); | ||
app.configure(function() { | ||
app.use(shell.router({ | ||
shell: app | ||
})); | ||
}); | ||
app.cmd('restart', [ | ||
my_app.routes.stop, | ||
shell.routes.timeout(1000), | ||
my_app.routes.start | ||
]); | ||
``` | ||
Contributors | ||
------------ | ||
* David Worms : <https://github.com/wdavidw> | ||
* Tony: <https://github.com/Zearin> | ||
* Russ Frank : <https://github.com/russfrank> |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
72525
3
46
265
433
4
- Removedcoffeekup@latest
- Removedcoffeekup@0.3.1(transitive)