Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@seneca/repl

Package Overview
Dependencies
Maintainers
3
Versions
30
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@seneca/repl - npm Package Compare versions

Comparing version 2.0.0 to 2.1.0

4

bin/seneca-repl-exec.js

@@ -10,3 +10,3 @@ #!/usr/bin/env node

const vorpal = Vorpal()
const vorpal = Vorpal({history:{ignore_mode:true}})

@@ -32,2 +32,3 @@ const connection = {}

var cmd = args+'\n'
connection.sock.write(cmd)

@@ -51,2 +52,3 @@ callback()

else {
vorpal.history('seneca~'+host+'~'+port)
vorpal.exec('repl')

@@ -53,0 +55,0 @@ }

{
"name": "@seneca/repl",
"description": "Provides a client and server REPL for Seneca microservice systems.",
"version": "2.0.0",
"version": "2.1.0",
"main": "repl.js",

@@ -20,3 +20,3 @@ "license": "MIT",

"scripts": {
"test": "lab -P test -v -t 70",
"test": "lab -P test -v -t 75 -r console -o stdout -r html -o test/coverage.html",
"coveralls": "lab -s -P test -r lcov | coveralls",

@@ -40,8 +40,9 @@ "coverage": "lab -v -P test -t 70 -r html > coverage.html",

"dependencies": {
"@seneca/vorpal": "^2.0.2"
"@hapi/hoek": "^9.0.0",
"@seneca/vorpal": "^2.1.0"
},
"devDependencies": {
"@hapi/code": "^7.0.0",
"@hapi/code": "^8.0.1",
"@hapi/joi": "^15.1.1",
"@hapi/lab": "^22.0.2",
"@hapi/lab": "^21.0.0",
"acorn": "^7.1.0",

@@ -48,0 +49,0 @@ "async": "^3.1.0",

@@ -107,10 +107,11 @@ ![Seneca](http://senecajs.org/files/assets/seneca-logo.png)

* `list`: list local patterns
* `list <pin>`: list local patterns, optionally narrowed by `pin`
* `tree`: show local patterns in tree format
* `stats`: print local statistics
* `stats/full`: print full local statistics
* `stats full`: print full local statistics
* `exit` or `quit`: exit the repl session
* `last`: run last command again
* `history`: print command history
* `set <path> <value>`: set a seneca option, e.g: `set debug.deprecation true`. Use `seneca.options()` to get options
* `set <path> <value>`: set a seneca option, e.g: `set debug.deprecation true`
* `get <path>`: get a seneca option
* `alias <name> <cmd>`: define a new alias

@@ -120,7 +121,9 @@ * `trace`: toggle IN/OUT tracing of submitted messages

* `log match <literal>`: when logging is enabled, only print lines matching the provided literal string
* `depth <number>`: set depth of Util.inspect printing
## Contributing
The [Senecajs org][] encourage open participation. If you feel you can help in any way, be it with
documentation, examples, extra testing, or new features please get in touch.
The [Senecajs org][] encourages open participation. If you feel you
can help in any way, be it with documentation, examples, extra
testing, or new features please get in touch.

@@ -136,3 +139,3 @@ ## Test

## License
Copyright (c) 2015-2017, Richard Rodger and other contributors.
Copyright (c) 2015-2020, Richard Rodger and other contributors.
Licensed under [MIT][].

@@ -139,0 +142,0 @@

@@ -0,12 +1,14 @@

/* Copyright © 2015-2020 Richard Rodger and other contributors, MIT License. */
'use strict'
// TODO: implement cmd for seneca.make('core/fixture').load$('qazwsx',(e,x)=>console.log(x.data$())) to show ent data
// NOTE: vorpal is not used server-side to keep things lean
// Load modules
var Net = require('net')
var Repl = require('repl')
var Util = require('util')
var Vm = require('vm')
const Net = require('net')
const Repl = require('repl')
const Util = require('util')
const Vm = require('vm')
const Hoek = require('@hapi/hoek')
module.exports = repl

@@ -18,4 +20,6 @@ module.exports.defaults = {

alias: {
list: 'seneca.list()',
stats: 'seneca.stats()',
'stats full': 'seneca.stats({summary:false})',
// DEPRECATED
'stats/full': 'seneca.stats({summary:false})',

@@ -25,5 +29,26 @@

tree: 'seneca.root.private$.actrouter'
},
inspect: {
},
cmds: {
// custom cmds
}
}
const intern = repl.intern = make_intern()
const default_cmds = {
get: intern.cmd_get,
depth: intern.cmd_depth,
plain: intern.cmd_plain,
quit: intern.cmd_quit,
list: intern.cmd_list,
history: intern.cmd_history,
log: intern.cmd_log,
set: intern.cmd_set,
alias: intern.cmd_alias,
trace: intern.cmd_trace,
}
function repl(options) {

@@ -33,4 +58,7 @@ var seneca = this

var cmd_map = Object.assign({},default_cmds,options.cmds)
seneca.init(function(reply) {
var server = start_repl(seneca, options)
var server = intern.start_repl(seneca, options, cmd_map)

@@ -65,223 +93,330 @@ server.on('listening', function() {

function start_repl(seneca, options) {
var alias = options.alias
function make_intern() {
return {
start_repl: function (seneca, options, cmd_map) {
var alias = options.alias
var server = Net.createServer(function(socket) {
socket.on('error', function(err) {
sd.log.debug('repl-socket', err)
})
var server = Net.createServer(function(socket) {
socket.on('error', function(err) {
sd.log.debug('repl-socket', err)
})
var r = Repl.start({
prompt: 'seneca ' + seneca.version + ' ' + seneca.id + '> ',
input: socket,
output: socket,
terminal: false,
useGlobal: false,
eval: evaluate
})
var sd = seneca.root.delegate({ repl$: true, fatal$: false })
r.on('exit', function() {
socket.end()
})
var r = Repl.start({
prompt: 'seneca ' + seneca.version + ' ' + seneca.id + '> ',
input: socket,
output: socket,
terminal: false,
useGlobal: false,
eval: evaluate
})
r.on('exit', function() {
socket.end()
})
var act_trace = false
var act_index_map = {}
var act_index = 1000000
function fmt_index(i) {
return ('' + i).substring(1)
}
r.on('error', function(err) {
sd.log.debug('repl', err)
})
var sd = seneca.root.delegate({ repl$: true, fatal$: false })
Object.assign(r.context, {
// NOTE: don't trigger funnies with a .inspect property
inspekt: intern
.make_inspect(r.context,{...options.inspect, depth:options.depth}),
socket: socket,
s: sd,
seneca: sd,
plain: false,
history: [],
log_capture: false,
log_match: null,
alias: alias,
act_trace: false,
act_index_map: {},
act_index: 1000000,
})
r.on('error', function(err) {
sd.log.debug('repl', err)
})
sd.on_act_in = intern.make_on_act_in(r.context)
sd.on_act_out = intern.make_on_act_out(r.context)
sd.on_act_err = intern.make_on_act_err(r.context)
sd.on('log', intern.make_log_handler(r.context))
sd.on_act_in = function on_act_in(actdef, args, meta) {
if(!act_trace) return;
var actid = (meta || args.meta$ || {}).id
socket.write(
'IN ' +
fmt_index(act_index) +
': ' +
Util.inspect(sd.util.clean(args)) +
' # ' +
actid +
' ' +
actdef.pattern +
' ' +
actdef.id +
' ' +
actdef.action +
' ' +
(actdef.callpoint ? actdef.callpoint : '') +
'\n'
)
act_index_map[actid] = act_index
act_index++
}
function evaluate(cmdtext, context, filename, respond) {
const inspect = context.inspekt
var cmd_history = context.history
cmdtext = cmdtext.trim()
sd.on_act_out = function on_act_out(actdef, out, meta) {
if(!act_trace) return;
var actid = (meta || out.meta$ || {}).id
if ('last' === cmdtext && 0 < cmd_history.length) {
cmdtext = cmd_history[cmd_history.length - 1]
} else {
cmd_history.push(cmdtext)
}
out = out && out.entity$
? out
: Util.inspect(sd.util.clean(out), { depth: options.depth })
if (alias[cmdtext]) {
cmdtext = alias[cmdtext]
}
var cur_index = act_index_map[actid]
socket.write('OUT ' + fmt_index(cur_index) + ': ' + out + '\n')
}
var m = cmdtext.match(/^(\S+)/)
var cmd = m && m[1]
sd.on_act_err = function on_act_err(actdef, err, meta) {
if(!act_trace) return;
var actid = (meta || err.meta$ || {}).id
var argtext = 'string' === typeof(cmd) ? cmdtext.substring(cmd.length) : ''
// NOTE: alias can also apply just to command
if (alias[cmd]) {
cmd = alias[cmd]
}
var cmd_func = cmd_map[cmd]
// console.log('CMD', cmd, !!cmd_func)
if(cmd_func) {
return cmd_func(cmd, argtext, context, options, respond)
}
if (!execute_action(cmdtext)) {
execute_script(cmdtext)
}
if (actid) {
var cur_index = act_index_map[actid]
socket.write('ERR ' + fmt_index(cur_index) + ': ' + err.message + '\n')
}
}
function execute_action(cmdtext) {
try {
var args = seneca.util.Jsonic(cmdtext)
context.s.act(args, function(err, out) {
if(out && !r.context.act_trace) {
out = out && out.entity$
? out
: context.inspekt(sd.util.clean(out))
socket.write(out + '\n')
}
else if(err) {
socket.write(context.inspekt(err) + '\n')
}
})
return true
} catch (e) {
// Not jsonic format, so try to execute as a script
// TODO: check actual jsonic parse error so we can give better error
// message if not
return false
}
}
var log_capture = false
var log_match = null
sd.on('log',function(data) {
if(log_capture) {
var out = sd.__build_test_log__$$ ?
sd.__build_test_log__$$(this,'test',data) :
Util.inspect(data).replace(/\n/g, ' ')
function execute_script(cmdtext) {
try {
var script = Vm.createScript(cmdtext, {
filename: filename,
displayErrors: false
})
var result = script.runInContext(context, { displayErrors: false })
if(null == log_match || -1 < out.indexOf(log_match)) {
socket.write('LOG: '+out)
result = result === seneca ? null : result
respond(null, result)
} catch (e) {
return respond(e.message)
}
}
}
}
})
}).listen(options.port, options.host)
r.context.s = r.context.seneca = sd
return server
},
parse_option: function(optpath, val) {
optpath += '.'
var cmd_history = []
var part = /([^.]+)\.+/g
var m
var out = {}
var cur = out
var po = out
var pn
function evaluate(cmdtext, context, filename, callback) {
var m = cmdtext.match(/^(\S+)/)
var cmd = m && m[1]
while (null != (m = part.exec(optpath))) {
cur[m[1]] = {}
po = cur
pn = m[1]
cur = cur[m[1]]
}
po[pn] = val
return out
},
if ('last' === cmd) {
cmd = cmd_history[cmd_history.length - 1]
} else {
cmd_history.push(cmd)
make_inspect: function(context, inspect_options) {
return (x) => {
if(context.plain) {
x = JSON.parse(JSON.stringify(x))
}
return Util.inspect(x, inspect_options)
}
},
if ('quit' === cmd || 'exit' === cmd) {
socket.end()
} else if ('trace' === cmd) {
act_trace = !act_trace
return callback()
} else if ('log' === cmd) {
log_capture = !log_capture
fmt_index: function (i) {
return ('' + i).substring(1)
},
if(!log_capture) {
log_match = null
make_log_handler: function(context) {
return function log_handler(data) {
if(context.log_capture) {
var seneca = context.seneca
var out =
seneca.__build_test_log__$$ ?
seneca.__build_test_log__$$(seneca,'test',data) :
context.inspekt(data).replace(/\n/g, ' ')
if(null == context.log_match ||
-1 < out.indexOf(context.log_match)) {
context.socket.write('LOG: '+out)
}
}
else if(m = cmdtext.match(/^log\s+match\s+(.*)/)) {
log_match = m[1]
}
return callback()
} else if ('history' === cmd) {
return callback(cmd_history.join('\n'))
} else if ('set' === cmd) {
m = cmdtext.match(/^(\S+)\s+(\S+)\s+(\S+)/)
}
},
if (m) {
var setopt = parse_option(m[2], seneca.util.Jsonic('$:' + m[3]).$)
context.s.options(setopt)
make_on_act_in: function(context) {
return function on_act_in(actdef, args, meta) {
if(!context.act_trace) return;
var actid = (meta || args.meta$ || {}).id
context.socket.write(
'IN ' +
intern.fmt_index(context.act_index) +
': ' +
context.inspekt(context.seneca.util.clean(args)) +
' # ' +
actid +
' ' +
actdef.pattern +
' ' +
actdef.id +
' ' +
actdef.action +
' ' +
(actdef.callpoint ? actdef.callpoint : '') +
'\n'
)
context.act_index_map[actid] = context.act_index
context.act_index++
}
},
if (setopt.repl) {
options = context.s.util.deepextend(options, setopt.repl)
}
make_on_act_out: function(context) {
return function on_act_out(actdef, out, meta) {
if(!context.act_trace) return;
var actid = (meta || out.meta$ || {}).id
return callback()
} else {
return callback('ERROR: expected set <path> <value>')
}
} else if ('alias' === cmd) {
m = cmdtext.match(/^(\S+)\s+(\S+)\s+(.+)[\r\n]+$/)
out = out && out.entity$
? out
: context.inspekt(context.seneca.util.clean(out))
var cur_index = context.act_index_map[actid]
context.socket.write('OUT ' + intern.fmt_index(cur_index) + ': ' + out + '\n')
}
},
make_on_act_err: function(context) {
return function on_act_err(actdef, err, meta) {
if(!context.act_trace) return;
var actid = (meta || err.meta$ || {}).id
if (m) {
alias[m[2]] = m[3]
return callback()
} else {
return callback('ERROR: expected alias <name> <command>')
if (actid) {
var cur_index = context.act_index_map[actid]
context.socket.write('ERR ' +
intern.fmt_index(cur_index) + ': ' +
err.message + '\n')
}
} else if (alias[cmd]) {
cmd = alias[cmd]
}
},
cmd_get: function(cmd, argtext, context, options, respond) {
var option_path = argtext.trim()
var options = context.seneca.options()
var out = Hoek.reach(options,option_path)
return respond(null,out)
},
if (!execute_action(cmd)) {
execute_script(cmd)
cmd_depth: function(cmd, argtext, context, options, respond) {
var depth = parseInt(argtext,10)
depth = isNaN(depth) ? null : depth
context.inspekt =
intern.make_inspect(context, {...options.inspect, depth:depth})
return respond(null,'Inspection depth set to '+depth)
},
cmd_plain: function(cmd, argtext, context, options, respond) {
context.plain = !context.plain
return respond()
},
cmd_quit: function(cmd, argtext, context, options, respond) {
context.socket.end()
},
cmd_list: function(cmd, argtext, context, options, respond) {
var narrow = context.seneca.util.Jsonic(argtext)
respond(null, context.seneca.list(narrow))
},
cmd_history: function(cmd, argtext, context, options, respond) {
return respond(null,context.history.join('\n'))
},
cmd_log: function(cmd, argtext, context, options, respond) {
context.log_capture = !context.log_capture
var m = null
if(!context.log_capture) {
context.log_match = null
}
function execute_action(cmd) {
try {
var args = seneca.util.Jsonic(cmd)
context.s.act(args, function(err, out) {
if(out && !act_trace) {
out = out && out.entity$
? out
: Util.inspect(sd.util.clean(out), { depth: options.depth })
socket.write(out + '\n')
}
else if(err) {
socket.write(Util.inspect(err) + '\n')
}
})
return true
} catch (e) {
return false
}
if(m = argtext.match(/^\s*match\s+(.*)/)) {
context.log_capture = true // using match always turns logging on
context.log_match = m[1]
}
return respond()
},
function execute_script(cmd) {
try {
var script = Vm.createScript(cmd, {
filename: filename,
displayErrors: false
})
var result = script.runInContext(context, { displayErrors: false })
cmd_set: function(cmd, argtext, context, options, respond) {
var m = argtext.match(/^\s*(\S+)\s+(\S+)/)
result = result === seneca ? null : result
callback(null, result)
} catch (e) {
return callback(e.message)
if (m) {
var setopt =
intern.parse_option(m[1], context.seneca.util.Jsonic('$:' + m[2]).$)
context.seneca.options(setopt)
if (setopt.repl) {
options = context.seneca.util.deepextend(options, setopt.repl)
}
return respond()
} else {
return respond('ERROR: expected set <path> <value>')
}
}
}).listen(options.port, options.host)
},
return server
}
cmd_alias: function(cmd, argtext, context, options, respond) {
var m = argtext.match(/^\s*(\S+)\s+(.+)[\r\n]?/)
if (m) {
context.alias[m[1]] = m[2]
return respond()
} else {
return respond('ERROR: expected alias <name> <command>')
}
},
function parse_option(optpath, val) {
optpath += '.'
var part = /([^.]+)\.+/g
var m
var out = {}
var cur = out
var po = out
var pn
while (null != (m = part.exec(optpath))) {
cur[m[1]] = {}
po = cur
pn = m[1]
cur = cur[m[1]]
cmd_trace: function(cmd, argtext, context, options, respond) {
context.act_trace = !context.act_trace
return respond()
}
}
po[pn] = val
return out
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc