/
githubmirror
/
nest
Обзор
Документация
Войти
/
githubmirror
/
nest
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
packages/core/repl/repl-context.ts
186 строк
5 KB
Kamil Myśliwiec
build: use strict null checks part 5
26 ноя 2024, 16:39
Не верифицирован
26 ноя 2024, 16:39
7d3e5c1
Код
Авторство
О чём код?
import { INestApplicationContext, InjectionToken, Logger, } from '@nestjs/common'; import { ApplicationConfig } from '../application-config'; import { ModuleRef, NestContainer } from '../injector'; import { InternalCoreModule } from '../injector/internal-core-module/internal-core-module'; import { Module } from '../injector/module'; import { DebugReplFn, GetReplFn, HelpReplFn, MethodsReplFn, ResolveReplFn, SelectReplFn, } from './native-functions'; import { ReplFunction } from './repl-function'; import type { ReplFunctionClass } from './repl.interfaces'; type ModuleKey = string; export type ModuleDebugEntry = { controllers: Record<string, InjectionToken>; providers: Record<string, InjectionToken>; }; type ReplScope = Record<string, any>; export class ReplContext { public readonly logger = new Logger(ReplContext.name); public debugRegistry: Record<ModuleKey, ModuleDebugEntry> = {}; public readonly globalScope: ReplScope = Object.create(null); public readonly nativeFunctions = new Map< string, InstanceType<ReplFunctionClass> >(); private readonly container: NestContainer; constructor( public readonly app: INestApplicationContext, nativeFunctionsClassRefs?: ReplFunctionClass[], ) { this.container = (app as any).container; // Using `any` because `app.container` is not public. this.initializeContext(); this.initializeNativeFunctions(nativeFunctionsClassRefs || []); } public writeToStdout(text: string) { process.stdout.write(text); } private initializeContext() { const modules = this.container.getModules(); modules.forEach(moduleRef => { let moduleName = moduleRef.metatype.name; if (moduleName === InternalCoreModule.name) { return; } if (this.globalScope[moduleName]) { moduleName += ` (${moduleRef.token})`; } this.introspectCollection(moduleRef, moduleName, 'providers'); this.introspectCollection(moduleRef, moduleName, 'controllers'); // For in REPL auto-complete functionality Object.defineProperty(this.globalScope, moduleName, { value: moduleRef.metatype, configurable: false, enumerable: true, }); }); } private introspectCollection( moduleRef: Module, moduleKey: ModuleKey, collection: keyof ModuleDebugEntry, ) { const moduleDebugEntry = {}; moduleRef[collection].forEach(({ token }) => { const stringifiedToken = this.stringifyToken(token); if ( stringifiedToken === ApplicationConfig.name || stringifiedToken === moduleRef.metatype.name ) { return; } if (!this.globalScope[stringifiedToken]) { // For in REPL auto-complete functionality Object.defineProperty(this.globalScope, stringifiedToken, { value: token, configurable: false, enumerable: true, }); } if (stringifiedToken === ModuleRef.name) { return; } moduleDebugEntry[stringifiedToken] = token; }); this.debugRegistry[moduleKey] = { ...this.debugRegistry?.[moduleKey], [collection]: moduleDebugEntry, }; } private stringifyToken(token: unknown): string { return typeof token !== 'string' ? typeof token === 'function' ? token.name : (token?.toString() as string) : `"${token}"`; } private addNativeFunction( NativeFunctionRef: ReplFunctionClass, ): InstanceType<ReplFunctionClass>[] { const nativeFunction = new NativeFunctionRef(this); const nativeFunctions = [nativeFunction]; this.nativeFunctions.set(nativeFunction.fnDefinition.name, nativeFunction); nativeFunction.fnDefinition.aliases?.forEach(aliasName => { const aliasNativeFunction: InstanceType<ReplFunctionClass> = Object.create(nativeFunction); aliasNativeFunction.fnDefinition = { name: aliasName, description: aliasNativeFunction.fnDefinition.description, signature: aliasNativeFunction.fnDefinition.signature, }; this.nativeFunctions.set(aliasName, aliasNativeFunction); nativeFunctions.push(aliasNativeFunction); }); return nativeFunctions; } private registerFunctionIntoGlobalScope( nativeFunction: InstanceType<ReplFunctionClass>, ) { // Bind the method to REPL's context: this.globalScope[nativeFunction.fnDefinition.name] = nativeFunction.action.bind(nativeFunction); // Load the help trigger as a `help` getter on each native function: const functionBoundRef: ReplFunction['action'] = this.globalScope[nativeFunction.fnDefinition.name]; Object.defineProperty(functionBoundRef, 'help', { enumerable: false, configurable: false, get: () => // Dynamically builds the help message as will unlikely to be called // several times. this.writeToStdout(nativeFunction.makeHelpMessage()), }); } private initializeNativeFunctions( nativeFunctionsClassRefs: ReplFunctionClass[], ): void { const builtInFunctionsClassRefs: ReplFunctionClass[] = [ HelpReplFn, GetReplFn, ResolveReplFn, SelectReplFn, DebugReplFn, MethodsReplFn, ]; builtInFunctionsClassRefs .concat(nativeFunctionsClassRefs) .forEach(NativeFunction => { const nativeFunctions = this.addNativeFunction(NativeFunction); nativeFunctions.forEach(nativeFunction => { this.registerFunctionIntoGlobalScope(nativeFunction); }); }); } }