@seneca/repl
Advanced tools
Comparing version 6.2.3 to 7.0.0
@@ -16,3 +16,5 @@ #!/usr/bin/env node | ||
const state = { | ||
connection: {}, | ||
connection: { | ||
mode: 'cmd', | ||
}, | ||
} | ||
@@ -283,6 +285,10 @@ | ||
if (null == state.connection.readline) { | ||
Readline.emitKeypressEvents(process.stdin) | ||
state.connection.readline = Readline.createInterface({ | ||
input: process.stdin, | ||
output: process.stdout, | ||
// prompt: 'QQQ', | ||
completer: (linep) => { | ||
return [history.filter((n) => n.startsWith(linep)), linep] | ||
}, | ||
terminal: true, | ||
@@ -294,4 +300,79 @@ history, | ||
process.stdin.on('keypress', function (key, spec) { | ||
if ('g' == spec.name && spec.ctrl) { | ||
Readline.cursorTo(process.stdin, 0) | ||
Readline.clearLine(process.stdin, 1) | ||
state.connection.readline.setPrompt(state.connection.prompt) | ||
state.connection.readline.prompt() | ||
state.connection.found = '' | ||
state.connection.mode = 'cmd' | ||
state.connection.readline.resume() | ||
return | ||
} | ||
if ('search' === state.connection.mode) { | ||
let cc = key.charCodeAt(0) | ||
if (31 < cc || 8 === cc) { | ||
if (127 === cc || 8 === cc) { | ||
// state.connection.search = | ||
// state.connection.search.substring(0,state.connection.search.length-1) | ||
// state.connection.offset = 0 | ||
} else { | ||
state.connection.search += key | ||
} | ||
} else if ('r' == spec.name && spec.ctrl) { | ||
state.connection.offset++ | ||
} | ||
let search = state.connection.search | ||
Readline.cursorTo(process.stdin, 0, () => { | ||
Readline.clearLine(process.stdin, 1) | ||
const searchprompt = 'search: [' + search + '] ' | ||
// state.connection.readline.write(searchprompt) | ||
state.connection.found = '' | ||
if ('' != search) { | ||
let offset = state.connection.offset | ||
for (let i = 0; i < history.length; i++) { | ||
if (history[i].includes(search)) { | ||
if (0 === offset) { | ||
state.connection.readline.write(searchprompt + history[i]) | ||
state.connection.found = history[i] | ||
break | ||
} else { | ||
offset-- | ||
} | ||
} | ||
} | ||
} | ||
if ('' === state.connection.found) { | ||
state.connection.readline.write(searchprompt) | ||
} | ||
}) | ||
} else if ('r' == spec.name && spec.ctrl) { | ||
state.connection.readline.pause() | ||
state.connection.readline.setPrompt('search: [] ') | ||
state.connection.readline.prompt() | ||
state.connection.mode = 'search' | ||
state.connection.search = '' | ||
state.connection.offset = 0 | ||
} | ||
}) | ||
state.connection.readline | ||
.on('line', (line) => { | ||
if ('search' === state.connection.mode) { | ||
Readline.cursorTo(process.stdin, 0) | ||
Readline.clearLine(process.stdin, 1) | ||
state.connection.readline.setPrompt(state.connection.prompt) | ||
state.connection.readline.prompt() | ||
state.connection.mode = 'cmd' | ||
state.connection.readline.write(state.connection.found) | ||
state.connection.readline.resume() | ||
return | ||
} | ||
if (state.connection.closed) { | ||
@@ -316,3 +397,2 @@ return setImmediate(() => { | ||
state.connection.sock.write(line + '\n') | ||
// state.connection.readline.prompt() | ||
}) | ||
@@ -351,6 +431,5 @@ .on('error', (err) => { | ||
try { | ||
const makeProtocol = require(__dirname + | ||
'/protocol-' + | ||
protocol.replace(/[^a-z0-9-_]/g, '') + | ||
'.js') | ||
const makeProtocol = require( | ||
__dirname + '/protocol-' + protocol.replace(/[^a-z0-9-_]/g, '') + '.js', | ||
) | ||
return makeProtocol(spec) | ||
@@ -357,0 +436,0 @@ } catch (e) { |
@@ -92,3 +92,3 @@ "use strict"; | ||
const { context, respond } = spec; | ||
return respond(null, context.history.join('\n')); | ||
return respond(null, context.history); | ||
}; | ||
@@ -208,3 +208,3 @@ const LogCmd = (spec) => { | ||
let query = seneca.util.Jsonic(qstr); | ||
seneca.entity(canon).load$(query, function (err, out) { | ||
seneca.entity(canon).remove$(query, function (err, out) { | ||
if (err) { | ||
@@ -235,2 +235,50 @@ return respond('ERROR: entity remove$: ', err.message); | ||
}; | ||
const DelegateCmd = (spec) => { | ||
const { context, argstr, respond } = spec; | ||
let args = context.seneca.util.Jsonic(argstr) || []; | ||
args = Array.isArray(args) ? args : [args]; | ||
console.log('DA', args, context.delegate); | ||
let name = args[0]; | ||
let fromDelegateName = args[1]; | ||
let fixedargs = args[2]; | ||
let fixedmeta = args[3]; | ||
if ('string' != typeof fromDelegateName) { | ||
fromDelegateName = null; | ||
fixedargs = args[1]; | ||
fixedmeta = args[2]; | ||
} | ||
let delegate = context.delegate[name]; | ||
// Just name. | ||
if (null == fixedargs && null == fixedmeta) { | ||
if (null == delegate) { | ||
return respond('ERROR: delegate not found: ' + name); | ||
} | ||
} | ||
// Create new. | ||
else { | ||
if ({ root$: 1, repl$: 1 }[name]) { | ||
return respond('ERROR: delegate name reserved: ' + name); | ||
} | ||
else if (null != delegate) { | ||
return respond('ERROR: delegate already exists: ' + name); | ||
} | ||
else if (null == name || '' == name) { | ||
context.s = context.seneca = context.delegate.repl$; | ||
} | ||
else { | ||
let fromDelegate = context.seneca; | ||
if (null != fromDelegateName) { | ||
fromDelegate = context.delegate[fromDelegateName]; | ||
if (null == fromDelegate) { | ||
return respond('ERROR: unknown delegate: ' + fromDelegateName); | ||
} | ||
} | ||
delegate = fromDelegate.delegate(fixedargs, fixedmeta); | ||
delegate.did = delegate.did + '~' + name; | ||
context.delegate[name] = delegate; | ||
} | ||
} | ||
context.s = context.seneca = delegate; | ||
respond(null, delegate); | ||
}; | ||
const Cmds = { | ||
@@ -251,2 +299,3 @@ HelloCmd, | ||
HelpCmd, | ||
DelegateCmd, | ||
List$Cmd, | ||
@@ -253,0 +302,0 @@ Load$Cmd, |
233
dist/repl.js
@@ -100,2 +100,3 @@ "use strict"; | ||
let replSeneca = seneca.root.delegate({ repl$: true, fatal$: false }); | ||
replSeneca.did = replSeneca.did + '~repl$'; | ||
replMap[replID] = replInst = new ReplInstance({ | ||
@@ -323,2 +324,6 @@ id: replID, | ||
cmdMap: this.cmdMap, | ||
delegate: { | ||
repl$: seneca, | ||
root$: seneca.root, | ||
}, | ||
}); | ||
@@ -346,125 +351,129 @@ seneca.on_act_in = intern.make_on_act_in(repl.context); | ||
}; | ||
let cmd_history = context.history; | ||
cmdtext = cmdtext.trim(); | ||
if ('last' === cmdtext && 0 < cmd_history.length) { | ||
cmdtext = cmd_history[cmd_history.length - 1]; | ||
} | ||
else { | ||
cmd_history.push(cmdtext); | ||
} | ||
// console.log('AAA', cmdtext) | ||
if (alias[cmdtext]) { | ||
cmdtext = alias[cmdtext]; | ||
} | ||
let m = cmdtext.match(/^(\S+)/); | ||
let cmd = m && m[1]; | ||
let argstr = 'string' === typeof cmd ? cmdtext.substring(cmd.length) : ''; | ||
// NOTE: alias can also apply just to command | ||
if (alias[cmd]) { | ||
cmd = alias[cmd]; | ||
} | ||
let cmd_func = this.cmdMap[cmd]; | ||
if (cmd_func) { | ||
return cmd_func({ name: cmd, argstr, context, options, respond }); | ||
} | ||
if (!execute_action(cmdtext)) { | ||
// context.s.ready(() => { | ||
execute_script(cmdtext); | ||
//}) | ||
} | ||
function execute_action(cmdtext) { | ||
// console.log('EA', cmdtext) | ||
try { | ||
let msg = cmdtext; | ||
// TODO: use a different operator! will conflict with => !!! | ||
let m = msg.split(/\s*~>\s*/); | ||
if (2 === m.length) { | ||
msg = m[0]; | ||
try { | ||
let cmd_history = context.history; | ||
cmdtext = cmdtext.trim(); | ||
if ('last' === cmdtext && 0 < cmd_history.length) { | ||
cmdtext = cmd_history[cmd_history.length - 1]; | ||
} | ||
else { | ||
cmd_history.push(cmdtext); | ||
} | ||
// console.log('AAA', cmdtext) | ||
if (alias[cmdtext]) { | ||
cmdtext = alias[cmdtext]; | ||
} | ||
let m = cmdtext.match(/^(\S+)/); | ||
let cmd = m && m[1]; | ||
let argstr = 'string' === typeof cmd ? cmdtext.substring(cmd.length) : ''; | ||
// NOTE: alias can also apply just to command | ||
if (alias[cmd]) { | ||
cmd = alias[cmd]; | ||
} | ||
let cmd_func = this.cmdMap[cmd]; | ||
if (cmd_func) { | ||
return cmd_func({ name: cmd, argstr, context, options, respond }); | ||
} | ||
if (!execute_action(cmdtext)) { | ||
// context.s.ready(() => { | ||
execute_script(cmdtext); | ||
//}) | ||
} | ||
function execute_action(cmdtext) { | ||
// console.log('EA', cmdtext) | ||
try { | ||
let msg = cmdtext; | ||
let m = msg.split(/\s*~>\s*/); | ||
if (2 === m.length) { | ||
msg = m[0]; | ||
} | ||
let injected_msg = Inks(msg, context); | ||
let args = seneca.util.Jsonic(injected_msg); | ||
let notmsg = null == args || Array.isArray(args) || 'object' !== typeof args; | ||
// console.log('ARGS', args, notmsg) | ||
if (notmsg) { | ||
return false; | ||
} | ||
context.s.act(args, function (err, out) { | ||
context.err = err; | ||
context.out = out; | ||
// EXPERIMENTAL! msg ~> x saves msg result into x | ||
if (m[1]) { | ||
let ma = m[1].split(/\s*=\s*/); | ||
if (2 === ma.length) { | ||
context[ma[0]] = hoek_1.default.reach({ out: out, err: err }, ma[1]); | ||
} | ||
else { | ||
context[m[1]] = out; | ||
} | ||
} | ||
if (out && !repl.context.act_trace) { | ||
// out = | ||
// out && out.entity$ | ||
// ? out | ||
// : context.inspekt(seneca.util.clean(out)) | ||
respond(null, out); | ||
// output.write(out + '\n') | ||
// output.write(new Uint8Array([0])) | ||
} | ||
else if (err) { | ||
// output.write(context.inspekt(err) + '\n') | ||
respond(err); | ||
} | ||
}); | ||
return true; | ||
} | ||
let injected_msg = Inks(msg, context); | ||
let args = seneca.util.Jsonic(injected_msg); | ||
let notmsg = null == args || Array.isArray(args) || 'object' !== typeof args; | ||
// console.log('ARGS', args, notmsg) | ||
if (notmsg) { | ||
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; | ||
} | ||
context.s.act(args, function (err, out) { | ||
context.err = err; | ||
context.out = out; | ||
// EXPERIMENTAL! msg ~> x saves msg result into x | ||
if (m[1]) { | ||
let ma = m[1].split(/\s*=\s*/); | ||
if (2 === ma.length) { | ||
context[ma[0]] = hoek_1.default.reach({ out: out, err: err }, ma[1]); | ||
} | ||
function execute_script(cmdtext) { | ||
// console.log('EVAL SCRIPT', cmdtext) | ||
try { | ||
let script = node_vm_1.default.createScript(cmdtext, { | ||
filename: filename, | ||
displayErrors: false, | ||
}); | ||
let result = script.runInContext(context, { | ||
displayErrors: false, | ||
}); | ||
result = result === seneca ? null : result; | ||
return respond(null, result); | ||
} | ||
catch (e) { | ||
if ('SyntaxError' === e.name && e.message.startsWith('await')) { | ||
let wrapper = '(async () => { return (' + cmdtext + ') })()'; | ||
try { | ||
let script = node_vm_1.default.createScript(wrapper, { | ||
filename: filename, | ||
displayErrors: false, | ||
}); | ||
let out = script.runInContext(context, { | ||
displayErrors: false, | ||
}); | ||
out | ||
.then((result) => { | ||
result = result === seneca ? null : result; | ||
respond(null, result); | ||
}) | ||
.catch((e) => { | ||
return respond(e); | ||
}); | ||
} | ||
else { | ||
context[m[1]] = out; | ||
catch (e) { | ||
return respond(e); | ||
} | ||
} | ||
if (out && !repl.context.act_trace) { | ||
// out = | ||
// out && out.entity$ | ||
// ? out | ||
// : context.inspekt(seneca.util.clean(out)) | ||
respond(null, out); | ||
// output.write(out + '\n') | ||
// output.write(new Uint8Array([0])) | ||
} | ||
else if (err) { | ||
// output.write(context.inspekt(err) + '\n') | ||
respond(err); | ||
} | ||
}); | ||
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; | ||
} | ||
} | ||
function execute_script(cmdtext) { | ||
// console.log('EVAL SCRIPT', cmdtext) | ||
try { | ||
let script = node_vm_1.default.createScript(cmdtext, { | ||
filename: filename, | ||
displayErrors: false, | ||
}); | ||
let result = script.runInContext(context, { | ||
displayErrors: false, | ||
}); | ||
result = result === seneca ? null : result; | ||
return respond(null, result); | ||
} | ||
catch (e) { | ||
if ('SyntaxError' === e.name && e.message.startsWith('await')) { | ||
let wrapper = '(async () => { return (' + cmdtext + ') })()'; | ||
try { | ||
let script = node_vm_1.default.createScript(wrapper, { | ||
filename: filename, | ||
displayErrors: false, | ||
}); | ||
let out = script.runInContext(context, { | ||
displayErrors: false, | ||
}); | ||
out | ||
.then((result) => { | ||
result = result === seneca ? null : result; | ||
respond(null, result); | ||
}) | ||
.catch((e) => { | ||
return respond(e); | ||
}); | ||
} | ||
catch (e) { | ||
else { | ||
// return respond(e.message) | ||
return respond(e); | ||
} | ||
} | ||
else { | ||
// return respond(e.message) | ||
return respond(e); | ||
} | ||
} | ||
} | ||
catch (e) { | ||
return respond(e); | ||
} | ||
} | ||
@@ -471,0 +480,0 @@ async destroy() { |
{ | ||
"name": "@seneca/repl", | ||
"description": "Provides a client and server REPL for Seneca microservice systems.", | ||
"version": "6.2.3", | ||
"version": "7.0.0", | ||
"main": "dist/repl.js", | ||
@@ -43,17 +43,20 @@ "license": "MIT", | ||
"dependencies": { | ||
"@hapi/hoek": "^11.0.2", | ||
"@hapi/hoek": "^11.0.4", | ||
"inks": "^2.0.0" | ||
}, | ||
"devDependencies": { | ||
"@aws-sdk/client-lambda": "^3.382.0", | ||
"@seneca/entity-util": "^1.4.0", | ||
"@aws-sdk/client-lambda": "^3.476.0", | ||
"@seneca/entity-util": "^1.6.0", | ||
"@seneca/gateway-auth": "^1.0.0", | ||
"@seneca/maintain": "^0.1.0", | ||
"jest": "^29.6.2", | ||
"prettier": "^3.0.0", | ||
"seneca": "^3.32.0", | ||
"@seneca/owner": "^6.0.1", | ||
"@seneca/user": "^6.3.0", | ||
"jest": "^29.7.0", | ||
"prettier": "^3.1.1", | ||
"seneca": "^3.33.0", | ||
"seneca-doc": "^2.1.3", | ||
"seneca-entity": "^24.0.0", | ||
"seneca-mem-store": "^8.3.0", | ||
"seneca-promisify": "^3.6.0", | ||
"typescript": "5.1.6" | ||
"seneca-entity": "^25.1.1", | ||
"seneca-mem-store": "^8.4.0", | ||
"seneca-promisify": "^3.7.1", | ||
"typescript": "5.3.3" | ||
}, | ||
@@ -60,0 +63,0 @@ "files": [ |
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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
88346
1355
14
Updated@hapi/hoek@^11.0.4