Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
mafintosh committed Nov 10, 2012
0 parents commit 0789488
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 0 deletions.
45 changes: 45 additions & 0 deletions README.md
@@ -0,0 +1,45 @@
# spies

Spy on a running node program by having a man on the inside

npm install spies

The first thing you need is to setup a spy inside your program

``` js
var spies = require('spies');

spies(9999, function(spy) {
spy.on('echo', function(value) {
spy.log(value);
});
spy.on('load-avg', function() {
spy.log(require('os').loadavg());
});
});
```

Afterwards you can use `netcat` to contact and debrief your spy

nc localhost 9999

This starts a `repl` where you can type in commands

help
$ : help
: watch
: echo
: load-avg

`help` and `watch` are build in commands than print the help and runs the same command every 1 second.
You invoke a command simply typing it and pressing `enter` and the result will be pretty printed below.

load-avg
$ : 0.30126953125
: 0.3203125
: 0.33642578125

To pass arguments to the commands simply seperate them them by a `space`

echo hello
$ : hello
10 changes: 10 additions & 0 deletions example.js
@@ -0,0 +1,10 @@
var spies = require('spies');

spies(9999, function(spy) {
spy.on('echo', function(value) {
spy.log(value);
});
spy.on('load-avg', function() {
spy.log(require('os').loadavg());
});
});
42 changes: 42 additions & 0 deletions format.js
@@ -0,0 +1,42 @@
var format = function(obj) {
var res = [];

var visit = function(prev, val) {
if (val === undefined || val === null) return res.push([prev, '(nil)']);
if (typeof val !== 'object') return res.push([prev, ''+val]);
if (Array.isArray(val) && !val.length) return res.push([prev, '(empty)']);

if (Array.isArray(val)) {
val.forEach(function(item) {
visit(prev, item);
});
return;
}

Object.keys(val).forEach(function(key) {
visit(prev ? prev+'.'+key : key, val[key]);
});
};

if (typeof obj !== 'object' || !obj || (Array.isArray(obj) && typeof obj[0] !== 'object')) {
obj = {'$':obj};
}

visit('', obj);

var prev = [];
var max = res.reduce(function(sofar, line) {
return line[0].length > sofar.length ? line[0] : sofar;
}, '').replace(/./g, ' ')+' \x1B[90m:\x1B[39m ';

return res.map(function(line) {
var prefix = line[0].split('.').map(function(l, i) {
return l === prev[i] ? l.replace(/./g, ' ') : l;
}).join('.').replace(/ \. /g, ' ');
var suffix = max.slice(-(max.length-line[0].length));
prev = line[0].split('.');
return '\x1B[36m'+prefix+'\x1B[39m'+suffix+line[1]+'\n';
}).join('');
};

module.exports = format;
87 changes: 87 additions & 0 deletions index.js
@@ -0,0 +1,87 @@
var net = require('net');
var format = require('./format');
var Stream = require('stream');

var CLEAR = new Buffer('G1tIG1sySg==', 'base64');

var noop = function() {};

var Shell = function() {
this.buffer = '';
this.once('pipe', function(stream) {
stream.on('error', noop); // ignore errors yo
stream.setEncoding('utf-8');
});

this.readable = true;
this.writable = true;
};

Shell.prototype.__proto__ = Stream.prototype;

Shell.prototype.write = function(data) {
var self = this;
var messages = (this.buffer+data).split('\n');
this.buffer = messages.pop();
messages.forEach(function(message) {
if (!message.trim()) return self.emit('help');
if (!self.readable) return;
message = message.split(/\s+/g).map(function(item) {
if (/^\d+$/.test(item)) return parseInt(item, 10);
return item;
});
self.emit.apply(self, message);
});
};

Shell.prototype.end = function() {
this.finish('end');
};

Shell.prototype.destroy = function() {
this.finish('close');
};

Shell.prototype.finish = function(name) {
if (!this.readable) return;
this.readable = false;
this.writable = false;
this.emit(name);
};

Shell.prototype.log = function(value) {
this.emit('data', format(value));
};

module.exports = function(port, onshell) {
net.createServer(function(socket) {
var sh = new Shell();

socket.pipe(sh).pipe(socket);

var cmds = [];

sh.on('newListener', function(name) {
cmds.push(name);
});
sh.on('help', function() {
sh.log(cmds);
});
sh.on('watch', function() {
var args = arguments;
var watch = setInterval(function() {
sh.emit('data', CLEAR);
sh.emit.apply(sh, args);
}, 1000);

sh.once('close', function() {
clearInterval(watch);
});
});

onshell(sh);
}).listen(port);
};
module.exports.sh = function() {
return new Shell();
};
9 changes: 9 additions & 0 deletions package.json
@@ -0,0 +1,9 @@
{
"name":"spies",
"version":"0.1.0",
"dependencies": {},
"repository": "git://github.com/mafintosh/spies",
"description":"spy on a running program",
"keywords": ["repl","shell","nc"],
"author": "Mathias Buus Madsen <mathiasbuus@gmail.com>"
}

0 comments on commit 0789488

Please sign in to comment.