-
-
Notifications
You must be signed in to change notification settings - Fork 7.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(core): read–eval–print loop feature #9684
Conversation
Pull Request Test Coverage Report for Build b52928ac-3c6e-4a55-a0d4-5db25ea40e60
💛 - Coveralls |
A fantastic feature!. I can't wait to try it out 😻 |
can't we have a |
I think |
as we have |
Many times if not always |
I have three suggestions that I believe could improve DX:
I've implemented both locally to demonstrate 1 and 2: Implementationparts of the code// repl-context.ts
export const REPL_COMMANDS = 'repl:all-commands';
type HelpTextBuilder = (colors: typeof clc) => string;
export function ReplCommand(
helpTextOrBuilder: string | HelpTextBuilder,
): MethodDecorator {
return (target: Object, propertyKey: string | symbol) => {
const commands =
Reflect.getMetadata(REPL_COMMANDS, target.constructor) || [];
commands.push(propertyKey);
Reflect.defineMetadata(REPL_COMMANDS, commands, target.constructor);
Object.defineProperty(target[propertyKey], 'helpText', {
value:
(typeof helpTextOrBuilder === 'string'
? helpTextOrBuilder
: helpTextOrBuilder(clc)) + '\n',
enumerable: false,
writable: false,
configurable: false,
});
};
} // repl.ts
import { Logger, Type } from '@nestjs/common';
import * as _repl from 'repl';
import { NestFactory } from '../nest-factory';
import { REPL_INITIALIZED_MESSAGE } from './constants';
import { ReplContext, REPL_COMMANDS } from './repl-context';
import { ReplLogger } from './repl-logger';
interface ReplOptions {
Context?: Type<ReplContext>;
}
export async function repl(
module: Type,
replOptions?: ReplOptions = {},
) {
const app = await NestFactory.create(module, {
abortOnError: false,
logger: new ReplLogger(),
});
await app.init();
const Context = replOptions.Context || ReplContext;
const replContext = new Context(app);
Logger.log(REPL_INITIALIZED_MESSAGE);
const replServer = _repl.start({
prompt: '\x1b[32m>\x1b[0m ',
ignoreUndefined: true,
});
const commands: string[] = Reflect.getMetadata(REPL_COMMANDS, Context) || [];
commands.forEach(command => {
if (!replContext[command]) return;
replServer.context[command] = replContext[command].bind(replContext);
Object.defineProperty(replServer.context[command], 'help', {
get: () => replContext.writeToStdout(replContext[command].helpText),
enumerable: false,
configurable: false,
});
});
return replServer;
} demo.mp4 |
@micalevisk feel free to create a PR that's targeting this PR :) |
@kamilmysliwiec I guess we can postpone those suggestions as they won't break the current behavior (and could be trickier to write tests). |
@micalevisk I don't plan to merge it earlier than ~mid-June anyway so feel free to create a PR whenever you're ready! |
feat(core,common): add help messages to REPL built-in functions
fix(core): prompt respects `NO_COLOR` config
packages/core/repl/repl-context.ts
Outdated
} | ||
|
||
private initializeContext() { | ||
const globalRef = globalThis; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why renaming globalThis
to globalRef
here but not in the introspectCollection
method? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this might be a leftover I forgot to remove
by marking them as a read-only properties of `globalThis` obj
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing feature! Looking forward to use it 🚀
Just left minor comments regarding some typos :)
@@ -0,0 +1,6 @@ | |||
export * from './help-repl-fn'; | |||
export * from './get-relp-fn'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there is a minor typo here 😄
export * from './get-relp-fn'; | |
export * from './get-repl-fn'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, my bad. I fixed them in #9720
@@ -0,0 +1,17 @@ | |||
import type { Type } from '@nestjs/common'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(related to file): There is a minor typo in the file name. It should be get-repl-fn.ts
fix(core): prevent renaming global providers and modules in the repl
@micalevisk would you like to start working on a PR to the docs (for this feature)? Preferably in Recipes category :) I can pick it up later on if needed! |
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Issue Number: N/A
What is the new behavior?
https://twitter.com/i/status/1529088190958735361
Does this PR introduce a breaking change?
Other information