skypager-repl
Version:
an awesome repl
431 lines (325 loc) • 11.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.banner = exports.prompt = exports.help = undefined;
var _extends2 = require('babel-runtime/helpers/extends');
var _extends3 = _interopRequireDefault(_extends2);
var _assign = require('babel-runtime/core-js/object/assign');
var _assign2 = _interopRequireDefault(_assign);
var _defineProperty = require('babel-runtime/core-js/object/define-property');
var _defineProperty2 = _interopRequireDefault(_defineProperty);
var _keys = require('babel-runtime/core-js/object/keys');
var _keys2 = _interopRequireDefault(_keys);
exports.create = create;
exports.server = server;
exports.connect = connect;
require('colors');
var _repl = require('repl');
var _path = require('path');
var _isFunction = require('lodash/isFunction');
var _isFunction2 = _interopRequireDefault(_isFunction);
var _defaults = require('lodash/defaults');
var _defaults2 = _interopRequireDefault(_defaults);
var _camelCase = require('lodash/camelCase');
var _camelCase2 = _interopRequireDefault(_camelCase);
var _castArray = require('lodash/castArray');
var _castArray2 = _interopRequireDefault(_castArray);
var _mapKeys = require('lodash/mapKeys');
var _mapKeys2 = _interopRequireDefault(_mapKeys);
var _omit = require('lodash/omit');
var _omit2 = _interopRequireDefault(_omit);
var _fs = require('fs');
var _promise = require('./extensions/promise');
var _promise2 = _interopRequireDefault(_promise);
var _history = require('./extensions/history');
var _history2 = _interopRequireDefault(_history);
var _reloading = require('./extensions/reloading');
var _reloading2 = _interopRequireDefault(_reloading);
var _cli = require('./cli');
var _net = require('net');
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var keys = _keys2.default,
defineProperty = _defineProperty2.default,
assign = _assign2.default;
var argv = require('minimist')(process.argv.slice(2));
argv = assign(argv, (0, _mapKeys2.default)((0, _omit2.default)(argv, '_'), function (v, k) {
return (0, _camelCase2.default)(k);
}));
/**
* Creates the instance of the REPL server
*
* @param {Object} options - options for the REPL. Same as node's REPL with some additional options
* @param {Object} context - context to start the repl with
* @param {Function} ready - a function to run when the repl is ready
*
* The following hooks can be passed in as options
*
* before
* beforeHook
* after
* afterHook
* beforeInitialize
* beforeInitializeHook
* afterInitialize
* afterInitializeHook
* onReset
*
* Additionally, a `customize` property can be passed which references a script which is can be required
* and if it exports any of the above as functions, those values will be used. In addition, the customize script
* can export properties such as `prompt` which are used in place of the REPL options.
*/
function create() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var _this = this;
var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var ready = arguments[2];
if (argv.es6 !== false) {
require('babel-register');
}
var customize = options.customize || process.env.SKYPAGER_REPL_CUSTOMIZER || (0, _fs.existsSync)((0, _path.join)(process.cwd(), '.skypager-repl.js')) && '.skypager-repl.js';
if (typeof customize === 'string') {
customize = require((0, _path.resolve)(process.cwd(), customize));
}
if ((0, _keys2.default)(customize).length === 1 && (0, _isFunction2.default)(customize.default)) {
customize = customize.default;
}
options = (0, _defaults2.default)(options, {
terminal: true,
colors: true,
ignoreUndefined: true,
prompt: customize.prompt || prompt,
banner: customize.banner || banner,
help: customize.help || help,
input: process.stdin,
output: process.stdout,
useGlobal: false,
buildContext: customize.buildContext,
before: customize.before,
after: customize.after || (0, _isFunction2.default)(customize) && customize,
afterInitialize: customize.afterInitialize,
beforeInitialize: customize.beforeInitialize,
onReset: customize.onReset,
evalFn: customize.evalFn,
promisify: argv.promisify,
commands: {}
});
if ((0, _isFunction2.default)(options.prompt)) {
options.prompt = options.prompt(_cli.cli);
}
if ((0, _isFunction2.default)(options.beforeHook)) {
options.beforeHook(_cli.cli, options, context);
}
if (options.before) {
var before = options.before;
if (typeof before === 'string') {
before = require((0, _path.resolve)(process.cwd(), before));
before = before.default ? before.default : before;
}
if ((0, _isFunction2.default)(before)) {
before(_cli.cli, options, context);
}
}
var server = (0, _repl.start)(options);
Object.defineProperty(server, '_sockets', {
enumerable: false,
value: []
});
Object.defineProperty(server, 'cli', {
enumerable: false,
get: function get() {
return _cli.cli;
}
});
server.commands['cls'] = {
help: 'Clears the screen',
// eslint-disable-next-line
action: function action() {
process.stdout.write('\x1bc');
this.displayPrompt();
}
};
if (!(0, _isFunction2.default)(ready)) {
ready = function ready() {};
}
if (options.historyFile) {
var historyFilePath = (0, _path.resolve)(options.historyFile);
server = (0, _history2.default)(server, historyFilePath);
}
(0, _reloading2.default)(server, options);
var initializeContext = function initializeContext() {
server.context.SKYPAGER_REPL = server;
if ((0, _isFunction2.default)(options.buildContext)) {
try {
context = options.buildContext.call(_this, context, options, _this) || context;
} catch (e) {}
}
keys(context).forEach(function (key) {
defineProperty(server.context, key, {
configurable: true,
enumerable: true,
// eslint-disable-next-line
get: function get() {
return context[key];
}
});
});
if ((0, _isFunction2.default)(options.after)) {
options.after(server, options, server.context);
}
if ((0, _isFunction2.default)(options.afterHook)) {
options.afterHook(server, options, server.context);
}
};
server.on('reset', function () {
if ((0, _isFunction2.default)(options.onReset)) {
options.onReset(server, options, server.context);
}
initializeContext();
});
try {
if (options.clear !== false) {
_cli.cli.clear();
}
if (options.banner) {
_cli.cli.print((0, _isFunction2.default)(options.banner) ? options.banner(_cli.cli, options, server) : options.banner, 2, 2);
}
if (options.help) {
_cli.cli.print((0, _isFunction2.default)(options.help) ? options.help(_cli.cli, options, server) : options.help);
}
if (options.promisify !== false) {
if ((0, _isFunction2.default)(options.evalFn)) {
(0, _promise2.default)(server, options.evalFn.bind(server));
} else {
(0, _promise2.default)(server);
}
}
// can be hardcoded by the consumer of the repl library
if ((0, _isFunction2.default)(options.beforeInitializeHook)) {
options.beforeInitializeHook(server, options, context);
}
// allow local project customization
if ((0, _isFunction2.default)(options.beforeInitialize)) {
options.beforeInitialize(server, options, context);
}
initializeContext();
// can be hardcoded by the consumer of the repl library
if ((0, _isFunction2.default)(options.afterInitializeHook)) {
options.afterInitializeHook(server, options, server.context);
}
// allow local project customization
if ((0, _isFunction2.default)(options.afterInitialize)) {
options.afterInitialize(server, options, server.context);
}
} catch (error) {
ready(error);
return;
}
ready(null, server);
if (options.delayPrompt !== false) {
setTimeout(function () {
server.displayPrompt();
}, 300);
}
return server;
}
exports.default = create;
var help = exports.help = function help(cli) {
cli.defineTable('commands', {
head: ['Command', 'Description'],
colWidths: [30, 60]
});
cli.print('Commands'.bold.underline, 2, 2, 2);
cli.displayTable('commands', [['cls', 'Clear the console'], ['reload', 'Clear the require cache and reset the repl context']]);
cli.print("\n");
};
var prompt = exports.prompt = function prompt(cli) {
return [cli.colors.blue('Sky'), cli.colors.cyan('pag'), cli.colors.green('er'), cli.colors.dim(':'), cli.colors.bold.white('REPL'), cli.colors.dim(':> ')].join('');
};
var banner = exports.banner = function banner(cli) {
return cli.figlet.textSync('Skypager', {
font: cli.random.font
}).split("\n").map(function (line) {
return cli.random.color(line);
}).join("\n");
};
function server() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
var context = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
var fn = arguments[2];
var instance = (0, _net.createServer)(function (socket) {
var replServer = create((0, _extends3.default)({
delayPrompt: false,
input: socket,
output: socket,
clear: true,
help: function help(cli) {
cli.print('Skypager Console is running in server mode', 0, 2, 2);
}
}, options), context, fn);
replServer._sockets.push(socket);
replServer.on('exit', function () {
return socket.end();
});
Object.defineProperty(replServer, 'server', {
enumerable: false,
configurable: true,
get: function get() {
return instance;
}
});
Object.defineProperty(instance, 'repl', {
enumerable: false,
configurable: true,
get: function get() {
return replServer;
}
});
instance.stop = function () {
replServer._sockets.forEach(function (sock) {
return sock.end();
});
};
});
instance._listen = instance.listen;
instance.listen = function () {
var socketOrPort = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : argv._[0];
var deleteSocketOnStart = argv.deleteSocket || argv['delete-socket'];
socketOrPort = socketOrPort || '.repl.sock';
if (socketOrPort.match(/\.sock$/) && (0, _fs.existsSync)(socketOrPort)) {
(0, _fs.unlinkSync)(socketOrPort);
}
for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
args[_key - 1] = arguments[_key];
}
var result = instance._listen.apply(instance, [socketOrPort].concat(args));
return result;
};
return instance;
}
function connect() {
var sock = _net.connect.apply(undefined, arguments);
process.stdin.pipe(sock);
sock.pipe(process.stdout);
sock.on('connect', function () {
process.stdin.resume();
process.stdin.setRawMode(true);
});
sock.on('close', function done() {
sock.removeListener('close', done);
process.exit(0);
});
process.stdin.on('end', function () {
process.stdin.setRawMode('false');
process.stdin.pause();
sock.destroy();
console.log();
});
process.stdin.on('data', function (b) {
if (b.length === 1 && b[0] === 4) {
process.stdin.emit('end');
}
});
return sock;
}
//# sourceMappingURL=repl.js.map