From d8ece486e88b8fc74b362b4571400078744f7f86 Mon Sep 17 00:00:00 2001 From: "Micael Levi L. Cavalcante" Date: Sun, 27 Nov 2022 23:24:19 -0400 Subject: [PATCH] feat(core): enhance repl 'help' command with nestjs functions --- packages/core/repl/repl-native-commands.ts | 51 ++++++++++++++++++++++ packages/core/repl/repl.ts | 3 ++ 2 files changed, 54 insertions(+) create mode 100644 packages/core/repl/repl-native-commands.ts diff --git a/packages/core/repl/repl-native-commands.ts b/packages/core/repl/repl-native-commands.ts new file mode 100644 index 00000000000..aae7661e8ca --- /dev/null +++ b/packages/core/repl/repl-native-commands.ts @@ -0,0 +1,51 @@ +import type { REPLServer } from 'repl'; + +/** + * Displays the list of available commands in the REPL alonside with their + * descriptions. + * (c) This code was inspired by the 'help' command from Node.js core: + * {@link https://github.com/nodejs/node/blob/58b60c1393dd65cd228a8b0084a19acd2c1d16aa/lib/repl.js#L1741-L1759} + */ +/* istanbul ignore next */ +function listAllCommands(replServer: REPLServer) { + Object.keys(replServer.commands) + .sort() + .forEach(name => { + const cmd = replServer.commands[name]; + if (cmd) { + replServer.output.write(`${name}\t${cmd.help || ''}\n`); + } + }); +} + +export function defineDefaultCommandsOnRepl(replServer: REPLServer): void { + replServer.defineCommand('help', { + help: 'Show REPL options', + action(name?: string) { + this.clearBufferedCommand(); + + if (name) { + // Considering native commands before native nestjs injected functions. + const nativeCommandOrFunction = + this.commands[name] || this.context[name]; + // NOTE: If the command was retrieve from the context, it will have a `help` + // getter property that outputs the helper message and returns undefined. + // But if the command was retrieve from the `commands` object, it will + // have a `help` property that returns the helper message. + const helpMessage = nativeCommandOrFunction?.help; + if (helpMessage) { + this.output.write(`${helpMessage}\n`); + } + } else { + listAllCommands(this); + this.output.write('\n\n'); + this.context.help(); + this.output.write( + '\nPress Ctrl+C to abort current expression, Ctrl+D to exit the REPL\n', + ); + } + + this.displayPrompt(); + }, + }); +} diff --git a/packages/core/repl/repl.ts b/packages/core/repl/repl.ts index 980dd652cb0..2e021a1e4c4 100644 --- a/packages/core/repl/repl.ts +++ b/packages/core/repl/repl.ts @@ -5,6 +5,7 @@ import { assignToObject } from './assign-to-object.util'; import { REPL_INITIALIZED_MESSAGE } from './constants'; import { ReplContext } from './repl-context'; import { ReplLogger } from './repl-logger'; +import { defineDefaultCommandsOnRepl } from './repl-native-commands'; export async function repl(module: Type | DynamicModule) { const app = await NestFactory.createApplicationContext(module, { @@ -23,5 +24,7 @@ export async function repl(module: Type | DynamicModule) { }); assignToObject(replServer.context, replContext.globalScope); + defineDefaultCommandsOnRepl(replServer); + return replServer; }