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:
Chris Davies 2018-05-30 11:37:01 -04:00 committed by GitHub
parent 9d08ab7f49
commit ab6dfe7043
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 78 additions and 50 deletions

View file

@ -1,19 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`repl it allows print depth to be specified 1`] = `"{ '0': { '1': { '2': [Object] } }, whoops: [Circular] }"`;
exports[`repl it colorizes raw values 1`] = `"{ meaning: 42 }"`;
exports[`repl it handles deep and recursive objects 1`] = `
"{ '0':
{ '1':
{ '2':
{ '3':
{ '4':
{ '5':
{ '6':
{ '7':
{ '8':
{ '9':
{ '10': { '11': { '12': { '13': { '14': { '15': [Object] } } } } } } } } } } } } } } },
"{ '0': { '1': { '2': { '3': { '4': { '5': [Object] } } } } },
whoops: [Circular] }"
`;
@ -53,17 +45,7 @@ Array [
Array [
"Promise Rejected:
",
"{ '0':
{ '1':
{ '2':
{ '3':
{ '4':
{ '5':
{ '6':
{ '7':
{ '8':
{ '9':
{ '10': { '11': { '12': { '13': { '14': { '15': [Object] } } } } } } } } } } } } } } },
"{ '0': { '1': { '2': { '3': { '4': { '5': [Object] } } } } },
whoops: [Circular] }",
],
]
@ -77,17 +59,7 @@ Array [
Array [
"Promise Resolved:
",
"{ '0':
{ '1':
{ '2':
{ '3':
{ '4':
{ '5':
{ '6':
{ '7':
{ '8':
{ '9':
{ '10': { '11': { '12': { '13': { '14': { '15': [Object] } } } } } } } } } } } } } } },
"{ '0': { '1': { '2': { '3': { '4': { '5': [Object] } } } } },
whoops: [Circular] }",
],
]

View file

@ -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.

View file

@ -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({});

View file

@ -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;
});
}