@nestjs/core 9.0.0-next.1 → 9.0.0-next.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/Readme.md +4 -3
  2. package/adapters/http-adapter.d.ts +2 -0
  3. package/exceptions/base-exception-filter.js +14 -2
  4. package/helpers/context-id-factory.d.ts +3 -2
  5. package/index.d.ts +1 -0
  6. package/index.js +1 -0
  7. package/injector/index.d.ts +1 -1
  8. package/injector/injector.d.ts +1 -1
  9. package/injector/injector.js +18 -8
  10. package/injector/instance-wrapper.d.ts +3 -3
  11. package/package.json +2 -2
  12. package/repl/assign-to-object.util.d.ts +5 -0
  13. package/repl/assign-to-object.util.js +15 -0
  14. package/repl/constants.d.ts +1 -0
  15. package/repl/constants.js +4 -0
  16. package/repl/index.d.ts +1 -0
  17. package/repl/index.js +4 -0
  18. package/repl/native-functions/debug-repl-fn.d.ts +9 -0
  19. package/repl/native-functions/debug-repl-fn.js +46 -0
  20. package/repl/native-functions/get-relp-fn.d.ts +7 -0
  21. package/repl/native-functions/get-relp-fn.js +19 -0
  22. package/repl/native-functions/help-repl-fn.d.ts +7 -0
  23. package/repl/native-functions/help-repl-fn.js +29 -0
  24. package/repl/native-functions/index.d.ts +6 -0
  25. package/repl/native-functions/index.js +9 -0
  26. package/repl/native-functions/methods-repl-fn.d.ts +8 -0
  27. package/repl/native-functions/methods-repl-fn.js +28 -0
  28. package/repl/native-functions/resolve-repl-fn.d.ts +7 -0
  29. package/repl/native-functions/resolve-repl-fn.js +18 -0
  30. package/repl/native-functions/select-relp-fn.d.ts +7 -0
  31. package/repl/native-functions/select-relp-fn.js +18 -0
  32. package/repl/repl-context.d.ts +26 -0
  33. package/repl/repl-context.js +124 -0
  34. package/repl/repl-function.d.ts +18 -0
  35. package/repl/repl-function.js +19 -0
  36. package/repl/repl-logger.d.ts +5 -0
  37. package/repl/repl-logger.js +22 -0
  38. package/repl/repl.d.ts +4 -0
  39. package/repl/repl.interfaces.d.ts +16 -0
  40. package/repl/repl.interfaces.js +2 -0
  41. package/repl/repl.js +27 -0
package/Readme.md CHANGED
@@ -65,19 +65,20 @@ Nest is an MIT-licensed open source project. It can grow thanks to the sponsors
65
65
  <td>
66
66
  <a href="https://nx.dev" target="_blank"><img src="https://nestjs.com/img/nx-logo.png" height="45" valign="middle" /></a></td>
67
67
  <td>
68
- <a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td>
68
+ <a href="https://valor-software.com/" target="_blank"><img src="https://docs.nestjs.com/assets/sponsors/valor-software.png" width="170" valign="middle" /></a></td><td>
69
+ <a href="https://amplication.com/" target="_blank"><img src="https://nestjs.com/img/amplication-logo.svg" width="190" valign="middle" /></a></td>
69
70
  </tr></table>
70
71
 
71
72
  #### Gold Sponsors
72
73
 
73
74
  <table style="text-align:center;"><tr><td>
74
- <a href="https://careers.labster.com/departments/platform" target="_blank"><img src="https://nestjs.com/img/labster-logo.png" width="170" valign="middle" /></a></td><td>
75
75
  <a href="https://weld.app/" target="_blank"><img src="https://nestjs.com/img/weld-logo.svg" width="140" valign="middle" /></a></td>
76
76
  <td>
77
77
  <a href="https://intrinsic.ventures/" target="_blank"><img src="https://nestjs.com/img/intrinisic-logo.png" width="210" valign="middle" /></a></td>
78
78
  <td>
79
79
  <a href="https://jetbrains.com/" target="_blank"><img src="https://nestjs.com/img/jetbrains-logo.svg" width="110" valign="middle" /></a></td><td>
80
- <a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/snyk-logo-black.png" width="185" valign="middle" /></a></td></</tr></table>
80
+ <a href="https://snyk.co/nestjs" target="_blank"><img src="https://nestjs.com/img/snyk-logo-black.png" width="185" valign="middle" /></a></td><td>
81
+ <a href="https://fuseautotech.com/" target="_blank"><img src="https://nestjs.com/img/fuse-logo.svg" width="105" valign="middle" /></a></td></</tr></table>
81
82
 
82
83
  #### Silver Sponsors
83
84
 
@@ -42,10 +42,12 @@ export declare abstract class AbstractHttpAdapter<TServer = any, TRequest = any,
42
42
  abstract getRequestUrl(request: any): any;
43
43
  abstract status(response: any, statusCode: number): any;
44
44
  abstract reply(response: any, body: any, statusCode?: number): any;
45
+ abstract end(response: any, message?: string): any;
45
46
  abstract render(response: any, view: string, options: any): any;
46
47
  abstract redirect(response: any, statusCode: number, url: string): any;
47
48
  abstract setErrorHandler(handler: Function, prefix?: string): any;
48
49
  abstract setNotFoundHandler(handler: Function, prefix?: string): any;
50
+ abstract isHeadersSent(response: any): any;
49
51
  abstract setHeader(response: any, name: string, value: string): any;
50
52
  abstract registerParserMiddleware(prefix?: string, rawBody?: boolean): any;
51
53
  abstract enableCors(options: CorsOptions | CorsOptionsDelegate<TRequest>, prefix?: string): any;
@@ -23,7 +23,13 @@ class BaseExceptionFilter {
23
23
  statusCode: exception.getStatus(),
24
24
  message: res,
25
25
  };
26
- applicationRef.reply(host.getArgByIndex(1), message, exception.getStatus());
26
+ const response = host.getArgByIndex(1);
27
+ if (!applicationRef.isHeadersSent(response)) {
28
+ applicationRef.reply(response, message, exception.getStatus());
29
+ }
30
+ else {
31
+ applicationRef.end(response);
32
+ }
27
33
  }
28
34
  handleUnknownError(exception, host, applicationRef) {
29
35
  const body = this.isHttpError(exception)
@@ -35,7 +41,13 @@ class BaseExceptionFilter {
35
41
  statusCode: common_1.HttpStatus.INTERNAL_SERVER_ERROR,
36
42
  message: constants_1.MESSAGES.UNKNOWN_EXCEPTION_MESSAGE,
37
43
  };
38
- applicationRef.reply(host.getArgByIndex(1), body, body.statusCode);
44
+ const response = host.getArgByIndex(1);
45
+ if (!applicationRef.isHeadersSent(response)) {
46
+ applicationRef.reply(response, body, body.statusCode);
47
+ }
48
+ else {
49
+ applicationRef.end(response);
50
+ }
39
51
  if (this.isExceptionObject(exception)) {
40
52
  return BaseExceptionFilter.logger.error(exception.message, exception.stack);
41
53
  }
@@ -1,4 +1,4 @@
1
- import { ChildContextIdInfo, ContextId } from '../injector/instance-wrapper';
1
+ import { ContextId, HostComponentInfo } from '../injector/instance-wrapper';
2
2
  export declare function createContextId(): ContextId;
3
3
  export interface ContextIdStrategy<T = any> {
4
4
  /**
@@ -6,8 +6,9 @@ export interface ContextIdStrategy<T = any> {
6
6
  * This lets you construct durable DI sub-trees that can be shared between contexts.
7
7
  * @param contextId auto-generated child context id
8
8
  * @param request request object
9
+ * @returns a context id resolver function
9
10
  */
10
- attach(contextId: ContextId, request: T): ((info: ChildContextIdInfo) => ContextId) | undefined;
11
+ attach(contextId: ContextId, request: T): ((info: HostComponentInfo) => ContextId) | undefined;
11
12
  }
12
13
  export declare class ContextIdFactory {
13
14
  private static strategy?;
package/index.d.ts CHANGED
@@ -11,5 +11,6 @@ export * from './middleware';
11
11
  export * from './nest-application';
12
12
  export * from './nest-application-context';
13
13
  export { NestFactory } from './nest-factory';
14
+ export * from './repl';
14
15
  export * from './router';
15
16
  export * from './services';
package/index.js CHANGED
@@ -26,5 +26,6 @@ tslib_1.__exportStar(require("./nest-application"), exports);
26
26
  tslib_1.__exportStar(require("./nest-application-context"), exports);
27
27
  var nest_factory_1 = require("./nest-factory");
28
28
  Object.defineProperty(exports, "NestFactory", { enumerable: true, get: function () { return nest_factory_1.NestFactory; } });
29
+ tslib_1.__exportStar(require("./repl"), exports);
29
30
  tslib_1.__exportStar(require("./router"), exports);
30
31
  tslib_1.__exportStar(require("./services"), exports);
@@ -1,6 +1,6 @@
1
1
  export * from './container';
2
2
  export * from './inquirer';
3
- export { ChildContextIdInfo, ContextId } from './instance-wrapper';
3
+ export { ContextId, HostComponentInfo } from './instance-wrapper';
4
4
  export * from './lazy-module-loader';
5
5
  export * from './module-ref';
6
6
  export * from './modules-container';
@@ -48,7 +48,7 @@ export declare class Injector {
48
48
  loadController(wrapper: InstanceWrapper<Controller>, moduleRef: Module, contextId?: ContextId): Promise<void>;
49
49
  loadInjectable<T = any>(wrapper: InstanceWrapper<T>, moduleRef: Module, contextId?: ContextId, inquirer?: InstanceWrapper): Promise<void>;
50
50
  loadProvider(wrapper: InstanceWrapper<Injectable>, moduleRef: Module, contextId?: ContextId, inquirer?: InstanceWrapper): Promise<void>;
51
- applyDoneHook<T>(wrapper: InstancePerContext<T>): () => void;
51
+ applyDoneHook<T>(wrapper: InstancePerContext<T>): (err?: unknown) => void;
52
52
  resolveConstructorParams<T>(wrapper: InstanceWrapper<T>, moduleRef: Module, inject: InjectorDependency[], callback: (args: unknown[]) => void | Promise<void>, contextId?: ContextId, inquirer?: InstanceWrapper, parentInquirer?: InstanceWrapper): Promise<void>;
53
53
  getClassDependencies<T>(wrapper: InstanceWrapper<T>): [InjectorDependency[], number[]];
54
54
  getFactoryProviderDependencies<T>(wrapper: InstanceWrapper<T>): [InjectorDependency[], number[]];
@@ -31,7 +31,11 @@ class Injector {
31
31
  const inquirerId = this.getInquirerId(inquirer);
32
32
  const instanceHost = wrapper.getInstanceByContextId(this.getContextId(contextId, wrapper), inquirerId);
33
33
  if (instanceHost.isPending) {
34
- return instanceHost.donePromise;
34
+ return instanceHost.donePromise.then((err) => {
35
+ if (err) {
36
+ throw err;
37
+ }
38
+ });
35
39
  }
36
40
  const done = this.applyDoneHook(instanceHost);
37
41
  const token = wrapper.token || wrapper.name;
@@ -43,13 +47,19 @@ class Injector {
43
47
  if (instanceHost.isResolved) {
44
48
  return done();
45
49
  }
46
- const callback = async (instances) => {
47
- const properties = await this.resolveProperties(wrapper, moduleRef, inject, contextId, wrapper, inquirer);
48
- const instance = await this.instantiateClass(instances, wrapper, targetWrapper, contextId, inquirer);
49
- this.applyProperties(instance, properties);
50
- done();
51
- };
52
- await this.resolveConstructorParams(wrapper, moduleRef, inject, callback, contextId, wrapper, inquirer);
50
+ try {
51
+ const callback = async (instances) => {
52
+ const properties = await this.resolveProperties(wrapper, moduleRef, inject, contextId, wrapper, inquirer);
53
+ const instance = await this.instantiateClass(instances, wrapper, targetWrapper, contextId, inquirer);
54
+ this.applyProperties(instance, properties);
55
+ done();
56
+ };
57
+ await this.resolveConstructorParams(wrapper, moduleRef, inject, callback, contextId, wrapper, inquirer);
58
+ }
59
+ catch (err) {
60
+ done(err);
61
+ throw err;
62
+ }
53
63
  }
54
64
  async loadMiddleware(wrapper, collection, moduleRef, contextId = constants_2.STATIC_CONTEXT, inquirer) {
55
65
  const { metatype, token } = wrapper;
@@ -3,7 +3,7 @@ import { FactoryProvider } from '@nestjs/common/interfaces';
3
3
  import { InstanceToken, Module } from './module';
4
4
  export declare const INSTANCE_METADATA_SYMBOL: unique symbol;
5
5
  export declare const INSTANCE_ID_SYMBOL: unique symbol;
6
- export interface ChildContextIdInfo {
6
+ export interface HostComponentInfo {
7
7
  /**
8
8
  * Injection token (or class reference)
9
9
  */
@@ -15,13 +15,13 @@ export interface ChildContextIdInfo {
15
15
  }
16
16
  export interface ContextId {
17
17
  readonly id: number;
18
- getParent?(info: ChildContextIdInfo): ContextId;
18
+ getParent?(info: HostComponentInfo): ContextId;
19
19
  }
20
20
  export interface InstancePerContext<T> {
21
21
  instance: T;
22
22
  isResolved?: boolean;
23
23
  isPending?: boolean;
24
- donePromise?: Promise<void>;
24
+ donePromise?: Promise<unknown>;
25
25
  }
26
26
  export interface PropertyMetadata {
27
27
  key: symbol | string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nestjs/core",
3
- "version": "9.0.0-next.1",
3
+ "version": "9.0.0-next.2",
4
4
  "description": "Nest - modern, fast, powerful node.js web framework (@core)",
5
5
  "author": "Kamil Mysliwiec",
6
6
  "license": "MIT",
@@ -36,7 +36,7 @@
36
36
  "uuid": "8.3.2"
37
37
  },
38
38
  "devDependencies": {
39
- "@nestjs/common": "^9.0.0-next.1"
39
+ "@nestjs/common": "^9.0.0-next.2"
40
40
  },
41
41
  "peerDependencies": {
42
42
  "@nestjs/common": "^8.0.0",
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Similar to `Object.assign` but copying properties descriptors from `source`
3
+ * as well.
4
+ */
5
+ export declare function assignToObject<T, U>(target: T, source: U): T & U;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assignToObject = void 0;
4
+ /**
5
+ * Similar to `Object.assign` but copying properties descriptors from `source`
6
+ * as well.
7
+ */
8
+ function assignToObject(target, source) {
9
+ Object.defineProperties(target, Object.keys(source).reduce((descriptors, key) => {
10
+ descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
11
+ return descriptors;
12
+ }, Object.create(null)));
13
+ return target;
14
+ }
15
+ exports.assignToObject = assignToObject;
@@ -0,0 +1 @@
1
+ export declare const REPL_INITIALIZED_MESSAGE = "REPL initialized";
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.REPL_INITIALIZED_MESSAGE = void 0;
4
+ exports.REPL_INITIALIZED_MESSAGE = 'REPL initialized';
@@ -0,0 +1 @@
1
+ export * from './repl';
package/repl/index.js ADDED
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./repl"), exports);
@@ -0,0 +1,9 @@
1
+ import type { Type } from '@nestjs/common';
2
+ import { ReplFunction } from '../repl-function';
3
+ import type { ReplFnDefinition } from '../repl.interfaces';
4
+ export declare class DebugReplFn extends ReplFunction {
5
+ fnDefinition: ReplFnDefinition;
6
+ action(moduleCls?: Type<unknown> | string): void;
7
+ private printCtrlsAndProviders;
8
+ private printCollection;
9
+ }
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DebugReplFn = void 0;
4
+ const cli_colors_util_1 = require("@nestjs/common/utils/cli-colors.util");
5
+ const repl_function_1 = require("../repl-function");
6
+ class DebugReplFn extends repl_function_1.ReplFunction {
7
+ constructor() {
8
+ super(...arguments);
9
+ this.fnDefinition = {
10
+ name: 'debug',
11
+ description: 'Print all registered modules as a list together with their controllers and providers. If the argument is passed in, for example, "debug(MyModule)" then it will only print components of this specific module.',
12
+ signature: '(moduleCls?: ClassRef | string) => void',
13
+ };
14
+ }
15
+ action(moduleCls) {
16
+ this.ctx.writeToStdout('\n');
17
+ if (moduleCls) {
18
+ const token = typeof moduleCls === 'function' ? moduleCls.name : moduleCls;
19
+ const moduleEntry = this.ctx.debugRegistry[token];
20
+ if (!moduleEntry) {
21
+ return this.logger.error(`"${token}" has not been found in the modules registry`);
22
+ }
23
+ this.printCtrlsAndProviders(token, moduleEntry);
24
+ }
25
+ else {
26
+ Object.keys(this.ctx.debugRegistry).forEach(moduleKey => {
27
+ this.printCtrlsAndProviders(moduleKey, this.ctx.debugRegistry[moduleKey]);
28
+ });
29
+ }
30
+ this.ctx.writeToStdout('\n');
31
+ }
32
+ printCtrlsAndProviders(moduleName, moduleDebugEntry) {
33
+ this.ctx.writeToStdout(`${cli_colors_util_1.clc.green(moduleName)}:\n`);
34
+ this.printCollection('controllers', moduleDebugEntry['controllers']);
35
+ this.printCollection('providers', moduleDebugEntry['providers']);
36
+ }
37
+ printCollection(title, collectionValue) {
38
+ const collectionEntries = Object.keys(collectionValue);
39
+ if (collectionEntries.length <= 0) {
40
+ return;
41
+ }
42
+ this.ctx.writeToStdout(` ${cli_colors_util_1.clc.yellow(`- ${title}`)}:\n`);
43
+ collectionEntries.forEach(provider => this.ctx.writeToStdout(` ${cli_colors_util_1.clc.green('◻')} ${provider}\n`));
44
+ }
45
+ }
46
+ exports.DebugReplFn = DebugReplFn;
@@ -0,0 +1,7 @@
1
+ import type { Type } from '@nestjs/common';
2
+ import { ReplFunction } from '../repl-function';
3
+ import type { ReplFnDefinition } from '../repl.interfaces';
4
+ export declare class GetReplFn extends ReplFunction {
5
+ fnDefinition: ReplFnDefinition;
6
+ action(token: string | symbol | Function | Type<any>): any;
7
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GetReplFn = void 0;
4
+ const repl_function_1 = require("../repl-function");
5
+ class GetReplFn extends repl_function_1.ReplFunction {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.fnDefinition = {
9
+ name: 'get',
10
+ signature: '(token: InjectionToken) => any',
11
+ description: 'Retrieves an instance of either injectable or controller, otherwise, throws exception.',
12
+ aliases: ['$'],
13
+ };
14
+ }
15
+ action(token) {
16
+ return this.ctx.app.get(token);
17
+ }
18
+ }
19
+ exports.GetReplFn = GetReplFn;
@@ -0,0 +1,7 @@
1
+ import { ReplFunction } from '../repl-function';
2
+ import type { ReplFnDefinition } from '../repl.interfaces';
3
+ export declare class HelpReplFn extends ReplFunction {
4
+ fnDefinition: ReplFnDefinition;
5
+ static buildHelpMessage: ({ name, description }: ReplFnDefinition) => string;
6
+ action(): void;
7
+ }
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.HelpReplFn = void 0;
4
+ const iterare_1 = require("iterare");
5
+ const cli_colors_util_1 = require("@nestjs/common/utils/cli-colors.util");
6
+ const repl_function_1 = require("../repl-function");
7
+ class HelpReplFn extends repl_function_1.ReplFunction {
8
+ constructor() {
9
+ super(...arguments);
10
+ this.fnDefinition = {
11
+ name: 'help',
12
+ signature: '() => void',
13
+ description: 'Display all available REPL native functions.',
14
+ };
15
+ }
16
+ action() {
17
+ const sortedNativeFunctions = (0, iterare_1.iterate)(this.ctx.nativeFunctions)
18
+ .map(([, nativeFunction]) => nativeFunction.fnDefinition)
19
+ .toArray()
20
+ .sort((a, b) => (a.name < b.name ? -1 : 1));
21
+ this.ctx.writeToStdout(`You can call ${cli_colors_util_1.clc.bold('.help')} on any function listed below (e.g.: ${cli_colors_util_1.clc.bold('help.help')}):\n\n` +
22
+ sortedNativeFunctions.map(HelpReplFn.buildHelpMessage).join('\n') +
23
+ // Without the following LF the last item won't be displayed
24
+ '\n');
25
+ }
26
+ }
27
+ exports.HelpReplFn = HelpReplFn;
28
+ HelpReplFn.buildHelpMessage = ({ name, description }) => cli_colors_util_1.clc.cyanBright(name) +
29
+ (description ? ` ${cli_colors_util_1.clc.bold('-')} ${description}` : '');
@@ -0,0 +1,6 @@
1
+ export * from './help-repl-fn';
2
+ export * from './get-relp-fn';
3
+ export * from './resolve-repl-fn';
4
+ export * from './select-relp-fn';
5
+ export * from './debug-repl-fn';
6
+ export * from './methods-repl-fn';
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./help-repl-fn"), exports);
5
+ tslib_1.__exportStar(require("./get-relp-fn"), exports);
6
+ tslib_1.__exportStar(require("./resolve-repl-fn"), exports);
7
+ tslib_1.__exportStar(require("./select-relp-fn"), exports);
8
+ tslib_1.__exportStar(require("./debug-repl-fn"), exports);
9
+ tslib_1.__exportStar(require("./methods-repl-fn"), exports);
@@ -0,0 +1,8 @@
1
+ import type { Type } from '@nestjs/common';
2
+ import { ReplFunction } from '../repl-function';
3
+ import type { ReplFnDefinition } from '../repl.interfaces';
4
+ export declare class MethodsReplFn extends ReplFunction {
5
+ fnDefinition: ReplFnDefinition;
6
+ private readonly metadataScanner;
7
+ action(token: Type<unknown> | string): void;
8
+ }
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MethodsReplFn = void 0;
4
+ const cli_colors_util_1 = require("@nestjs/common/utils/cli-colors.util");
5
+ const metadata_scanner_1 = require("../../metadata-scanner");
6
+ const repl_function_1 = require("../repl-function");
7
+ class MethodsReplFn extends repl_function_1.ReplFunction {
8
+ constructor() {
9
+ super(...arguments);
10
+ this.fnDefinition = {
11
+ name: 'methods',
12
+ description: 'Display all public methods available on a given provider or controller.',
13
+ signature: '(token: ClassRef | string) => void',
14
+ };
15
+ this.metadataScanner = new metadata_scanner_1.MetadataScanner();
16
+ }
17
+ action(token) {
18
+ const proto = typeof token !== 'function'
19
+ ? Object.getPrototypeOf(this.ctx.app.get(token))
20
+ : token === null || token === void 0 ? void 0 : token.prototype;
21
+ const methods = new Set(this.metadataScanner.getAllFilteredMethodNames(proto));
22
+ this.ctx.writeToStdout('\n');
23
+ this.ctx.writeToStdout(`${cli_colors_util_1.clc.green('Methods')}:\n`);
24
+ methods.forEach(methodName => this.ctx.writeToStdout(` ${cli_colors_util_1.clc.yellow('◻')} ${methodName}\n`));
25
+ this.ctx.writeToStdout('\n');
26
+ }
27
+ }
28
+ exports.MethodsReplFn = MethodsReplFn;
@@ -0,0 +1,7 @@
1
+ import type { Type } from '@nestjs/common';
2
+ import { ReplFunction } from '../repl-function';
3
+ import type { ReplFnDefinition } from '../repl.interfaces';
4
+ export declare class ResolveReplFn extends ReplFunction {
5
+ fnDefinition: ReplFnDefinition;
6
+ action(token: string | symbol | Function | Type<any>, contextId: any): Promise<any>;
7
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ResolveReplFn = void 0;
4
+ const repl_function_1 = require("../repl-function");
5
+ class ResolveReplFn extends repl_function_1.ReplFunction {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.fnDefinition = {
9
+ name: 'resolve',
10
+ description: 'Resolves transient or request-scoped instance of either injectable or controller, otherwise, throws exception.',
11
+ signature: '(token: InjectionToken, contextId: any) => Promise<any>',
12
+ };
13
+ }
14
+ action(token, contextId) {
15
+ return this.ctx.app.resolve(token, contextId);
16
+ }
17
+ }
18
+ exports.ResolveReplFn = ResolveReplFn;
@@ -0,0 +1,7 @@
1
+ import type { DynamicModule, INestApplicationContext, Type } from '@nestjs/common';
2
+ import { ReplFunction } from '../repl-function';
3
+ import type { ReplFnDefinition } from '../repl.interfaces';
4
+ export declare class SelectReplFn extends ReplFunction {
5
+ fnDefinition: ReplFnDefinition;
6
+ action(token: DynamicModule | Type<unknown>): INestApplicationContext;
7
+ }
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SelectReplFn = void 0;
4
+ const repl_function_1 = require("../repl-function");
5
+ class SelectReplFn extends repl_function_1.ReplFunction {
6
+ constructor() {
7
+ super(...arguments);
8
+ this.fnDefinition = {
9
+ name: 'select',
10
+ description: 'Allows navigating through the modules tree, for example, to pull out a specific instance from the selected module.',
11
+ signature: '(token: DynamicModule | ClassRef) => INestApplicationContext',
12
+ };
13
+ }
14
+ action(token) {
15
+ return this.ctx.app.select(token);
16
+ }
17
+ }
18
+ exports.SelectReplFn = SelectReplFn;
@@ -0,0 +1,26 @@
1
+ import { INestApplication, InjectionToken, Logger } from '@nestjs/common';
2
+ import { ReplFunction } from './repl-function';
3
+ import type { ReplFunctionClass } from './repl.interfaces';
4
+ declare type ModuleKey = string;
5
+ export declare type ModuleDebugEntry = {
6
+ controllers: Record<string, InjectionToken>;
7
+ providers: Record<string, InjectionToken>;
8
+ };
9
+ declare type ReplScope = Record<string, any>;
10
+ export declare class ReplContext {
11
+ readonly app: INestApplication;
12
+ readonly logger: Logger;
13
+ debugRegistry: Record<ModuleKey, ModuleDebugEntry>;
14
+ readonly globalScope: ReplScope;
15
+ readonly nativeFunctions: Map<string, ReplFunction<unknown[], any>>;
16
+ private readonly container;
17
+ constructor(app: INestApplication, nativeFunctionsClassRefs?: ReplFunctionClass[]);
18
+ writeToStdout(text: string): void;
19
+ private initializeContext;
20
+ private introspectCollection;
21
+ private stringifyToken;
22
+ private addNativeFunction;
23
+ private registerFunctionIntoGlobalScope;
24
+ private initializeNativeFunctions;
25
+ }
26
+ export {};
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReplContext = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const application_config_1 = require("../application-config");
6
+ const injector_1 = require("../injector");
7
+ const internal_core_module_1 = require("../injector/internal-core-module");
8
+ const native_functions_1 = require("./native-functions");
9
+ class ReplContext {
10
+ constructor(app, nativeFunctionsClassRefs) {
11
+ this.app = app;
12
+ this.logger = new common_1.Logger(ReplContext.name);
13
+ this.debugRegistry = {};
14
+ this.globalScope = Object.create(null);
15
+ this.nativeFunctions = new Map();
16
+ this.container = app.container; // Using `any` because `app.container` is not public.
17
+ this.initializeContext();
18
+ this.initializeNativeFunctions(nativeFunctionsClassRefs || []);
19
+ }
20
+ writeToStdout(text) {
21
+ process.stdout.write(text);
22
+ }
23
+ initializeContext() {
24
+ const modules = this.container.getModules();
25
+ modules.forEach(moduleRef => {
26
+ let moduleName = moduleRef.metatype.name;
27
+ if (moduleName === internal_core_module_1.InternalCoreModule.name) {
28
+ return;
29
+ }
30
+ if (this.globalScope[moduleName]) {
31
+ moduleName += ` (${moduleRef.token})`;
32
+ }
33
+ this.introspectCollection(moduleRef, moduleName, 'providers');
34
+ this.introspectCollection(moduleRef, moduleName, 'controllers');
35
+ // For in REPL auto-complete functionality
36
+ Object.defineProperty(this.globalScope, moduleName, {
37
+ value: moduleRef.metatype,
38
+ configurable: false,
39
+ enumerable: true,
40
+ });
41
+ });
42
+ }
43
+ introspectCollection(moduleRef, moduleKey, collection) {
44
+ var _a;
45
+ const moduleDebugEntry = {};
46
+ moduleRef[collection].forEach(({ token }) => {
47
+ const stringifiedToken = this.stringifyToken(token);
48
+ if (stringifiedToken === application_config_1.ApplicationConfig.name ||
49
+ stringifiedToken === moduleRef.metatype.name ||
50
+ this.globalScope[stringifiedToken]) {
51
+ return;
52
+ }
53
+ // For in REPL auto-complete functionality
54
+ Object.defineProperty(this.globalScope, stringifiedToken, {
55
+ value: token,
56
+ configurable: false,
57
+ enumerable: true,
58
+ });
59
+ if (stringifiedToken === injector_1.ModuleRef.name) {
60
+ return;
61
+ }
62
+ moduleDebugEntry[stringifiedToken] = token;
63
+ });
64
+ this.debugRegistry[moduleKey] = Object.assign(Object.assign({}, (_a = this.debugRegistry) === null || _a === void 0 ? void 0 : _a[moduleKey]), { [collection]: moduleDebugEntry });
65
+ }
66
+ stringifyToken(token) {
67
+ return typeof token !== 'string'
68
+ ? typeof token === 'function'
69
+ ? token.name
70
+ : token === null || token === void 0 ? void 0 : token.toString()
71
+ : token;
72
+ }
73
+ addNativeFunction(NativeFunctionRef) {
74
+ var _a;
75
+ const nativeFunction = new NativeFunctionRef(this);
76
+ const nativeFunctions = [nativeFunction];
77
+ this.nativeFunctions.set(nativeFunction.fnDefinition.name, nativeFunction);
78
+ (_a = nativeFunction.fnDefinition.aliases) === null || _a === void 0 ? void 0 : _a.forEach(aliaseName => {
79
+ const aliasNativeFunction = Object.create(nativeFunction);
80
+ aliasNativeFunction.fnDefinition = {
81
+ name: aliaseName,
82
+ description: aliasNativeFunction.fnDefinition.description,
83
+ signature: aliasNativeFunction.fnDefinition.signature,
84
+ };
85
+ this.nativeFunctions.set(aliaseName, aliasNativeFunction);
86
+ nativeFunctions.push(aliasNativeFunction);
87
+ });
88
+ return nativeFunctions;
89
+ }
90
+ registerFunctionIntoGlobalScope(nativeFunction) {
91
+ // Bind the method to REPL's context:
92
+ this.globalScope[nativeFunction.fnDefinition.name] =
93
+ nativeFunction.action.bind(nativeFunction);
94
+ // Load the help trigger as a `help` getter on each native function:
95
+ const functionBoundRef = this.globalScope[nativeFunction.fnDefinition.name];
96
+ Object.defineProperty(functionBoundRef, 'help', {
97
+ enumerable: false,
98
+ configurable: false,
99
+ get: () =>
100
+ // Dynamically builds the help message as will unlikely to be called
101
+ // several times.
102
+ this.writeToStdout(nativeFunction.makeHelpMessage()),
103
+ });
104
+ }
105
+ initializeNativeFunctions(nativeFunctionsClassRefs) {
106
+ const builtInFunctionsClassRefs = [
107
+ native_functions_1.HelpReplFn,
108
+ native_functions_1.GetReplFn,
109
+ native_functions_1.ResolveReplFn,
110
+ native_functions_1.SelectReplFn,
111
+ native_functions_1.DebugReplFn,
112
+ native_functions_1.MethodsReplFn,
113
+ ];
114
+ builtInFunctionsClassRefs
115
+ .concat(nativeFunctionsClassRefs)
116
+ .forEach(NativeFunction => {
117
+ const nativeFunctions = this.addNativeFunction(NativeFunction);
118
+ nativeFunctions.forEach(nativeFunction => {
119
+ this.registerFunctionIntoGlobalScope(nativeFunction);
120
+ });
121
+ });
122
+ }
123
+ }
124
+ exports.ReplContext = ReplContext;
@@ -0,0 +1,18 @@
1
+ import { Logger } from '@nestjs/common';
2
+ import { ReplContext } from './repl-context';
3
+ import type { ReplFnDefinition } from './repl.interfaces';
4
+ export declare abstract class ReplFunction<ActionParams extends Array<unknown> = Array<unknown>, ActionReturn = any> {
5
+ protected readonly ctx: ReplContext;
6
+ /** Metadata that describes the built-in function itself. */
7
+ abstract fnDefinition: ReplFnDefinition;
8
+ protected readonly logger: Logger;
9
+ constructor(ctx: ReplContext);
10
+ /**
11
+ * Method called when the function is invoked from the REPL by the user.
12
+ */
13
+ abstract action(...args: ActionParams): ActionReturn;
14
+ /**
15
+ * @returns A message displayed by calling `<fnName>.help`
16
+ */
17
+ makeHelpMessage(): string;
18
+ }
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReplFunction = void 0;
4
+ const cli_colors_util_1 = require("@nestjs/common/utils/cli-colors.util");
5
+ class ReplFunction {
6
+ constructor(ctx) {
7
+ this.ctx = ctx;
8
+ this.logger = ctx.logger;
9
+ }
10
+ /**
11
+ * @returns A message displayed by calling `<fnName>.help`
12
+ */
13
+ makeHelpMessage() {
14
+ const { description, name, signature } = this.fnDefinition;
15
+ const fnSignatureWithName = `${name}${signature}`;
16
+ return `${cli_colors_util_1.clc.yellow(description)}\n${cli_colors_util_1.clc.magentaBright('Interface:')} ${cli_colors_util_1.clc.bold(fnSignatureWithName)}\n`;
17
+ }
18
+ }
19
+ exports.ReplFunction = ReplFunction;
@@ -0,0 +1,5 @@
1
+ import { ConsoleLogger } from '@nestjs/common';
2
+ export declare class ReplLogger extends ConsoleLogger {
3
+ private static readonly ignoredContexts;
4
+ log(_message: any, context?: string): void;
5
+ }
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ReplLogger = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const nest_application_1 = require("../nest-application");
6
+ const router_explorer_1 = require("../router/router-explorer");
7
+ const routes_resolver_1 = require("../router/routes-resolver");
8
+ class ReplLogger extends common_1.ConsoleLogger {
9
+ log(_message, context) {
10
+ if (ReplLogger.ignoredContexts.includes(context)) {
11
+ return;
12
+ }
13
+ // eslint-disable-next-line
14
+ return super.log.apply(this, Array.from(arguments));
15
+ }
16
+ }
17
+ exports.ReplLogger = ReplLogger;
18
+ ReplLogger.ignoredContexts = [
19
+ routes_resolver_1.RoutesResolver.name,
20
+ router_explorer_1.RouterExplorer.name,
21
+ nest_application_1.NestApplication.name,
22
+ ];
package/repl/repl.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ /// <reference types="node" />
2
+ import { Type } from '@nestjs/common';
3
+ import * as _repl from 'repl';
4
+ export declare function repl(module: Type): Promise<_repl.REPLServer>;
@@ -0,0 +1,16 @@
1
+ import type { ReplContext } from './repl-context';
2
+ import type { ReplFunction } from './repl-function';
3
+ export declare type ReplFnDefinition = {
4
+ /** Function's name. Note that this should be a valid JavaScript function name. */
5
+ name: string;
6
+ /** Alternative names to the function. */
7
+ aliases?: ReplFnDefinition['name'][];
8
+ /** Function's description to display when `<function>.help` is entered. */
9
+ description: string;
10
+ /**
11
+ * Function's signature following TypeScript _function type expression_ syntax.
12
+ * @example '(token: InjectionToken) => any'
13
+ */
14
+ signature: string;
15
+ };
16
+ export declare type ReplFunctionClass = new (replContext: ReplContext) => ReplFunction;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/repl/repl.js ADDED
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.repl = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const _repl = require("repl");
6
+ const cli_colors_util_1 = require("@nestjs/common/utils/cli-colors.util");
7
+ const nest_factory_1 = require("../nest-factory");
8
+ const constants_1 = require("./constants");
9
+ const repl_context_1 = require("./repl-context");
10
+ const repl_logger_1 = require("./repl-logger");
11
+ const assign_to_object_util_1 = require("./assign-to-object.util");
12
+ async function repl(module) {
13
+ const app = await nest_factory_1.NestFactory.create(module, {
14
+ abortOnError: false,
15
+ logger: new repl_logger_1.ReplLogger(),
16
+ });
17
+ await app.init();
18
+ const replContext = new repl_context_1.ReplContext(app);
19
+ common_1.Logger.log(constants_1.REPL_INITIALIZED_MESSAGE);
20
+ const replServer = _repl.start({
21
+ prompt: cli_colors_util_1.clc.green('> '),
22
+ ignoreUndefined: true,
23
+ });
24
+ (0, assign_to_object_util_1.assignToObject)(replServer.context, replContext.globalScope);
25
+ return replServer;
26
+ }
27
+ exports.repl = repl;