Tweak repl to be a bit more useful (#19395)
* Tweak repl to be a bit more useful: - Start it earlier so it can be used to diagnose server boot bugs - Retain kbnServer, etc when repl is cleared (`.clear`) - Change default print depth so it doesn't bomb when printing kbnServer - Allow print depth to be changed as previous bullet may be annoying
This commit is contained in:
parent
9d08ab7f49
commit
ab6dfe7043
|
@ -1,19 +1,11 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`repl it allows print depth to be specified 1`] = `"{ [32m'0'[39m: { [32m'1'[39m: { [32m'2'[39m: [36m[Object][39m } }, whoops: [36m[Circular][39m }"`;
|
||||
|
||||
exports[`repl it colorizes raw values 1`] = `"{ meaning: [33m42[39m }"`;
|
||||
|
||||
exports[`repl it handles deep and recursive objects 1`] = `
|
||||
"{ [32m'0'[39m:
|
||||
{ [32m'1'[39m:
|
||||
{ [32m'2'[39m:
|
||||
{ [32m'3'[39m:
|
||||
{ [32m'4'[39m:
|
||||
{ [32m'5'[39m:
|
||||
{ [32m'6'[39m:
|
||||
{ [32m'7'[39m:
|
||||
{ [32m'8'[39m:
|
||||
{ [32m'9'[39m:
|
||||
{ [32m'10'[39m: { [32m'11'[39m: { [32m'12'[39m: { [32m'13'[39m: { [32m'14'[39m: { [32m'15'[39m: [36m[Object][39m } } } } } } } } } } } } } } },
|
||||
"{ [32m'0'[39m: { [32m'1'[39m: { [32m'2'[39m: { [32m'3'[39m: { [32m'4'[39m: { [32m'5'[39m: [36m[Object][39m } } } } },
|
||||
whoops: [36m[Circular][39m }"
|
||||
`;
|
||||
|
||||
|
@ -53,17 +45,7 @@ Array [
|
|||
Array [
|
||||
"Promise Rejected:
|
||||
",
|
||||
"{ [32m'0'[39m:
|
||||
{ [32m'1'[39m:
|
||||
{ [32m'2'[39m:
|
||||
{ [32m'3'[39m:
|
||||
{ [32m'4'[39m:
|
||||
{ [32m'5'[39m:
|
||||
{ [32m'6'[39m:
|
||||
{ [32m'7'[39m:
|
||||
{ [32m'8'[39m:
|
||||
{ [32m'9'[39m:
|
||||
{ [32m'10'[39m: { [32m'11'[39m: { [32m'12'[39m: { [32m'13'[39m: { [32m'14'[39m: { [32m'15'[39m: [36m[Object][39m } } } } } } } } } } } } } } },
|
||||
"{ [32m'0'[39m: { [32m'1'[39m: { [32m'2'[39m: { [32m'3'[39m: { [32m'4'[39m: { [32m'5'[39m: [36m[Object][39m } } } } },
|
||||
whoops: [36m[Circular][39m }",
|
||||
],
|
||||
]
|
||||
|
@ -77,17 +59,7 @@ Array [
|
|||
Array [
|
||||
"Promise Resolved:
|
||||
",
|
||||
"{ [32m'0'[39m:
|
||||
{ [32m'1'[39m:
|
||||
{ [32m'2'[39m:
|
||||
{ [32m'3'[39m:
|
||||
{ [32m'4'[39m:
|
||||
{ [32m'5'[39m:
|
||||
{ [32m'6'[39m:
|
||||
{ [32m'7'[39m:
|
||||
{ [32m'8'[39m:
|
||||
{ [32m'9'[39m:
|
||||
{ [32m'10'[39m: { [32m'11'[39m: { [32m'12'[39m: { [32m'13'[39m: { [32m'14'[39m: { [32m'15'[39m: [36m[Object][39m } } } } } } } } } } } } } } },
|
||||
"{ [32m'0'[39m: { [32m'1'[39m: { [32m'2'[39m: { [32m'3'[39m: { [32m'4'[39m: { [32m'5'[39m: [36m[Object][39m } } } } },
|
||||
whoops: [36m[Circular][39m }",
|
||||
],
|
||||
]
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
import repl from 'repl';
|
||||
import util from 'util';
|
||||
|
||||
const PRINT_DEPTH = 5;
|
||||
|
||||
/**
|
||||
* Starts an interactive REPL with a global `server` object.
|
||||
*
|
||||
|
@ -29,18 +31,27 @@ export function startRepl(kbnServer) {
|
|||
const replServer = repl.start({
|
||||
prompt: 'Kibana> ',
|
||||
useColors: true,
|
||||
writer: promiseFriendlyWriter(() => replServer.displayPrompt()),
|
||||
writer: promiseFriendlyWriter({
|
||||
displayPrompt: () => replServer.displayPrompt(),
|
||||
getPrintDepth: () => replServer.context.repl.printDepth,
|
||||
}),
|
||||
});
|
||||
|
||||
replServer.context.kbnServer = kbnServer;
|
||||
replServer.context.server = kbnServer.server;
|
||||
replServer.context.repl = {
|
||||
print(obj, depth = null) {
|
||||
console.log(promisePrint(obj, () => replServer.displayPrompt(), depth));
|
||||
return '';
|
||||
},
|
||||
const initializeContext = () => {
|
||||
replServer.context.kbnServer = kbnServer;
|
||||
replServer.context.server = kbnServer.server;
|
||||
replServer.context.repl = {
|
||||
printDepth: PRINT_DEPTH,
|
||||
print(obj, depth = null) {
|
||||
console.log(promisePrint(obj, () => replServer.displayPrompt(), () => depth));
|
||||
return '';
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
initializeContext();
|
||||
replServer.on('reset', initializeContext);
|
||||
|
||||
return replServer;
|
||||
}
|
||||
|
||||
|
@ -54,12 +65,12 @@ function prettyPrint(text, o, depth) {
|
|||
|
||||
// This lets us handle promises more gracefully than the default REPL,
|
||||
// which doesn't show the results.
|
||||
function promiseFriendlyWriter(displayPrompt) {
|
||||
const PRINT_DEPTH = 15;
|
||||
return (result) => promisePrint(result, displayPrompt, PRINT_DEPTH);
|
||||
function promiseFriendlyWriter({ displayPrompt, getPrintDepth }) {
|
||||
return (result) => promisePrint(result, displayPrompt, getPrintDepth);
|
||||
}
|
||||
|
||||
function promisePrint(result, displayPrompt, depth) {
|
||||
function promisePrint(result, displayPrompt, getPrintDepth) {
|
||||
const depth = getPrintDepth();
|
||||
if (result && typeof result.then === 'function') {
|
||||
// Bit of a hack to encourage the user to wait for the result of a promise
|
||||
// by printing text out beside the current prompt.
|
||||
|
|
|
@ -21,14 +21,29 @@ jest.mock('repl', () => ({ start: (opts) => ({ opts, context: {} }) }), { virtua
|
|||
|
||||
describe('repl', () => {
|
||||
const originalConsoleLog = console.log;
|
||||
let mockRepl;
|
||||
|
||||
beforeEach(() => {
|
||||
global.console.log = jest.fn();
|
||||
require('repl').start = (opts) => {
|
||||
return {
|
||||
let resetHandler;
|
||||
const replServer = {
|
||||
opts,
|
||||
context: { },
|
||||
on: jest.fn((eventName, handler) => {
|
||||
expect(eventName).toBe('reset');
|
||||
resetHandler = handler;
|
||||
}),
|
||||
};
|
||||
|
||||
mockRepl = {
|
||||
replServer,
|
||||
clear() {
|
||||
replServer.context = {};
|
||||
resetHandler(replServer.context);
|
||||
},
|
||||
};
|
||||
return replServer;
|
||||
};
|
||||
});
|
||||
|
||||
|
@ -79,6 +94,37 @@ describe('repl', () => {
|
|||
.toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('it allows print depth to be specified', () => {
|
||||
const { startRepl } = require('.');
|
||||
const replServer = startRepl({});
|
||||
const splosion = {};
|
||||
let child = splosion;
|
||||
for (let i = 0; i < 2000; ++i) {
|
||||
child[i] = {};
|
||||
child = child[i];
|
||||
}
|
||||
splosion.whoops = splosion;
|
||||
replServer.context.repl.printDepth = 2;
|
||||
expect(replServer.opts.writer(splosion))
|
||||
.toMatchSnapshot();
|
||||
});
|
||||
|
||||
test('resets context to original when reset', () => {
|
||||
const { startRepl } = require('.');
|
||||
const testServer = {
|
||||
server: { },
|
||||
};
|
||||
const replServer = startRepl(testServer);
|
||||
replServer.context.foo = 'bar';
|
||||
expect(replServer.context.server).toBe(testServer.server);
|
||||
expect(replServer.context.kbnServer).toBe(testServer);
|
||||
expect(replServer.context.foo).toBe('bar');
|
||||
mockRepl.clear();
|
||||
expect(replServer.context.server).toBe(testServer.server);
|
||||
expect(replServer.context.kbnServer).toBe(testServer);
|
||||
expect(replServer.context.foo).toBeUndefined();
|
||||
});
|
||||
|
||||
test('it prints promise resolves', async () => {
|
||||
const { startRepl } = require('.');
|
||||
const replServer = startRepl({});
|
||||
|
|
|
@ -217,6 +217,9 @@ export default function (program) {
|
|||
const KbnServer = require('../../server/kbn_server');
|
||||
try {
|
||||
kbnServer = new KbnServer(settings);
|
||||
if (shouldStartRepl(opts)) {
|
||||
startRepl(kbnServer);
|
||||
}
|
||||
await kbnServer.ready();
|
||||
} catch (error) {
|
||||
const { server } = kbnServer;
|
||||
|
@ -248,10 +251,6 @@ export default function (program) {
|
|||
kbnServer.server.log(['info', 'config'], 'Reloaded logging configuration due to SIGHUP.');
|
||||
});
|
||||
|
||||
if (shouldStartRepl(opts)) {
|
||||
startRepl(kbnServer);
|
||||
}
|
||||
|
||||
return kbnServer;
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue