mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
refactor: general refactor reorganize, rename things
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import { Optional } from '../decorators';
|
||||
import { Injectable } from '../decorators/core';
|
||||
import { ArgumentMetadata, BadRequestException } from '../index';
|
||||
import { ValidatorOptions } from '../interfaces/external/validator-options.interface';
|
||||
import { PipeTransform } from '../interfaces/features/pipe-transform.interface';
|
||||
import { loadPackage } from '../utils/load-package.util';
|
||||
import { isNil } from '../utils/shared.utils';
|
||||
import { Injectable } from '../decorators/core/component.decorator';
|
||||
|
||||
export interface ValidationPipeOptions extends ValidatorOptions {
|
||||
transform?: boolean;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { expect } from 'chai';
|
||||
import { Component, MiddlewareFunction, Interceptor, mixin, Injectable } from '../../index';
|
||||
import { Component, Injectable, Interceptor, mixin } from '../../index';
|
||||
|
||||
describe('@Component', () => {
|
||||
@Component()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Constructor } from './merge-with-values.util';
|
||||
import { Injectable } from '../decorators/core';
|
||||
import { NestMiddleware } from '../interfaces/middleware/nest-middleware.interface';
|
||||
import { Injectable } from '../decorators/core/component.decorator';
|
||||
import { Constructor } from './merge-with-values.util';
|
||||
|
||||
export const BindResolveMiddlewareValues = <
|
||||
T extends Constructor<NestMiddleware>
|
||||
|
||||
@@ -12,7 +12,7 @@ import { Module } from '../injector/module';
|
||||
* @param instance The instance which should get the name from
|
||||
*/
|
||||
const getInstanceName = (instance: any) =>
|
||||
(instance && (instance as Type<any>).name);
|
||||
instance && (instance as Type<any>).name;
|
||||
|
||||
/**
|
||||
* Returns the name of the dependency
|
||||
@@ -20,13 +20,15 @@ const getInstanceName = (instance: any) =>
|
||||
* (= injection token). As fallback it returns '+'
|
||||
* @param dependency The dependency whichs name should get displayed
|
||||
*/
|
||||
const getDependencyName = (dependency: InjectorDependency) => getInstanceName(dependency) || dependency || '+';
|
||||
const getDependencyName = (dependency: InjectorDependency) =>
|
||||
getInstanceName(dependency) || dependency || '+';
|
||||
/**
|
||||
* Returns the name of the module
|
||||
* Tries to get the class name. As fallback it returns 'current'.
|
||||
* @param module The module which should get displayed
|
||||
*/
|
||||
const getModuleName = (module: Module) => (module && getInstanceName(module.metatype)) || 'current';
|
||||
const getModuleName = (module: Module) =>
|
||||
(module && getInstanceName(module.metatype)) || 'current';
|
||||
|
||||
export const UNKNOWN_DEPENDENCIES_MESSAGE = (
|
||||
type: string,
|
||||
@@ -45,7 +47,9 @@ export const UNKNOWN_DEPENDENCIES_MESSAGE = (
|
||||
|
||||
message += ` (`;
|
||||
message += dependenciesName.join(', ');
|
||||
message += `). Please make sure that the argument at index [${index}] is available in the ${getModuleName(module)} context.`;
|
||||
message += `). Please make sure that the argument at index [${index}] is available in the ${getModuleName(
|
||||
module,
|
||||
)} context.`;
|
||||
return message;
|
||||
};
|
||||
|
||||
@@ -56,7 +60,7 @@ export const INVALID_MODULE_MESSAGE = (text, scope: string) =>
|
||||
`Nest cannot create the module instance. Often, this is because of a circular dependency between modules. Use forwardRef() to avoid it. (Read more https://docs.nestjs.com/advanced/circular-dependency.) Scope [${scope}]`;
|
||||
|
||||
export const UNKNOWN_EXPORT_MESSAGE = (text, module: string) =>
|
||||
`Nest cannot export a component/module that is not a part of the currently processed module (${module}). Please verify whether each exported unit is available in this particular context.`;
|
||||
`Nest cannot export a provider/module that is not a part of the currently processed module (${module}). Please verify whether each exported unit is available in this particular context.`;
|
||||
|
||||
export const INVALID_CLASS_MESSAGE = (text, value: any) =>
|
||||
`ModuleRef cannot instantiate class (${value} is not constructable).`;
|
||||
|
||||
@@ -44,7 +44,7 @@ export class BaseExceptionFilter<T = any> implements ExceptionFilter<T> {
|
||||
);
|
||||
}
|
||||
|
||||
public isExceptionObject(err): err is Error {
|
||||
public isExceptionObject(err: any): err is Error {
|
||||
return isObject(err) && !!(err as Error).message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,10 @@ export class ExceptionsHandler extends BaseExceptionFilter {
|
||||
this.filters = filters;
|
||||
}
|
||||
|
||||
public invokeCustomFilters(exception, response): boolean {
|
||||
public invokeCustomFilters<T = any>(
|
||||
exception: T,
|
||||
ctx: ArgumentsHost,
|
||||
): boolean {
|
||||
if (isEmpty(this.filters)) return false;
|
||||
|
||||
const filter = this.filters.find(({ exceptionMetatypes }) => {
|
||||
@@ -37,7 +40,7 @@ export class ExceptionsHandler extends BaseExceptionFilter {
|
||||
);
|
||||
return hasMetatype;
|
||||
});
|
||||
filter && filter.func(exception, response);
|
||||
filter && filter.func(exception, ctx);
|
||||
return !!filter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,19 +123,19 @@ export class ExternalContextCreator {
|
||||
return '';
|
||||
}
|
||||
for (const [key, module] of [...this.modulesContainer.entries()]) {
|
||||
if (this.findComponentByClassName(module, className)) {
|
||||
if (this.findProviderByClassName(module, className)) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
public findComponentByClassName(module: Module, className: string): boolean {
|
||||
const { components } = module;
|
||||
const hasComponent = [...components.keys()].some(
|
||||
component => component === className,
|
||||
public findProviderByClassName(module: Module, className: string): boolean {
|
||||
const { providers } = module;
|
||||
const hasProvider = [...providers.keys()].some(
|
||||
provider => provider === className,
|
||||
);
|
||||
return hasComponent;
|
||||
return hasProvider;
|
||||
}
|
||||
|
||||
public exchangeKeysForValues<TMetadata = any>(
|
||||
@@ -211,7 +211,7 @@ export class ExternalContextCreator {
|
||||
);
|
||||
}
|
||||
|
||||
public async transformToResult(resultOrDeffered) {
|
||||
public async transformToResult(resultOrDeffered: any) {
|
||||
if (resultOrDeffered && isFunction(resultOrDeffered.subscribe)) {
|
||||
return resultOrDeffered.toPromise();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { HttpServer } from '@nestjs/common';
|
||||
import { RequestMethod } from '@nestjs/common/enums/request-method.enum';
|
||||
|
||||
export class RouterMethodFactory {
|
||||
public get(target, requestMethod: RequestMethod) {
|
||||
public get(target: HttpServer, requestMethod: RequestMethod): Function {
|
||||
switch (requestMethod) {
|
||||
case RequestMethod.POST:
|
||||
return target.post;
|
||||
|
||||
@@ -24,8 +24,8 @@ export class ContainerScanner {
|
||||
contextModule: Partial<Module>,
|
||||
): TResult {
|
||||
const dependencies = new Map([
|
||||
...contextModule.components,
|
||||
...contextModule.routes,
|
||||
...contextModule.providers,
|
||||
...contextModule.controllers,
|
||||
...contextModule.injectables,
|
||||
]);
|
||||
const name = isFunction(metatypeOrToken)
|
||||
@@ -44,8 +44,8 @@ export class ContainerScanner {
|
||||
}
|
||||
const modules = this.container.getModules();
|
||||
const initialValue = {
|
||||
components: [],
|
||||
routes: [],
|
||||
providers: [],
|
||||
controllers: [],
|
||||
injectables: [],
|
||||
};
|
||||
const merge = <T = any>(
|
||||
@@ -55,8 +55,8 @@ export class ContainerScanner {
|
||||
|
||||
this.flatContainer = ([...modules.values()].reduce(
|
||||
(current, next) => ({
|
||||
components: merge(current.components, next.components),
|
||||
routes: merge(current.routes, next.routes),
|
||||
providers: merge(current.providers, next.providers),
|
||||
controllers: merge(current.controllers, next.controllers),
|
||||
injectables: merge(current.injectables, next.injectables),
|
||||
}),
|
||||
initialValue,
|
||||
|
||||
@@ -27,7 +27,7 @@ export class NestContainer {
|
||||
private applicationRef: any;
|
||||
|
||||
constructor(
|
||||
private readonly _applicationConfig: ApplicationConfig = void 0,
|
||||
private readonly _applicationConfig: ApplicationConfig = undefined,
|
||||
) {}
|
||||
|
||||
get applicationConfig(): ApplicationConfig | undefined {
|
||||
@@ -120,15 +120,15 @@ export class NestContainer {
|
||||
module.addRelatedModule(related);
|
||||
}
|
||||
|
||||
public addComponent(component: Type<any>, token: string): string {
|
||||
if (!component) {
|
||||
public addProvider(provider: Type<any>, token: string): string {
|
||||
if (!provider) {
|
||||
throw new CircularDependencyException();
|
||||
}
|
||||
if (!this.modules.has(token)) {
|
||||
throw new UnknownModuleException();
|
||||
}
|
||||
const module = this.modules.get(token);
|
||||
return module.addComponent(component);
|
||||
return module.addProvider(provider);
|
||||
}
|
||||
|
||||
public addInjectable(injectable: Type<any>, token: string) {
|
||||
@@ -139,12 +139,12 @@ export class NestContainer {
|
||||
module.addInjectable(injectable);
|
||||
}
|
||||
|
||||
public addExportedComponent(exportedComponent: Type<any>, token: string) {
|
||||
public addExportedProvider(provider: Type<any>, token: string) {
|
||||
if (!this.modules.has(token)) {
|
||||
throw new UnknownModuleException();
|
||||
}
|
||||
const module = this.modules.get(token);
|
||||
module.addExportedComponent(exportedComponent);
|
||||
module.addExportedProvider(provider);
|
||||
}
|
||||
|
||||
public addController(controller: Type<any>, token: string) {
|
||||
@@ -152,7 +152,7 @@ export class NestContainer {
|
||||
throw new UnknownModuleException();
|
||||
}
|
||||
const module = this.modules.get(token);
|
||||
module.addRoute(controller);
|
||||
module.addController(controller);
|
||||
}
|
||||
|
||||
public clear() {
|
||||
|
||||
@@ -84,12 +84,12 @@ export class Injector {
|
||||
);
|
||||
}
|
||||
|
||||
public async loadInstanceOfRoute(
|
||||
public async loadInstanceOfController(
|
||||
wrapper: InstanceWrapper<Controller>,
|
||||
module: Module,
|
||||
) {
|
||||
const routes = module.routes;
|
||||
await this.loadInstance<Controller>(wrapper, routes, module);
|
||||
const controllers = module.controllers;
|
||||
await this.loadInstance<Controller>(wrapper, controllers, module);
|
||||
}
|
||||
|
||||
public async loadInstanceOfInjectable(
|
||||
@@ -121,8 +121,8 @@ export class Injector {
|
||||
wrapper: InstanceWrapper<Injectable>,
|
||||
module: Module,
|
||||
) {
|
||||
const components = module.components;
|
||||
await this.loadInstance<Injectable>(wrapper, components, module);
|
||||
const providers = module.providers;
|
||||
await this.loadInstance<Injectable>(wrapper, providers, module);
|
||||
}
|
||||
|
||||
public applyDoneHook<T>(wrapper: InstanceWrapper<T>): () => void {
|
||||
@@ -227,7 +227,11 @@ export class Injector {
|
||||
module: Module,
|
||||
) {
|
||||
if (isUndefined(param)) {
|
||||
throw new UndefinedDependencyException(wrapper.name, dependencyContext, module);
|
||||
throw new UndefinedDependencyException(
|
||||
wrapper.name,
|
||||
dependencyContext,
|
||||
module,
|
||||
);
|
||||
}
|
||||
const token = this.resolveParamToken(wrapper, param);
|
||||
return this.resolveComponentInstance<T>(
|
||||
@@ -255,9 +259,9 @@ export class Injector {
|
||||
dependencyContext: InjectorDependencyContext,
|
||||
wrapper: InstanceWrapper<T>,
|
||||
) {
|
||||
const components = module.components;
|
||||
const providers = module.providers;
|
||||
const instanceWrapper = await this.lookupComponent(
|
||||
components,
|
||||
providers,
|
||||
module,
|
||||
{ ...dependencyContext, name },
|
||||
wrapper,
|
||||
@@ -272,7 +276,7 @@ export class Injector {
|
||||
}
|
||||
|
||||
public async lookupComponent<T = any>(
|
||||
components: Map<string, any>,
|
||||
providers: Map<string, any>,
|
||||
module: Module,
|
||||
dependencyContext: InjectorDependencyContext,
|
||||
wrapper: InstanceWrapper<T>,
|
||||
@@ -280,7 +284,7 @@ export class Injector {
|
||||
const { name } = dependencyContext;
|
||||
const scanInExports = () =>
|
||||
this.lookupComponentInExports(dependencyContext, module, wrapper);
|
||||
return components.has(name) ? components.get(name) : scanInExports();
|
||||
return providers.has(name) ? providers.get(name) : scanInExports();
|
||||
}
|
||||
|
||||
public async lookupComponentInExports<T = any>(
|
||||
@@ -293,7 +297,11 @@ export class Injector {
|
||||
dependencyContext.name,
|
||||
);
|
||||
if (isNil(instanceWrapper)) {
|
||||
throw new UnknownDependenciesException(wrapper.name, dependencyContext, module);
|
||||
throw new UnknownDependenciesException(
|
||||
wrapper.name,
|
||||
dependencyContext,
|
||||
module,
|
||||
);
|
||||
}
|
||||
return instanceWrapper;
|
||||
}
|
||||
@@ -312,8 +320,8 @@ export class Injector {
|
||||
continue;
|
||||
}
|
||||
moduleRegistry.push(relatedModule.id);
|
||||
const { components, exports } = relatedModule;
|
||||
if (!exports.has(name) || !components.has(name)) {
|
||||
const { providers, exports } = relatedModule;
|
||||
if (!exports.has(name) || !providers.has(name)) {
|
||||
const instanceRef = await this.lookupComponentInRelatedModules(
|
||||
relatedModule,
|
||||
name,
|
||||
@@ -324,7 +332,7 @@ export class Injector {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
componentRef = components.get(name);
|
||||
componentRef = providers.get(name);
|
||||
if (!componentRef.isResolved && !componentRef.forwardRef) {
|
||||
await this.loadInstanceOfComponent(componentRef, relatedModule);
|
||||
break;
|
||||
|
||||
@@ -21,18 +21,18 @@ export class InstanceLoader {
|
||||
|
||||
private createPrototypes(modules: Map<string, Module>) {
|
||||
modules.forEach(module => {
|
||||
this.createPrototypesOfComponents(module);
|
||||
this.createPrototypesOfProviders(module);
|
||||
this.createPrototypesOfInjectables(module);
|
||||
this.createPrototypesOfRoutes(module);
|
||||
this.createPrototypesOfControllers(module);
|
||||
});
|
||||
}
|
||||
|
||||
private async createInstances(modules: Map<string, Module>) {
|
||||
await Promise.all(
|
||||
[...modules.values()].map(async module => {
|
||||
await this.createInstancesOfComponents(module);
|
||||
await this.createInstancesOfProviders(module);
|
||||
await this.createInstancesOfInjectables(module);
|
||||
await this.createInstancesOfRoutes(module);
|
||||
await this.createInstancesOfControllers(module);
|
||||
|
||||
const { name } = module.metatype;
|
||||
this.logger.log(MODULE_INIT_MESSAGE`${name}`);
|
||||
@@ -40,33 +40,36 @@ export class InstanceLoader {
|
||||
);
|
||||
}
|
||||
|
||||
private createPrototypesOfComponents(module: Module) {
|
||||
module.components.forEach(wrapper => {
|
||||
private createPrototypesOfProviders(module: Module) {
|
||||
module.providers.forEach(wrapper => {
|
||||
this.injector.loadPrototypeOfInstance<Injectable>(
|
||||
wrapper,
|
||||
module.components,
|
||||
module.providers,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private async createInstancesOfComponents(module: Module) {
|
||||
private async createInstancesOfProviders(module: Module) {
|
||||
await Promise.all(
|
||||
[...module.components.values()].map(
|
||||
async wrapper => this.injector.loadInstanceOfComponent(wrapper, module),
|
||||
[...module.providers.values()].map(async wrapper =>
|
||||
this.injector.loadInstanceOfComponent(wrapper, module),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
private createPrototypesOfRoutes(module: Module) {
|
||||
module.routes.forEach(wrapper => {
|
||||
this.injector.loadPrototypeOfInstance<Controller>(wrapper, module.routes);
|
||||
private createPrototypesOfControllers(module: Module) {
|
||||
module.controllers.forEach(wrapper => {
|
||||
this.injector.loadPrototypeOfInstance<Controller>(
|
||||
wrapper,
|
||||
module.controllers,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
private async createInstancesOfRoutes(module: Module) {
|
||||
private async createInstancesOfControllers(module: Module) {
|
||||
await Promise.all(
|
||||
[...module.routes.values()].map(
|
||||
async wrapper => this.injector.loadInstanceOfRoute(wrapper, module),
|
||||
[...module.controllers.values()].map(async wrapper =>
|
||||
this.injector.loadInstanceOfController(wrapper, module),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -82,8 +85,8 @@ export class InstanceLoader {
|
||||
|
||||
private async createInstancesOfInjectables(module: Module) {
|
||||
await Promise.all(
|
||||
[...module.injectables.values()].map(
|
||||
async wrapper => this.injector.loadInstanceOfInjectable(wrapper, module),
|
||||
[...module.injectables.values()].map(async wrapper =>
|
||||
this.injector.loadInstanceOfInjectable(wrapper, module),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -24,18 +24,18 @@ import { ModuleRef } from './module-ref';
|
||||
import { ModulesContainer } from './modules-container';
|
||||
import { HTTP_SERVER_REF } from './tokens';
|
||||
|
||||
export interface CustomComponent {
|
||||
export interface CustomProvider {
|
||||
provide: any;
|
||||
name: string;
|
||||
}
|
||||
export type OpaqueToken = string | symbol | object | Type<any>;
|
||||
export type CustomClass = CustomComponent & { useClass: Type<any> };
|
||||
export type CustomFactory = CustomComponent & {
|
||||
export type CustomClass = CustomProvider & { useClass: Type<any> };
|
||||
export type CustomFactory = CustomProvider & {
|
||||
useFactory: (...args) => any;
|
||||
inject?: OpaqueToken[];
|
||||
};
|
||||
export type CustomValue = CustomComponent & { useValue: any };
|
||||
export type ComponentMetatype =
|
||||
export type CustomValue = CustomProvider & { useValue: any };
|
||||
export type ProviderMetatype =
|
||||
| Type<Injectable>
|
||||
| CustomFactory
|
||||
| CustomValue
|
||||
@@ -44,9 +44,12 @@ export type ComponentMetatype =
|
||||
export class Module {
|
||||
private readonly _id: string;
|
||||
private readonly _relatedModules = new Set<Module>();
|
||||
private readonly _components = new Map<any, InstanceWrapper<Injectable>>();
|
||||
private readonly _providers = new Map<any, InstanceWrapper<Injectable>>();
|
||||
private readonly _injectables = new Map<any, InstanceWrapper<Injectable>>();
|
||||
private readonly _routes = new Map<string, InstanceWrapper<Controller>>();
|
||||
private readonly _controllers = new Map<
|
||||
string,
|
||||
InstanceWrapper<Controller>
|
||||
>();
|
||||
private readonly _exports = new Set<string>();
|
||||
|
||||
constructor(
|
||||
@@ -54,7 +57,7 @@ export class Module {
|
||||
private readonly _scope: Type<any>[],
|
||||
private readonly container: NestContainer,
|
||||
) {
|
||||
this.addCoreInjectables(container);
|
||||
this.addCoreProviders(container);
|
||||
this._id = randomStringGenerator();
|
||||
}
|
||||
|
||||
@@ -70,16 +73,30 @@ export class Module {
|
||||
return this._relatedModules;
|
||||
}
|
||||
|
||||
get providers(): Map<string, InstanceWrapper<Injectable>> {
|
||||
return this._providers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Left for backward-compatibility reasons
|
||||
*/
|
||||
get components(): Map<string, InstanceWrapper<Injectable>> {
|
||||
return this._components;
|
||||
return this._providers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Left for backward-compatibility reasons
|
||||
*/
|
||||
get routes(): Map<string, InstanceWrapper<Controller>> {
|
||||
return this._controllers;
|
||||
}
|
||||
|
||||
get injectables(): Map<string, InstanceWrapper<Injectable>> {
|
||||
return this._injectables;
|
||||
}
|
||||
|
||||
get routes(): Map<string, InstanceWrapper<Controller>> {
|
||||
return this._routes;
|
||||
get controllers(): Map<string, InstanceWrapper<Controller>> {
|
||||
return this._controllers;
|
||||
}
|
||||
|
||||
get exports(): Set<string> {
|
||||
@@ -87,10 +104,10 @@ export class Module {
|
||||
}
|
||||
|
||||
get instance(): NestModule {
|
||||
if (!this._components.has(this._metatype.name)) {
|
||||
if (!this._providers.has(this._metatype.name)) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
const module = this._components.get(this._metatype.name);
|
||||
const module = this._providers.get(this._metatype.name);
|
||||
return module.instance as NestModule;
|
||||
}
|
||||
|
||||
@@ -98,8 +115,8 @@ export class Module {
|
||||
return this._metatype;
|
||||
}
|
||||
|
||||
public addCoreInjectables(container: NestContainer) {
|
||||
this.addModuleAsComponent();
|
||||
public addCoreProviders(container: NestContainer) {
|
||||
this.addModuleAsProvider();
|
||||
this.addModuleRef();
|
||||
this.addReflector(container.getReflector());
|
||||
this.addApplicationRef(container.getApplicationRef());
|
||||
@@ -110,7 +127,7 @@ export class Module {
|
||||
|
||||
public addModuleRef() {
|
||||
const moduleRef = this.createModuleRefMetatype();
|
||||
this._components.set(ModuleRef.name, {
|
||||
this._providers.set(ModuleRef.name, {
|
||||
name: ModuleRef.name,
|
||||
metatype: ModuleRef as any,
|
||||
isResolved: true,
|
||||
@@ -118,8 +135,8 @@ export class Module {
|
||||
});
|
||||
}
|
||||
|
||||
public addModuleAsComponent() {
|
||||
this._components.set(this._metatype.name, {
|
||||
public addModuleAsProvider() {
|
||||
this._providers.set(this._metatype.name, {
|
||||
name: this._metatype.name,
|
||||
metatype: this._metatype,
|
||||
isResolved: false,
|
||||
@@ -128,7 +145,7 @@ export class Module {
|
||||
}
|
||||
|
||||
public addReflector(reflector: Reflector) {
|
||||
this._components.set(Reflector.name, {
|
||||
this._providers.set(Reflector.name, {
|
||||
name: Reflector.name,
|
||||
metatype: Reflector,
|
||||
isResolved: true,
|
||||
@@ -137,7 +154,7 @@ export class Module {
|
||||
}
|
||||
|
||||
public addApplicationRef(applicationRef: any) {
|
||||
this._components.set(HTTP_SERVER_REF, {
|
||||
this._providers.set(HTTP_SERVER_REF, {
|
||||
name: HTTP_SERVER_REF,
|
||||
metatype: {} as any,
|
||||
isResolved: true,
|
||||
@@ -148,7 +165,7 @@ export class Module {
|
||||
public addExternalContextCreator(
|
||||
externalContextCreator: ExternalContextCreator,
|
||||
) {
|
||||
this._components.set(ExternalContextCreator.name, {
|
||||
this._providers.set(ExternalContextCreator.name, {
|
||||
name: ExternalContextCreator.name,
|
||||
metatype: ExternalContextCreator,
|
||||
isResolved: true,
|
||||
@@ -157,7 +174,7 @@ export class Module {
|
||||
}
|
||||
|
||||
public addModulesContainer(modulesContainer: ModulesContainer) {
|
||||
this._components.set(ModulesContainer.name, {
|
||||
this._providers.set(ModulesContainer.name, {
|
||||
name: ModulesContainer.name,
|
||||
metatype: ModulesContainer,
|
||||
isResolved: true,
|
||||
@@ -166,7 +183,7 @@ export class Module {
|
||||
}
|
||||
|
||||
public addApplicationRefHost(applicationRefHost: ApplicationReferenceHost) {
|
||||
this._components.set(ApplicationReferenceHost.name, {
|
||||
this._providers.set(ApplicationReferenceHost.name, {
|
||||
name: ApplicationReferenceHost.name,
|
||||
metatype: ApplicationReferenceHost,
|
||||
isResolved: true,
|
||||
@@ -174,7 +191,7 @@ export class Module {
|
||||
});
|
||||
}
|
||||
|
||||
public addInjectable(injectable: Type<Injectable>) {
|
||||
public addInjectable<T = Injectable>(injectable: Type<T>) {
|
||||
if (this.isCustomProvider(injectable)) {
|
||||
return this.addCustomProvider(injectable, this._injectables);
|
||||
}
|
||||
@@ -186,63 +203,63 @@ export class Module {
|
||||
});
|
||||
}
|
||||
|
||||
public addComponent(component: ComponentMetatype): string {
|
||||
if (this.isCustomProvider(component)) {
|
||||
return this.addCustomProvider(component, this._components);
|
||||
public addProvider(provider: ProviderMetatype): string {
|
||||
if (this.isCustomProvider(provider)) {
|
||||
return this.addCustomProvider(provider, this._providers);
|
||||
}
|
||||
this._components.set((component as Type<Injectable>).name, {
|
||||
name: (component as Type<Injectable>).name,
|
||||
metatype: component as Type<Injectable>,
|
||||
this._providers.set((provider as Type<Injectable>).name, {
|
||||
name: (provider as Type<Injectable>).name,
|
||||
metatype: provider as Type<Injectable>,
|
||||
instance: null,
|
||||
isResolved: false,
|
||||
});
|
||||
return (component as Type<Injectable>).name;
|
||||
return (provider as Type<Injectable>).name;
|
||||
}
|
||||
|
||||
public isCustomProvider(
|
||||
component: ComponentMetatype,
|
||||
): component is CustomClass | CustomFactory | CustomValue {
|
||||
return !isNil((component as CustomComponent).provide);
|
||||
provider: ProviderMetatype,
|
||||
): provider is CustomClass | CustomFactory | CustomValue {
|
||||
return !isNil((provider as CustomProvider).provide);
|
||||
}
|
||||
|
||||
public addCustomProvider(
|
||||
component: CustomFactory | CustomValue | CustomClass,
|
||||
provider: CustomFactory | CustomValue | CustomClass,
|
||||
collection: Map<string, any>,
|
||||
): string {
|
||||
const { provide } = component;
|
||||
const { provide } = provider;
|
||||
const name = isFunction(provide) ? provide.name : provide;
|
||||
const componentWithName = {
|
||||
...component,
|
||||
const providerNamePair = {
|
||||
...provider,
|
||||
name,
|
||||
};
|
||||
if (this.isCustomClass(componentWithName))
|
||||
this.addCustomClass(componentWithName, collection);
|
||||
else if (this.isCustomValue(componentWithName))
|
||||
this.addCustomValue(componentWithName, collection);
|
||||
else if (this.isCustomFactory(componentWithName))
|
||||
this.addCustomFactory(componentWithName, collection);
|
||||
if (this.isCustomClass(providerNamePair))
|
||||
this.addCustomClass(providerNamePair, collection);
|
||||
else if (this.isCustomValue(providerNamePair))
|
||||
this.addCustomValue(providerNamePair, collection);
|
||||
else if (this.isCustomFactory(providerNamePair))
|
||||
this.addCustomFactory(providerNamePair, collection);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
public isCustomClass(component): component is CustomClass {
|
||||
return !isUndefined((component as CustomClass).useClass);
|
||||
public isCustomClass(provider): provider is CustomClass {
|
||||
return !isUndefined((provider as CustomClass).useClass);
|
||||
}
|
||||
|
||||
public isCustomValue(component): component is CustomValue {
|
||||
return !isUndefined((component as CustomValue).useValue);
|
||||
public isCustomValue(provider): provider is CustomValue {
|
||||
return !isUndefined((provider as CustomValue).useValue);
|
||||
}
|
||||
|
||||
public isCustomFactory(component): component is CustomFactory {
|
||||
return !isUndefined((component as CustomFactory).useFactory);
|
||||
public isCustomFactory(provider): provider is CustomFactory {
|
||||
return !isUndefined((provider as CustomFactory).useFactory);
|
||||
}
|
||||
|
||||
public isDynamicModule(exported): exported is DynamicModule {
|
||||
return exported && exported.module;
|
||||
}
|
||||
|
||||
public addCustomClass(component: CustomClass, collection: Map<string, any>) {
|
||||
const { name, useClass } = component;
|
||||
public addCustomClass(provider: CustomClass, collection: Map<string, any>) {
|
||||
const { name, useClass } = provider;
|
||||
collection.set(name, {
|
||||
name,
|
||||
metatype: useClass,
|
||||
@@ -251,8 +268,8 @@ export class Module {
|
||||
});
|
||||
}
|
||||
|
||||
public addCustomValue(component: CustomValue, collection: Map<string, any>) {
|
||||
const { name, useValue: value } = component;
|
||||
public addCustomValue(provider: CustomValue, collection: Map<string, any>) {
|
||||
const { name, useValue: value } = provider;
|
||||
collection.set(name, {
|
||||
name,
|
||||
metatype: null,
|
||||
@@ -264,10 +281,10 @@ export class Module {
|
||||
}
|
||||
|
||||
public addCustomFactory(
|
||||
component: CustomFactory,
|
||||
provider: CustomFactory,
|
||||
collection: Map<string, any>,
|
||||
) {
|
||||
const { name, useFactory: factory, inject } = component;
|
||||
const { name, useFactory: factory, inject } = provider;
|
||||
collection.set(name, {
|
||||
name,
|
||||
metatype: factory as any,
|
||||
@@ -278,27 +295,27 @@ export class Module {
|
||||
});
|
||||
}
|
||||
|
||||
public addExportedComponent(
|
||||
exportedComponent: ComponentMetatype | string | DynamicModule,
|
||||
public addExportedProvider(
|
||||
provider: ProviderMetatype | string | DynamicModule,
|
||||
) {
|
||||
const addExportedUnit = (token: string) =>
|
||||
this._exports.add(this.validateExportedProvider(token));
|
||||
|
||||
if (this.isCustomProvider(exportedComponent as any)) {
|
||||
return this.addCustomExportedComponent(exportedComponent as any);
|
||||
} else if (isString(exportedComponent)) {
|
||||
return addExportedUnit(exportedComponent);
|
||||
} else if (this.isDynamicModule(exportedComponent)) {
|
||||
const { module } = exportedComponent;
|
||||
if (this.isCustomProvider(provider as any)) {
|
||||
return this.addCustomExportedProvider(provider as any);
|
||||
} else if (isString(provider)) {
|
||||
return addExportedUnit(provider);
|
||||
} else if (this.isDynamicModule(provider)) {
|
||||
const { module } = provider;
|
||||
return addExportedUnit(module.name);
|
||||
}
|
||||
addExportedUnit(exportedComponent.name);
|
||||
addExportedUnit(provider.name);
|
||||
}
|
||||
|
||||
public addCustomExportedComponent(
|
||||
exportedComponent: CustomFactory | CustomValue | CustomClass,
|
||||
public addCustomExportedProvider(
|
||||
provider: CustomFactory | CustomValue | CustomClass,
|
||||
) {
|
||||
const provide = exportedComponent.provide;
|
||||
const provide = provider.provide;
|
||||
if (isString(provide) || isSymbol(provide)) {
|
||||
return this._exports.add(this.validateExportedProvider(provide));
|
||||
}
|
||||
@@ -306,7 +323,7 @@ export class Module {
|
||||
}
|
||||
|
||||
public validateExportedProvider(token: string) {
|
||||
if (this._components.has(token)) {
|
||||
if (this._providers.has(token)) {
|
||||
return token;
|
||||
}
|
||||
const importedArray = [...this._relatedModules.values()];
|
||||
@@ -323,22 +340,22 @@ export class Module {
|
||||
return token;
|
||||
}
|
||||
|
||||
public addRoute(route: Type<Controller>) {
|
||||
this._routes.set(route.name, {
|
||||
name: route.name,
|
||||
metatype: route,
|
||||
public addController(controller: Type<Controller>) {
|
||||
this._controllers.set(controller.name, {
|
||||
name: controller.name,
|
||||
metatype: controller,
|
||||
instance: null,
|
||||
isResolved: false,
|
||||
});
|
||||
}
|
||||
|
||||
public addRelatedModule(relatedModule) {
|
||||
this._relatedModules.add(relatedModule);
|
||||
public addRelatedModule(module: any) {
|
||||
this._relatedModules.add(module);
|
||||
}
|
||||
|
||||
public replace(toReplace, options) {
|
||||
if (options.isComponent) {
|
||||
return this.addComponent({ provide: toReplace, ...options });
|
||||
public replace(toReplace: string | symbol | Type<any>, options: any) {
|
||||
if (options.isProvider) {
|
||||
return this.addProvider({ provide: toReplace, ...options });
|
||||
}
|
||||
this.addInjectable({
|
||||
provide: toReplace,
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { HttpServer } from '@nestjs/common';
|
||||
import { RequestMethod } from '@nestjs/common/enums/request-method.enum';
|
||||
import { MiddlewareConfiguration, RouteInfo } from '@nestjs/common/interfaces/middleware/middleware-configuration.interface';
|
||||
import {
|
||||
MiddlewareConfiguration,
|
||||
RouteInfo,
|
||||
} from '@nestjs/common/interfaces/middleware/middleware-configuration.interface';
|
||||
import { NestMiddleware } from '@nestjs/common/interfaces/middleware/nest-middleware.interface';
|
||||
import { NestModule } from '@nestjs/common/interfaces/modules/nest-module.interface';
|
||||
import { Type } from '@nestjs/common/interfaces/type.interface';
|
||||
@@ -63,13 +66,15 @@ export class MiddlewareModule {
|
||||
instance: NestModule,
|
||||
module: string,
|
||||
) {
|
||||
if (!instance.configure) return;
|
||||
|
||||
if (!instance.configure) {
|
||||
return;
|
||||
}
|
||||
const middlewareBuilder = new MiddlewareBuilder(this.routesMapper);
|
||||
instance.configure(middlewareBuilder);
|
||||
|
||||
if (!(middlewareBuilder instanceof MiddlewareBuilder)) return;
|
||||
|
||||
if (!(middlewareBuilder instanceof MiddlewareBuilder)) {
|
||||
return;
|
||||
}
|
||||
const config = middlewareBuilder.build();
|
||||
middlewareContainer.addConfig(config, module);
|
||||
}
|
||||
|
||||
@@ -80,11 +80,11 @@ export class NestApplicationContext implements INestApplicationContext {
|
||||
}
|
||||
|
||||
protected async callModuleInitHook(module: Module): Promise<any> {
|
||||
const components = [...module.components];
|
||||
// The Module (class) instance is the first element of the components array
|
||||
const providers = [...module.providers];
|
||||
// Module (class) instance is the first element of the providers array
|
||||
// Lifecycle hook has to be called once all classes are properly initialized
|
||||
const [_, { instance: moduleClassInstance }] = components.shift();
|
||||
const instances = [...module.routes, ...components];
|
||||
const [_, { instance: moduleClassInstance }] = providers.shift();
|
||||
const instances = [...module.controllers, ...providers];
|
||||
|
||||
await Promise.all(
|
||||
iterate(instances)
|
||||
@@ -110,11 +110,11 @@ export class NestApplicationContext implements INestApplicationContext {
|
||||
}
|
||||
|
||||
protected async callModuleDestroyHook(module: Module): Promise<any> {
|
||||
const components = [...module.components];
|
||||
// The Module (class) instance is the first element of the components array
|
||||
const providers = [...module.providers];
|
||||
// Module (class) instance is the first element of the providers array
|
||||
// Lifecycle hook has to be called once all classes are properly destroyed
|
||||
const [_, { instance: moduleClassInstance }] = components.shift();
|
||||
const instances = [...module.routes, ...components];
|
||||
const [_, { instance: moduleClassInstance }] = providers.shift();
|
||||
const instances = [...module.controllers, ...providers];
|
||||
|
||||
await Promise.all(
|
||||
iterate(instances)
|
||||
@@ -143,9 +143,9 @@ export class NestApplicationContext implements INestApplicationContext {
|
||||
}
|
||||
|
||||
protected async callModuleBootstrapHook(module: Module): Promise<any> {
|
||||
const components = [...module.components];
|
||||
const [_, { instance: moduleClassInstance }] = components.shift();
|
||||
const instances = [...module.routes, ...components];
|
||||
const providers = [...module.providers];
|
||||
const [_, { instance: moduleClassInstance }] = providers.shift();
|
||||
const instances = [...module.controllers, ...providers];
|
||||
|
||||
await Promise.all(
|
||||
iterate(instances)
|
||||
|
||||
@@ -38,12 +38,12 @@ export class RoutesResolver implements Resolver {
|
||||
|
||||
public resolve(appInstance, basePath: string) {
|
||||
const modules = this.container.getModules();
|
||||
modules.forEach(({ routes, metatype }, moduleName) => {
|
||||
modules.forEach(({ controllers, metatype }, moduleName) => {
|
||||
let path = metatype
|
||||
? Reflect.getMetadata(MODULE_PATH, metatype)
|
||||
: undefined;
|
||||
path = path ? path + basePath : basePath;
|
||||
this.registerRouters(routes, moduleName, path, appInstance);
|
||||
this.registerRouters(controllers, moduleName, path, appInstance);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -75,11 +75,7 @@ export class RoutesResolver implements Resolver {
|
||||
const url = applicationRef.getRequestUrl(req);
|
||||
throw new NotFoundException(`Cannot ${method} ${url}`);
|
||||
};
|
||||
const handler = this.routerExceptionsFilter.create(
|
||||
{},
|
||||
callback,
|
||||
undefined,
|
||||
);
|
||||
const handler = this.routerExceptionsFilter.create({}, callback, undefined);
|
||||
const proxy = this.routerProxy.createProxy(callback, handler);
|
||||
applicationRef.setNotFoundHandler &&
|
||||
applicationRef.setNotFoundHandler(proxy);
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { DynamicModule, ForwardReference } from '@nestjs/common';
|
||||
import { DynamicModule, ForwardReference, Provider } from '@nestjs/common';
|
||||
import {
|
||||
EXCEPTION_FILTERS_METADATA,
|
||||
GATEWAY_MIDDLEWARES,
|
||||
GUARDS_METADATA,
|
||||
INTERCEPTORS_METADATA,
|
||||
METADATA,
|
||||
PIPES_METADATA,
|
||||
ROUTE_ARGS_METADATA,
|
||||
} from '@nestjs/common/constants';
|
||||
import {
|
||||
ClassProvider,
|
||||
FactoryProvider,
|
||||
ValueProvider,
|
||||
} from '@nestjs/common/interfaces';
|
||||
import { Controller } from '@nestjs/common/interfaces/controllers/controller.interface';
|
||||
import { Injectable } from '@nestjs/common/interfaces/injectable.interface';
|
||||
import { Type } from '@nestjs/common/interfaces/type.interface';
|
||||
@@ -48,14 +52,14 @@ export class DependenciesScanner {
|
||||
scope: Type<any>[] = [],
|
||||
ctxRegistry: (ForwardReference | DynamicModule | Type<any>)[] = [],
|
||||
) {
|
||||
await this.storeModule(module, scope);
|
||||
await this.insertModule(module, scope);
|
||||
ctxRegistry.push(module);
|
||||
|
||||
if (this.isForwardReference(module)) {
|
||||
module = (module as ForwardReference).forwardRef();
|
||||
}
|
||||
const modules = !this.isDynamicModule(module as Type<any> | DynamicModule)
|
||||
? this.reflectMetadata(module, METADATA.MODULES)
|
||||
? this.reflectMetadata(module as Type<any>, METADATA.MODULES)
|
||||
: [
|
||||
...this.reflectMetadata(
|
||||
(module as DynamicModule).module,
|
||||
@@ -76,7 +80,7 @@ export class DependenciesScanner {
|
||||
}
|
||||
}
|
||||
|
||||
public async storeModule(module: any, scope: Type<any>[]) {
|
||||
public async insertModule(module: any, scope: Type<any>[]) {
|
||||
if (module && module.forwardRef) {
|
||||
return this.container.addModule(module.forwardRef(), scope);
|
||||
}
|
||||
@@ -88,7 +92,7 @@ export class DependenciesScanner {
|
||||
|
||||
for (const [token, { metatype }] of modules) {
|
||||
await this.reflectRelatedModules(metatype, token, metatype.name);
|
||||
this.reflectComponents(metatype, token);
|
||||
this.reflectProviders(metatype, token);
|
||||
this.reflectControllers(metatype, token);
|
||||
this.reflectExports(metatype, token);
|
||||
}
|
||||
@@ -111,12 +115,12 @@ export class DependenciesScanner {
|
||||
),
|
||||
];
|
||||
for (const related of modules) {
|
||||
await this.storeRelatedModule(related, token, context);
|
||||
await this.insertRelatedModule(related, token, context);
|
||||
}
|
||||
}
|
||||
|
||||
public reflectComponents(module: Type<any>, token: string) {
|
||||
const components = [
|
||||
public reflectProviders(module: Type<any>, token: string) {
|
||||
const providers = [
|
||||
...this.reflectMetadata(module, METADATA.COMPONENTS),
|
||||
...this.container.getDynamicMetadataByToken(
|
||||
token,
|
||||
@@ -127,17 +131,12 @@ export class DependenciesScanner {
|
||||
METADATA.PROVIDERS as 'providers',
|
||||
),
|
||||
];
|
||||
components.forEach(component => {
|
||||
this.storeComponent(component, token);
|
||||
this.reflectComponentMetadata(component, token);
|
||||
this.reflectDynamicMetadata(component, token);
|
||||
providers.forEach(provider => {
|
||||
this.insertProvider(provider, token);
|
||||
this.reflectDynamicMetadata(provider, token);
|
||||
});
|
||||
}
|
||||
|
||||
public reflectComponentMetadata(component: Type<Injectable>, token: string) {
|
||||
this.reflectGatewaysMiddleware(component, token);
|
||||
}
|
||||
|
||||
public reflectControllers(module: Type<any>, token: string) {
|
||||
const routes = [
|
||||
...this.reflectMetadata(module, METADATA.CONTROLLERS),
|
||||
@@ -147,7 +146,7 @@ export class DependenciesScanner {
|
||||
),
|
||||
];
|
||||
routes.forEach(route => {
|
||||
this.storeRoute(route, token);
|
||||
this.insertController(route, token);
|
||||
this.reflectDynamicMetadata(route, token);
|
||||
});
|
||||
}
|
||||
@@ -171,16 +170,11 @@ export class DependenciesScanner {
|
||||
METADATA.EXPORTS as 'exports',
|
||||
),
|
||||
];
|
||||
exports.forEach(exportedComponent =>
|
||||
this.storeExportedComponent(exportedComponent, token),
|
||||
exports.forEach(exportedProvider =>
|
||||
this.insertExportedProvider(exportedProvider, token),
|
||||
);
|
||||
}
|
||||
|
||||
public reflectGatewaysMiddleware(component: Type<Injectable>, token: string) {
|
||||
const middleware = this.reflectMetadata(component, GATEWAY_MIDDLEWARES);
|
||||
middleware.forEach(ware => this.storeComponent(ware, token));
|
||||
}
|
||||
|
||||
public reflectInjectables(
|
||||
component: Type<Injectable>,
|
||||
token: string,
|
||||
@@ -202,7 +196,7 @@ export class DependenciesScanner {
|
||||
].filter(isFunction);
|
||||
|
||||
mergedInjectables.forEach(injectable =>
|
||||
this.storeInjectable(injectable, token),
|
||||
this.insertInjectable(injectable, token),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -221,7 +215,7 @@ export class DependenciesScanner {
|
||||
flatten(Object.keys(param).map(k => param[k].pipes)).filter(isFunction),
|
||||
);
|
||||
flatten(paramsInjectables).forEach(injectable =>
|
||||
this.storeInjectable(injectable, token),
|
||||
this.insertInjectable(injectable, token),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -246,7 +240,7 @@ export class DependenciesScanner {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
public async storeRelatedModule(
|
||||
public async insertRelatedModule(
|
||||
related: any,
|
||||
token: string,
|
||||
context: string,
|
||||
@@ -260,17 +254,24 @@ export class DependenciesScanner {
|
||||
await this.container.addRelatedModule(related, token);
|
||||
}
|
||||
|
||||
public storeComponent(component, token: string) {
|
||||
const isCustomProvider = component && !isNil(component.provide);
|
||||
public isCustomProvider(
|
||||
provider: Provider,
|
||||
): provider is ClassProvider | ValueProvider | FactoryProvider {
|
||||
return provider && !isNil((provider as any).provide);
|
||||
}
|
||||
|
||||
public insertProvider(provider: Provider, token: string) {
|
||||
const isCustomProvider = this.isCustomProvider(provider);
|
||||
if (!isCustomProvider) {
|
||||
return this.container.addComponent(component, token);
|
||||
return this.container.addProvider(provider as Type<any>, token);
|
||||
}
|
||||
const applyProvidersMap = this.getApplyProvidersMap();
|
||||
const providersKeys = Object.keys(applyProvidersMap);
|
||||
const type = component.provide;
|
||||
const type = (provider as ClassProvider | ValueProvider | FactoryProvider)
|
||||
.provide;
|
||||
|
||||
if (!providersKeys.includes(type)) {
|
||||
return this.container.addComponent(component, token);
|
||||
return this.container.addProvider(provider as any, token);
|
||||
}
|
||||
const providerToken = randomStringGenerator();
|
||||
this.applicationProvidersApplyMap.push({
|
||||
@@ -278,31 +279,31 @@ export class DependenciesScanner {
|
||||
moduleKey: token,
|
||||
providerKey: providerToken,
|
||||
});
|
||||
this.container.addComponent(
|
||||
this.container.addProvider(
|
||||
{
|
||||
...component,
|
||||
...provider,
|
||||
provide: providerToken,
|
||||
},
|
||||
} as any,
|
||||
token,
|
||||
);
|
||||
}
|
||||
|
||||
public storeInjectable(component: Type<Injectable>, token: string) {
|
||||
public insertInjectable(component: Type<Injectable>, token: string) {
|
||||
this.container.addInjectable(component, token);
|
||||
}
|
||||
|
||||
public storeExportedComponent(
|
||||
exportedComponent: Type<Injectable>,
|
||||
public insertExportedProvider(
|
||||
exportedProvider: Type<Injectable>,
|
||||
token: string,
|
||||
) {
|
||||
this.container.addExportedComponent(exportedComponent, token);
|
||||
this.container.addExportedProvider(exportedProvider, token);
|
||||
}
|
||||
|
||||
public storeRoute(route: Type<Controller>, token: string) {
|
||||
this.container.addController(route, token);
|
||||
public insertController(controller: Type<Controller>, token: string) {
|
||||
this.container.addController(controller, token);
|
||||
}
|
||||
|
||||
public reflectMetadata(metatype, metadataKey: string) {
|
||||
public reflectMetadata(metatype: Type<any>, metadataKey: string) {
|
||||
return Reflect.getMetadata(metadataKey, metatype) || [];
|
||||
}
|
||||
|
||||
@@ -311,8 +312,8 @@ export class DependenciesScanner {
|
||||
this.applicationProvidersApplyMap.forEach(
|
||||
({ moduleKey, providerKey, type }) => {
|
||||
const modules = this.container.getModules();
|
||||
const { components } = modules.get(moduleKey);
|
||||
const { instance } = components.get(providerKey);
|
||||
const { providers } = modules.get(moduleKey);
|
||||
const { instance } = providers.get(providerKey);
|
||||
|
||||
applyProvidersMap[type](instance);
|
||||
},
|
||||
|
||||
@@ -94,57 +94,57 @@ describe('ExternalContextCreator', () => {
|
||||
expect(contextCreator.findContextModuleName({} as any)).to.be.eql('');
|
||||
});
|
||||
});
|
||||
describe('when component exists', () => {
|
||||
describe('when provider exists', () => {
|
||||
it('should return module key', () => {
|
||||
const modules = new Map();
|
||||
const componentKey = 'test';
|
||||
const providerKey = 'test';
|
||||
const moduleKey = 'key';
|
||||
|
||||
modules.set(moduleKey, {});
|
||||
(contextCreator as any).modulesContainer = modules;
|
||||
sinon
|
||||
.stub(contextCreator, 'findComponentByClassName')
|
||||
.stub(contextCreator, 'findProviderByClassName')
|
||||
.callsFake(() => true);
|
||||
|
||||
expect(
|
||||
contextCreator.findContextModuleName({ name: componentKey } as any),
|
||||
contextCreator.findContextModuleName({ name: providerKey } as any),
|
||||
).to.be.eql(moduleKey);
|
||||
});
|
||||
});
|
||||
describe('when component does not exists', () => {
|
||||
describe('when provider does not exists', () => {
|
||||
it('should return empty string', () => {
|
||||
sinon
|
||||
.stub(contextCreator, 'findComponentByClassName')
|
||||
.stub(contextCreator, 'findProviderByClassName')
|
||||
.callsFake(() => false);
|
||||
expect(contextCreator.findContextModuleName({} as any)).to.be.eql('');
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('findComponentByClassName', () => {
|
||||
describe('when component exists', () => {
|
||||
describe('findProviderByClassName', () => {
|
||||
describe('when provider exists', () => {
|
||||
it('should return true', () => {
|
||||
const components = new Map();
|
||||
const providers = new Map();
|
||||
const key = 'test';
|
||||
components.set(key, key);
|
||||
providers.set(key, key);
|
||||
|
||||
expect(
|
||||
contextCreator.findComponentByClassName(
|
||||
contextCreator.findProviderByClassName(
|
||||
{
|
||||
components,
|
||||
providers,
|
||||
} as any,
|
||||
key,
|
||||
),
|
||||
).to.be.true;
|
||||
});
|
||||
});
|
||||
describe('when component does not exists', () => {
|
||||
describe('when provider does not exists', () => {
|
||||
it('should return false', () => {
|
||||
const components = new Map();
|
||||
const providers = new Map();
|
||||
const key = 'test';
|
||||
expect(
|
||||
contextCreator.findComponentByClassName(
|
||||
contextCreator.findProviderByClassName(
|
||||
{
|
||||
components,
|
||||
providers,
|
||||
} as any,
|
||||
key,
|
||||
),
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { expect } from 'chai';
|
||||
import { RouterMethodFactory } from '../../helpers/router-method-factory';
|
||||
import { RequestMethod } from '../../../common/enums/request-method.enum';
|
||||
import { RouterMethodFactory } from '../../helpers/router-method-factory';
|
||||
|
||||
describe('RouterMethodFactory', () => {
|
||||
let factory: RouterMethodFactory;
|
||||
const target = {
|
||||
|
||||
const target: any = {
|
||||
get: () => {},
|
||||
post: () => {},
|
||||
use: () => {},
|
||||
|
||||
@@ -20,14 +20,14 @@ describe('NestContainer', () => {
|
||||
container = new NestContainer();
|
||||
});
|
||||
|
||||
it('should "addComponent" throw "UnknownModuleException" when module is not stored in collection', () => {
|
||||
expect(() => container.addComponent({} as any, 'TestModule')).throw(
|
||||
it('should "addProvider" throw "UnknownModuleException" when module is not stored in collection', () => {
|
||||
expect(() => container.addProvider({} as any, 'TestModule')).throw(
|
||||
UnknownModuleException,
|
||||
);
|
||||
});
|
||||
|
||||
it('should "addComponent" throw "CircularDependencyException" when component is nil', () => {
|
||||
expect(() => container.addComponent(null, 'TestModule')).throw(
|
||||
it('should "addProvider" throw "CircularDependencyException" when provider is nil', () => {
|
||||
expect(() => container.addProvider(null, 'TestModule')).throw(
|
||||
CircularDependencyException,
|
||||
);
|
||||
});
|
||||
@@ -38,8 +38,8 @@ describe('NestContainer', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should "addExportedComponent" throw "UnknownModuleException" when module is not stored in collection', () => {
|
||||
expect(() => container.addExportedComponent(null, 'TestModule')).throw(
|
||||
it('should "addExportedProvider" throw "UnknownModuleException" when module is not stored in collection', () => {
|
||||
expect(() => container.addExportedProvider(null, 'TestModule')).throw(
|
||||
UnknownModuleException,
|
||||
);
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as chai from 'chai';
|
||||
import { expect } from 'chai';
|
||||
import * as chaiAsPromised from 'chai-as-promised';
|
||||
import * as sinon from 'sinon';
|
||||
import { Component } from '../../../common/decorators/core/component.decorator';
|
||||
import { Injectable } from '../../../common/decorators/core/component.decorator';
|
||||
import { Inject } from '../../../common/decorators/core/inject.decorator';
|
||||
import { InstanceWrapper, NestContainer } from '../../injector/container';
|
||||
import { Injector, PropertyDependency } from '../../injector/injector';
|
||||
@@ -17,13 +17,13 @@ describe('Injector', () => {
|
||||
});
|
||||
|
||||
describe('loadInstance', () => {
|
||||
@Component()
|
||||
@Injectable()
|
||||
class DependencyOne {}
|
||||
|
||||
@Component()
|
||||
@Injectable()
|
||||
class DependencyTwo {}
|
||||
|
||||
@Component()
|
||||
@Injectable()
|
||||
class MainTest {
|
||||
@Inject() property: DependencyOne;
|
||||
|
||||
@@ -53,18 +53,18 @@ describe('Injector', () => {
|
||||
instance: Object.create(DependencyOne.prototype),
|
||||
isResolved: false,
|
||||
};
|
||||
moduleDeps.components.set('MainTest', mainTest);
|
||||
moduleDeps.components.set('DependencyOne', depOne);
|
||||
moduleDeps.components.set('DependencyTwo', depTwo);
|
||||
moduleDeps.components.set('MainTestResolved', {
|
||||
moduleDeps.providers.set('MainTest', mainTest);
|
||||
moduleDeps.providers.set('DependencyOne', depOne);
|
||||
moduleDeps.providers.set('DependencyTwo', depTwo);
|
||||
moduleDeps.providers.set('MainTestResolved', {
|
||||
...mainTest,
|
||||
isResolved: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should create an instance of component with proper dependencies', async () => {
|
||||
await injector.loadInstance(mainTest, moduleDeps.components, moduleDeps);
|
||||
const { instance } = moduleDeps.components.get(
|
||||
await injector.loadInstance(mainTest, moduleDeps.providers, moduleDeps);
|
||||
const { instance } = moduleDeps.providers.get(
|
||||
'MainTest',
|
||||
) as InstanceWrapper<MainTest>;
|
||||
|
||||
@@ -74,8 +74,8 @@ describe('Injector', () => {
|
||||
});
|
||||
|
||||
it('should set "isResolved" property to true after instance initialization', async () => {
|
||||
await injector.loadInstance(mainTest, moduleDeps.components, moduleDeps);
|
||||
const { isResolved } = moduleDeps.components.get(
|
||||
await injector.loadInstance(mainTest, moduleDeps.providers, moduleDeps);
|
||||
const { isResolved } = moduleDeps.providers.get(
|
||||
'MainTest',
|
||||
) as InstanceWrapper<MainTest>;
|
||||
expect(isResolved).to.be.true;
|
||||
@@ -83,7 +83,7 @@ describe('Injector', () => {
|
||||
|
||||
it('should throw RuntimeException when type is not stored in collection', () => {
|
||||
return expect(
|
||||
injector.loadInstance({} as any, moduleDeps.components, moduleDeps),
|
||||
injector.loadInstance({} as any, moduleDeps.providers, moduleDeps),
|
||||
).to.eventually.be.rejected;
|
||||
});
|
||||
|
||||
@@ -98,7 +98,7 @@ describe('Injector', () => {
|
||||
isPending: true,
|
||||
done$: Promise.resolve(value) as any,
|
||||
},
|
||||
moduleDeps.components,
|
||||
moduleDeps.providers,
|
||||
moduleDeps,
|
||||
);
|
||||
expect(result).to.be.eql(value);
|
||||
@@ -113,7 +113,7 @@ describe('Injector', () => {
|
||||
instance: Object.create(MainTest.prototype),
|
||||
isResolved: true,
|
||||
},
|
||||
moduleDeps.components,
|
||||
moduleDeps.providers,
|
||||
moduleDeps,
|
||||
);
|
||||
expect(result).to.be.undefined;
|
||||
@@ -121,7 +121,7 @@ describe('Injector', () => {
|
||||
});
|
||||
|
||||
describe('loadPrototypeOfInstance', () => {
|
||||
@Component()
|
||||
@Injectable()
|
||||
class Test {}
|
||||
|
||||
let moduleDeps: Module;
|
||||
@@ -135,7 +135,7 @@ describe('Injector', () => {
|
||||
instance: Object.create(Test.prototype),
|
||||
isResolved: false,
|
||||
};
|
||||
moduleDeps.components.set('Test', test);
|
||||
moduleDeps.providers.set('Test', test);
|
||||
});
|
||||
|
||||
it('should create prototype of instance', () => {
|
||||
@@ -145,8 +145,8 @@ describe('Injector', () => {
|
||||
metatype: Test,
|
||||
name: 'Test',
|
||||
};
|
||||
injector.loadPrototypeOfInstance(test, moduleDeps.components);
|
||||
expect(moduleDeps.components.get('Test')).to.deep.equal(expectedResult);
|
||||
injector.loadPrototypeOfInstance(test, moduleDeps.providers);
|
||||
expect(moduleDeps.providers.get('Test')).to.deep.equal(expectedResult);
|
||||
});
|
||||
|
||||
it('should return null when collection is nil', () => {
|
||||
@@ -225,7 +225,7 @@ describe('Injector', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('loadInstanceOfRoute', () => {
|
||||
describe('loadInstanceOfController', () => {
|
||||
let loadInstance: sinon.SinonSpy;
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -234,11 +234,11 @@ describe('Injector', () => {
|
||||
});
|
||||
|
||||
it('should call "loadInstance" with expected arguments', async () => {
|
||||
const module = { routes: [] };
|
||||
const module = { controllers: [] };
|
||||
const wrapper = { test: 'test' };
|
||||
|
||||
await injector.loadInstanceOfRoute(wrapper as any, module as any);
|
||||
expect(loadInstance.calledWith(wrapper, module.routes, module)).to.be
|
||||
await injector.loadInstanceOfController(wrapper as any, module as any);
|
||||
expect(loadInstance.calledWith(wrapper, module.controllers, module)).to.be
|
||||
.true;
|
||||
});
|
||||
});
|
||||
@@ -363,7 +363,7 @@ describe('Injector', () => {
|
||||
[
|
||||
'key',
|
||||
{
|
||||
components: {
|
||||
providers: {
|
||||
has: () => false,
|
||||
},
|
||||
exports: {
|
||||
@@ -385,7 +385,7 @@ describe('Injector', () => {
|
||||
[
|
||||
'key',
|
||||
{
|
||||
components: {
|
||||
providers: {
|
||||
has: () => true,
|
||||
},
|
||||
exports: {
|
||||
@@ -409,7 +409,7 @@ describe('Injector', () => {
|
||||
[
|
||||
'key',
|
||||
{
|
||||
components: {
|
||||
providers: {
|
||||
has: () => true,
|
||||
get: () => ({
|
||||
isResolved: false,
|
||||
@@ -436,7 +436,7 @@ describe('Injector', () => {
|
||||
[
|
||||
'key',
|
||||
{
|
||||
components: {
|
||||
providers: {
|
||||
has: () => true,
|
||||
get: () => ({
|
||||
isResolved: true,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import * as sinon from 'sinon';
|
||||
import { expect } from 'chai';
|
||||
import { InstanceLoader } from '../../injector/instance-loader';
|
||||
import { NestContainer } from '../../injector/container';
|
||||
import { Injector } from '../../injector/injector';
|
||||
import * as sinon from 'sinon';
|
||||
import { Injectable } from '../../../common';
|
||||
import { Controller } from '../../../common/decorators/core/controller.decorator';
|
||||
import { Component } from '../../../common/decorators/core/component.decorator';
|
||||
import { NestEnvironment } from '../../../common/enums/nest-environment.enum';
|
||||
import { Logger } from '../../../common/services/logger.service';
|
||||
import { NestContainer } from '../../injector/container';
|
||||
import { Injector } from '../../injector/injector';
|
||||
import { InstanceLoader } from '../../injector/instance-loader';
|
||||
|
||||
describe('InstanceLoader', () => {
|
||||
let loader: InstanceLoader;
|
||||
@@ -16,8 +16,8 @@ describe('InstanceLoader', () => {
|
||||
@Controller('')
|
||||
class TestRoute {}
|
||||
|
||||
@Component()
|
||||
class TestComponent {}
|
||||
@Injectable()
|
||||
class TestProvider {}
|
||||
|
||||
before(() => Logger.setMode(NestEnvironment.TEST));
|
||||
|
||||
@@ -27,103 +27,98 @@ describe('InstanceLoader', () => {
|
||||
mockContainer = sinon.mock(container);
|
||||
});
|
||||
|
||||
it('should call "loadPrototypeOfInstance" for each component and route in each module', async () => {
|
||||
it('should call "loadPrototypeOfInstance" for each provider and route in each module', async () => {
|
||||
const injector = new Injector();
|
||||
(loader as any).injector = injector;
|
||||
|
||||
const module = {
|
||||
components: new Map(),
|
||||
routes: new Map(),
|
||||
providers: new Map(),
|
||||
controllers: new Map(),
|
||||
injectables: new Map(),
|
||||
metatype: { name: 'test' },
|
||||
};
|
||||
const componentWrapper = { instance: null, metatype: TestComponent };
|
||||
const providerWrapper = { instance: null, metatype: TestProvider };
|
||||
const routeWrapper = { instance: null, metatype: TestRoute };
|
||||
|
||||
module.components.set('TestComponent', componentWrapper);
|
||||
module.routes.set('TestRoute', routeWrapper);
|
||||
module.providers.set('TestProvider', providerWrapper);
|
||||
module.controllers.set('TestRoute', routeWrapper);
|
||||
|
||||
const modules = new Map();
|
||||
modules.set('Test', module);
|
||||
mockContainer.expects('getModules').returns(modules);
|
||||
|
||||
const loadComponentPrototypeStub = sinon.stub(
|
||||
const loadProviderPrototypeStub = sinon.stub(
|
||||
injector,
|
||||
'loadPrototypeOfInstance',
|
||||
);
|
||||
|
||||
sinon.stub(injector, 'loadInstanceOfRoute');
|
||||
sinon.stub(injector, 'loadInstanceOfController');
|
||||
sinon.stub(injector, 'loadInstanceOfComponent');
|
||||
|
||||
await loader.createInstancesOfDependencies();
|
||||
expect(
|
||||
loadComponentPrototypeStub.calledWith(
|
||||
componentWrapper,
|
||||
module.components,
|
||||
),
|
||||
loadProviderPrototypeStub.calledWith(providerWrapper, module.providers),
|
||||
).to.be.true;
|
||||
expect(
|
||||
loadComponentPrototypeStub.calledWith(routeWrapper, module.components),
|
||||
loadProviderPrototypeStub.calledWith(routeWrapper, module.controllers),
|
||||
).to.be.true;
|
||||
});
|
||||
|
||||
it('should call "loadInstanceOfComponent" for each component in each module', async () => {
|
||||
it('should call "loadInstanceOfComponent" for each provider in each module', async () => {
|
||||
const injector = new Injector();
|
||||
(loader as any).injector = injector;
|
||||
|
||||
const module = {
|
||||
components: new Map(),
|
||||
routes: new Map(),
|
||||
providers: new Map(),
|
||||
controllers: new Map(),
|
||||
injectables: new Map(),
|
||||
metatype: { name: 'test' },
|
||||
};
|
||||
const testComp = {
|
||||
instance: null,
|
||||
metatype: TestComponent,
|
||||
name: 'TestComponent',
|
||||
metatype: TestProvider,
|
||||
name: 'TestProvider',
|
||||
};
|
||||
|
||||
module.components.set('TestComponent', testComp);
|
||||
module.providers.set('TestProvider', testComp);
|
||||
|
||||
const modules = new Map();
|
||||
modules.set('Test', module);
|
||||
mockContainer.expects('getModules').returns(modules);
|
||||
|
||||
const loadComponentStub = sinon.stub(injector, 'loadInstanceOfComponent');
|
||||
sinon.stub(injector, 'loadInstanceOfRoute');
|
||||
const loadProviderStub = sinon.stub(injector, 'loadInstanceOfComponent');
|
||||
sinon.stub(injector, 'loadInstanceOfController');
|
||||
|
||||
await loader.createInstancesOfDependencies();
|
||||
expect(
|
||||
loadComponentStub.calledWith(
|
||||
module.components.get('TestComponent'),
|
||||
module,
|
||||
),
|
||||
loadProviderStub.calledWith(module.providers.get('TestProvider'), module),
|
||||
).to.be.true;
|
||||
});
|
||||
|
||||
it('should call "loadInstanceOfRoute" for each route in each module', async () => {
|
||||
it('should call "loadInstanceOfController" for each route in each module', async () => {
|
||||
const injector = new Injector();
|
||||
(loader as any).injector = injector;
|
||||
|
||||
const module = {
|
||||
components: new Map(),
|
||||
routes: new Map(),
|
||||
providers: new Map(),
|
||||
controllers: new Map(),
|
||||
injectables: new Map(),
|
||||
metatype: { name: 'test' },
|
||||
};
|
||||
const wrapper = { name: 'TestRoute', instance: null, metatype: TestRoute };
|
||||
module.routes.set('TestRoute', wrapper);
|
||||
module.controllers.set('TestRoute', wrapper);
|
||||
|
||||
const modules = new Map();
|
||||
modules.set('Test', module);
|
||||
mockContainer.expects('getModules').returns(modules);
|
||||
|
||||
sinon.stub(injector, 'loadInstanceOfComponent');
|
||||
const loadRoutesStub = sinon.stub(injector, 'loadInstanceOfRoute');
|
||||
sinon.stub(injector, 'loadInstanceOfProvider');
|
||||
const loadRoutesStub = sinon.stub(injector, 'loadInstanceOfController');
|
||||
|
||||
await loader.createInstancesOfDependencies();
|
||||
expect(loadRoutesStub.calledWith(module.routes.get('TestRoute'), module)).to
|
||||
.be.true;
|
||||
expect(
|
||||
loadRoutesStub.calledWith(module.controllers.get('TestRoute'), module),
|
||||
).to.be.true;
|
||||
});
|
||||
|
||||
it('should call "loadInstanceOfInjectable" for each injectable in each module', async () => {
|
||||
@@ -131,29 +126,29 @@ describe('InstanceLoader', () => {
|
||||
(loader as any).injector = injector;
|
||||
|
||||
const module = {
|
||||
components: new Map(),
|
||||
routes: new Map(),
|
||||
providers: new Map(),
|
||||
controllers: new Map(),
|
||||
injectables: new Map(),
|
||||
metatype: { name: 'test' },
|
||||
};
|
||||
const testComp = {
|
||||
instance: null,
|
||||
metatype: TestComponent,
|
||||
name: 'TestComponent',
|
||||
metatype: TestProvider,
|
||||
name: 'TestProvider',
|
||||
};
|
||||
module.injectables.set('TestComponent', testComp);
|
||||
module.injectables.set('TestProvider', testComp);
|
||||
|
||||
const modules = new Map();
|
||||
modules.set('Test', module);
|
||||
mockContainer.expects('getModules').returns(modules);
|
||||
|
||||
const loadInjectableStub = sinon.stub(injector, 'loadInstanceOfInjectable');
|
||||
sinon.stub(injector, 'loadInstanceOfRoute');
|
||||
sinon.stub(injector, 'loadInstanceOfController');
|
||||
|
||||
await loader.createInstancesOfDependencies();
|
||||
expect(
|
||||
loadInjectableStub.calledWith(
|
||||
module.injectables.get('TestComponent'),
|
||||
module.injectables.get('TestProvider'),
|
||||
module,
|
||||
),
|
||||
).to.be.true;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { expect } from 'chai';
|
||||
import safeStringify from 'fast-safe-stringify';
|
||||
import * as hash from 'object-hash';
|
||||
import { SingleScope } from '../../../common';
|
||||
import { ModuleTokenFactory } from '../../injector/module-token-factory';
|
||||
import safeStringify from 'fast-safe-stringify';
|
||||
|
||||
describe('ModuleTokenFactory', () => {
|
||||
let factory: ModuleTokenFactory;
|
||||
@@ -37,18 +37,14 @@ describe('ModuleTokenFactory', () => {
|
||||
);
|
||||
});
|
||||
it('should include dynamic metadata', () => {
|
||||
const token = factory.create(
|
||||
SingleScope()(Module) as any,
|
||||
[Module],
|
||||
{
|
||||
components: [{}],
|
||||
} as any,
|
||||
);
|
||||
const token = factory.create(SingleScope()(Module) as any, [Module], {
|
||||
providers: [{}],
|
||||
} as any);
|
||||
expect(token).to.be.deep.eq(
|
||||
hash({
|
||||
module: Module.name,
|
||||
dynamic: safeStringify({
|
||||
components: [{}],
|
||||
providers: [{}],
|
||||
}),
|
||||
scope: [Module.name],
|
||||
}),
|
||||
@@ -64,7 +60,7 @@ describe('ModuleTokenFactory', () => {
|
||||
describe('getDynamicMetadataToken', () => {
|
||||
describe('when metadata exists', () => {
|
||||
it('should return hash', () => {
|
||||
const metadata = { components: ['', {}] };
|
||||
const metadata = { providers: ['', {}] };
|
||||
expect(factory.getDynamicMetadataToken(metadata as any)).to.be.eql(
|
||||
JSON.stringify(metadata),
|
||||
);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { expect } from 'chai';
|
||||
import * as sinon from 'sinon';
|
||||
import { Component } from '../../../common/decorators/core/component.decorator';
|
||||
import { Injectable } from '../../../common';
|
||||
import { Module as ModuleDecorator } from '../../../common/decorators/modules/module.decorator';
|
||||
import { RuntimeException } from '../../errors/exceptions/runtime.exception';
|
||||
import { UnknownElementException } from '../../errors/exceptions/unknown-element.exception';
|
||||
@@ -14,21 +14,22 @@ describe('Module', () => {
|
||||
|
||||
@ModuleDecorator({})
|
||||
class TestModule {}
|
||||
@Component()
|
||||
class TestComponent {}
|
||||
|
||||
@Injectable()
|
||||
class TestProvider {}
|
||||
|
||||
beforeEach(() => {
|
||||
container = new NestContainer();
|
||||
module = new Module(TestModule as any, [], container);
|
||||
});
|
||||
|
||||
it('should add route', () => {
|
||||
it('should add controller', () => {
|
||||
const collection = new Map();
|
||||
const setSpy = sinon.spy(collection, 'set');
|
||||
(module as any)._routes = collection;
|
||||
(module as any)._controllers = collection;
|
||||
|
||||
class Test {}
|
||||
module.addRoute(Test);
|
||||
module.addController(Test);
|
||||
expect(setSpy.getCall(0).args).to.deep.equal([
|
||||
'Test',
|
||||
{
|
||||
@@ -45,12 +46,12 @@ describe('Module', () => {
|
||||
const setSpy = sinon.spy(collection, 'set');
|
||||
(module as any)._injectables = collection;
|
||||
|
||||
module.addInjectable(TestComponent);
|
||||
module.addInjectable(TestProvider);
|
||||
expect(setSpy.getCall(0).args).to.deep.equal([
|
||||
'TestComponent',
|
||||
'TestProvider',
|
||||
{
|
||||
name: 'TestComponent',
|
||||
metatype: TestComponent,
|
||||
name: 'TestProvider',
|
||||
metatype: TestProvider,
|
||||
instance: null,
|
||||
isResolved: false,
|
||||
},
|
||||
@@ -66,17 +67,17 @@ describe('Module', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should add component', () => {
|
||||
it('should add provider', () => {
|
||||
const collection = new Map();
|
||||
const setSpy = sinon.spy(collection, 'set');
|
||||
(module as any)._components = collection;
|
||||
(module as any)._providers = collection;
|
||||
|
||||
module.addComponent(TestComponent);
|
||||
module.addProvider(TestProvider);
|
||||
expect(setSpy.getCall(0).args).to.deep.equal([
|
||||
'TestComponent',
|
||||
'TestProvider',
|
||||
{
|
||||
name: 'TestComponent',
|
||||
metatype: TestComponent,
|
||||
name: 'TestProvider',
|
||||
metatype: TestProvider,
|
||||
instance: null,
|
||||
isResolved: false,
|
||||
},
|
||||
@@ -89,7 +90,7 @@ describe('Module', () => {
|
||||
|
||||
const provider = { provide: 'test', useValue: 'test' };
|
||||
|
||||
module.addComponent(provider as any);
|
||||
module.addProvider(provider as any);
|
||||
expect((addCustomProvider as sinon.SinonSpy).called).to.be.true;
|
||||
});
|
||||
|
||||
@@ -125,18 +126,18 @@ describe('Module', () => {
|
||||
|
||||
describe('addCustomClass', () => {
|
||||
const type = { name: 'TypeTest' };
|
||||
const component = { provide: type, useClass: type, name: 'test' };
|
||||
const provider = { provide: type, useClass: type, name: 'test' };
|
||||
let setSpy;
|
||||
beforeEach(() => {
|
||||
const collection = new Map();
|
||||
setSpy = sinon.spy(collection, 'set');
|
||||
(module as any)._components = collection;
|
||||
(module as any)._providers = collection;
|
||||
});
|
||||
it('should store component', () => {
|
||||
module.addCustomClass(component as any, (module as any)._components);
|
||||
it('should store provider', () => {
|
||||
module.addCustomClass(provider as any, (module as any)._providers);
|
||||
expect(
|
||||
setSpy.calledWith(component.name, {
|
||||
name: component.name,
|
||||
setSpy.calledWith(provider.name, {
|
||||
name: provider.name,
|
||||
metatype: type,
|
||||
instance: null,
|
||||
isResolved: false,
|
||||
@@ -149,16 +150,16 @@ describe('Module', () => {
|
||||
let setSpy;
|
||||
const value = () => ({});
|
||||
const name = 'test';
|
||||
const component = { provide: value, name, useValue: value };
|
||||
const provider = { provide: value, name, useValue: value };
|
||||
|
||||
beforeEach(() => {
|
||||
const collection = new Map();
|
||||
setSpy = sinon.spy(collection, 'set');
|
||||
(module as any)._components = collection;
|
||||
(module as any)._providers = collection;
|
||||
});
|
||||
|
||||
it('should store component', () => {
|
||||
module.addCustomValue(component as any, (module as any)._components);
|
||||
it('should store provider', () => {
|
||||
module.addCustomValue(provider as any, (module as any)._providers);
|
||||
expect(
|
||||
setSpy.calledWith(name, {
|
||||
name,
|
||||
@@ -175,20 +176,20 @@ describe('Module', () => {
|
||||
describe('addCustomFactory', () => {
|
||||
const type = { name: 'TypeTest' };
|
||||
const inject = [1, 2, 3];
|
||||
const component = { provide: type, useFactory: type, name: 'test', inject };
|
||||
const provider = { provide: type, useFactory: type, name: 'test', inject };
|
||||
|
||||
let setSpy;
|
||||
beforeEach(() => {
|
||||
const collection = new Map();
|
||||
setSpy = sinon.spy(collection, 'set');
|
||||
(module as any)._components = collection;
|
||||
(module as any)._providers = collection;
|
||||
});
|
||||
it('should store component', () => {
|
||||
module.addCustomFactory(component as any, (module as any)._components);
|
||||
it('should store provider', () => {
|
||||
module.addCustomFactory(provider as any, (module as any)._providers);
|
||||
expect(setSpy.getCall(0).args).to.deep.equal([
|
||||
component.name,
|
||||
provider.name,
|
||||
{
|
||||
name: component.name,
|
||||
name: provider.name,
|
||||
metatype: type,
|
||||
instance: null,
|
||||
isResolved: false,
|
||||
@@ -200,52 +201,52 @@ describe('Module', () => {
|
||||
});
|
||||
|
||||
describe('when get instance', () => {
|
||||
describe('when metatype does not exists in components collection', () => {
|
||||
describe('when metatype does not exists in providers collection', () => {
|
||||
beforeEach(() => {
|
||||
sinon.stub((module as any)._components, 'has').returns(false);
|
||||
sinon.stub((module as any)._providers, 'has').returns(false);
|
||||
});
|
||||
it('should throws RuntimeException', () => {
|
||||
expect(() => module.instance).to.throws(RuntimeException);
|
||||
});
|
||||
});
|
||||
describe('when metatype exists in components collection', () => {
|
||||
describe('when metatype exists in providers collection', () => {
|
||||
it('should returns null', () => {
|
||||
expect(module.instance).to.be.eql(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when exported component is custom provided', () => {
|
||||
describe('when exported provider is custom provided', () => {
|
||||
beforeEach(() => {
|
||||
sinon.stub(module, 'validateExportedProvider').callsFake(o => o);
|
||||
});
|
||||
it('should call `addCustomExportedComponent`', () => {
|
||||
const addCustomExportedComponentSpy = sinon.spy(
|
||||
it('should call `addCustomExportedProvider`', () => {
|
||||
const addCustomExportedProviderSpy = sinon.spy(
|
||||
module,
|
||||
'addCustomExportedComponent',
|
||||
'addCustomExportedProvider',
|
||||
);
|
||||
|
||||
module.addExportedComponent({ provide: 'test' } as any);
|
||||
expect(addCustomExportedComponentSpy.called).to.be.true;
|
||||
module.addExportedProvider({ provide: 'test' } as any);
|
||||
expect(addCustomExportedProviderSpy.called).to.be.true;
|
||||
});
|
||||
it('should support symbols', () => {
|
||||
const addCustomExportedComponentSpy = sinon.spy(
|
||||
const addCustomExportedProviderSpy = sinon.spy(
|
||||
module,
|
||||
'addCustomExportedComponent',
|
||||
'addCustomExportedProvider',
|
||||
);
|
||||
const symb = Symbol('test');
|
||||
module.addExportedComponent({ provide: symb } as any);
|
||||
expect(addCustomExportedComponentSpy.called).to.be.true;
|
||||
module.addExportedProvider({ provide: symb } as any);
|
||||
expect(addCustomExportedProviderSpy.called).to.be.true;
|
||||
expect((module as any)._exports.has(symb)).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe('replace', () => {
|
||||
describe('when component', () => {
|
||||
it('should call `addComponent`', () => {
|
||||
const addComponentSpy = sinon.spy(module, 'addComponent');
|
||||
module.replace(null, { isComponent: true });
|
||||
expect(addComponentSpy.called).to.be.true;
|
||||
describe('when provider', () => {
|
||||
it('should call `addProvider`', () => {
|
||||
const addProviderSpy = sinon.spy(module, 'addProvider');
|
||||
module.replace(null, { isProvider: true });
|
||||
expect(addProviderSpy.called).to.be.true;
|
||||
});
|
||||
});
|
||||
describe('when guard', () => {
|
||||
@@ -273,11 +274,11 @@ describe('Module', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('routes', () => {
|
||||
it('should return routes', () => {
|
||||
describe('controllers', () => {
|
||||
it('should return controllers', () => {
|
||||
const test = ['test'];
|
||||
(module as any)._routes = test;
|
||||
expect(module.routes).to.be.eql(test);
|
||||
(module as any)._controllers = test;
|
||||
expect(module.controllers).to.be.eql(test);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -311,9 +312,9 @@ describe('Module', () => {
|
||||
describe('validateExportedProvider', () => {
|
||||
const token = 'token';
|
||||
|
||||
describe('when unit exists in component collection', () => {
|
||||
describe('when unit exists in provider collection', () => {
|
||||
it('should behave as identity', () => {
|
||||
(module as any)._components = new Map([[token, true]]);
|
||||
(module as any)._providers = new Map([[token, true]]);
|
||||
expect(module.validateExportedProvider(token)).to.be.eql(token);
|
||||
});
|
||||
});
|
||||
@@ -326,7 +327,7 @@ describe('Module', () => {
|
||||
expect(module.validateExportedProvider(token)).to.be.eql(token);
|
||||
});
|
||||
});
|
||||
describe('when unit does not exist in both component and related modules collections', () => {
|
||||
describe('when unit does not exist in both provider and related modules collections', () => {
|
||||
it('should throw UnknownExportException', () => {
|
||||
expect(() => module.validateExportedProvider(token)).to.throws(
|
||||
UnknownExportException,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { expect } from 'chai';
|
||||
import { MiddlewareContainer } from '../../middleware/container';
|
||||
import { MiddlewareConfiguration } from '../../../common/interfaces/middleware/middleware-configuration.interface';
|
||||
import { NestMiddleware } from '../../../common/interfaces/middleware/nest-middleware.interface';
|
||||
import { Component } from '../../../common/decorators/core/component.decorator';
|
||||
import { Injectable } from '../../../common';
|
||||
import { Controller } from '../../../common/decorators/core/controller.decorator';
|
||||
import { RequestMapping } from '../../../common/decorators/http/request-mapping.decorator';
|
||||
import { RequestMethod } from '../../../common/enums/request-method.enum';
|
||||
import { MiddlewareConfiguration } from '../../../common/interfaces/middleware/middleware-configuration.interface';
|
||||
import { NestMiddleware } from '../../../common/interfaces/middleware/nest-middleware.interface';
|
||||
import { MiddlewareContainer } from '../../middleware/container';
|
||||
|
||||
describe('MiddlewareContainer', () => {
|
||||
@Controller('test')
|
||||
@@ -17,7 +17,7 @@ describe('MiddlewareContainer', () => {
|
||||
public getAnother() {}
|
||||
}
|
||||
|
||||
@Component()
|
||||
@Injectable()
|
||||
class TestMiddleware implements NestMiddleware {
|
||||
public resolve() {
|
||||
return (req, res, next) => {};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { expect } from 'chai';
|
||||
import * as sinon from 'sinon';
|
||||
import { Component } from '../../../common/decorators/core/component.decorator';
|
||||
import { Controller } from '../../../common/decorators/core/controller.decorator';
|
||||
import { RequestMapping } from '../../../common/decorators/http/request-mapping.decorator';
|
||||
import { RequestMethod } from '../../../common/enums/request-method.enum';
|
||||
@@ -30,7 +30,7 @@ describe('MiddlewareModule', () => {
|
||||
public getAnother() {}
|
||||
}
|
||||
|
||||
@Component()
|
||||
@Injectable()
|
||||
class TestMiddleware implements NestMiddleware {
|
||||
public resolve() {
|
||||
return (req, res, next) => {};
|
||||
@@ -93,7 +93,7 @@ describe('MiddlewareModule', () => {
|
||||
});
|
||||
|
||||
it('should throw "InvalidMiddlewareException" exception when middleware does not have "resolve" method', () => {
|
||||
@Component()
|
||||
@Injectable()
|
||||
class InvalidMiddleware {}
|
||||
|
||||
const route = { path: 'Test' };
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import * as sinon from 'sinon';
|
||||
import { expect } from 'chai';
|
||||
import { MiddlewareResolver } from '../../middleware/resolver';
|
||||
import { MiddlewareContainer } from '../../middleware/container';
|
||||
import { Component } from '../../../common/decorators/core/component.decorator';
|
||||
import * as sinon from 'sinon';
|
||||
import { Injectable } from '../../../common';
|
||||
import { NestEnvironment } from '../../../common/enums/nest-environment.enum';
|
||||
import { NestMiddleware } from '../../../common/interfaces/middleware/nest-middleware.interface';
|
||||
import { Logger } from '../../../common/services/logger.service';
|
||||
import { NestEnvironment } from '../../../common/enums/nest-environment.enum';
|
||||
import { MiddlewareContainer } from '../../middleware/container';
|
||||
import { MiddlewareResolver } from '../../middleware/resolver';
|
||||
|
||||
describe('MiddlewareResolver', () => {
|
||||
@Component()
|
||||
@Injectable()
|
||||
class TestMiddleware implements NestMiddleware {
|
||||
public resolve() {
|
||||
return (req, res, next) => {};
|
||||
@@ -29,6 +29,7 @@ describe('MiddlewareResolver', () => {
|
||||
|
||||
it('should resolve middleware instances from container', () => {
|
||||
const loadInstanceOfMiddleware = sinon.stub(
|
||||
// tslint:disable-next-line:no-string-literal
|
||||
resolver['instanceLoader'],
|
||||
'loadInstanceOfMiddleware',
|
||||
);
|
||||
@@ -39,7 +40,7 @@ describe('MiddlewareResolver', () => {
|
||||
};
|
||||
middleware.set('TestMiddleware', wrapper);
|
||||
|
||||
const module = <any>{ metatype: { name: '' } };
|
||||
const module = { metatype: { name: '' } } as any;
|
||||
mockContainer.expects('getMiddleware').returns(middleware);
|
||||
resolver.resolveInstances(module, null);
|
||||
|
||||
|
||||
@@ -1,27 +1,28 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { expect } from 'chai';
|
||||
import * as sinon from 'sinon';
|
||||
import { GUARDS_METADATA } from '../../common/constants';
|
||||
import { Component } from '../../common/decorators/core/component.decorator';
|
||||
import { Controller } from '../../common/decorators/core/controller.decorator';
|
||||
import { UseGuards } from '../../common/decorators/core/use-guards.decorator';
|
||||
import { Module } from '../../common/decorators/modules/module.decorator';
|
||||
import { ApplicationConfig } from '../application-config';
|
||||
import { APP_FILTER, APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from '../constants';
|
||||
import { MetadataScanner } from '../metadata-scanner';
|
||||
import { NestContainer } from '../injector/container';
|
||||
import { MetadataScanner } from '../metadata-scanner';
|
||||
import { DependenciesScanner } from '../scanner';
|
||||
|
||||
class Guard {}
|
||||
|
||||
describe('DependenciesScanner', () => {
|
||||
@Component()
|
||||
@Injectable()
|
||||
class TestComponent {}
|
||||
|
||||
@Controller('')
|
||||
class TestRoute {}
|
||||
class TestController {}
|
||||
|
||||
@Module({
|
||||
providers: [TestComponent],
|
||||
controllers: [TestRoute],
|
||||
controllers: [TestController],
|
||||
exports: [TestComponent],
|
||||
})
|
||||
class AnotherTestModule {}
|
||||
@@ -29,7 +30,7 @@ describe('DependenciesScanner', () => {
|
||||
@Module({
|
||||
imports: [AnotherTestModule],
|
||||
providers: [TestComponent],
|
||||
controllers: [TestRoute],
|
||||
controllers: [TestController],
|
||||
})
|
||||
class TestModule {}
|
||||
|
||||
@@ -52,29 +53,29 @@ describe('DependenciesScanner', () => {
|
||||
mockContainer.restore();
|
||||
});
|
||||
|
||||
it('should "storeModule" call twice (2 modules) container method "addModule"', async () => {
|
||||
it('should "insertModule" call twice (2 modules) container method "addModule"', async () => {
|
||||
const expectation = mockContainer.expects('addModule').twice();
|
||||
await scanner.scan(TestModule as any);
|
||||
expectation.verify();
|
||||
});
|
||||
|
||||
it('should "storeComponent" call twice (2 components) container method "addComponent"', async () => {
|
||||
const expectation = mockContainer.expects('addComponent').twice();
|
||||
const stub = sinon.stub(scanner, 'storeExportedComponent');
|
||||
it('should "insertProvider" call twice (2 components) container method "addProvider"', async () => {
|
||||
const expectation = mockContainer.expects('addProvider').twice();
|
||||
const stub = sinon.stub(scanner, 'insertExportedProvider');
|
||||
|
||||
await scanner.scan(TestModule as any);
|
||||
expectation.verify();
|
||||
stub.restore();
|
||||
});
|
||||
|
||||
it('should "storeRoute" call twice (2 components) container method "addController"', async () => {
|
||||
it('should "insertController" call twice (2 components) container method "addController"', async () => {
|
||||
const expectation = mockContainer.expects('addController').twice();
|
||||
await scanner.scan(TestModule as any);
|
||||
expectation.verify();
|
||||
});
|
||||
|
||||
it('should "storeExportedComponent" call once (1 component) container method "addExportedComponent"', async () => {
|
||||
const expectation = mockContainer.expects('addExportedComponent').once();
|
||||
it('should "insertExportedProvider" call once (1 component) container method "addExportedProvider"', async () => {
|
||||
const expectation = mockContainer.expects('addExportedProvider').once();
|
||||
await scanner.scan(TestModule as any);
|
||||
expectation.verify();
|
||||
});
|
||||
@@ -112,7 +113,7 @@ describe('DependenciesScanner', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('storeInjectable', () => {
|
||||
describe('insertInjectable', () => {
|
||||
it('should call "addInjectable"', () => {
|
||||
const addInjectable = sinon
|
||||
.stub((scanner as any).container, 'addInjectable')
|
||||
@@ -120,7 +121,7 @@ describe('DependenciesScanner', () => {
|
||||
const comp = {};
|
||||
const token = 'token';
|
||||
|
||||
scanner.storeInjectable(comp as any, token);
|
||||
scanner.insertInjectable(comp as any, token);
|
||||
expect(addInjectable.calledWith(comp, token)).to.be.true;
|
||||
});
|
||||
});
|
||||
@@ -144,67 +145,67 @@ describe('DependenciesScanner', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('storeModule', () => {
|
||||
describe('insertModule', () => {
|
||||
it('should call forwardRef() when forwardRef property exists', () => {
|
||||
const module = { forwardRef: sinon.spy() };
|
||||
|
||||
sinon.stub(container, 'addModule').returns({});
|
||||
scanner.storeModule(module as any, [] as any);
|
||||
scanner.insertModule(module as any, [] as any);
|
||||
expect(module.forwardRef.called).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
describe('storeRelatedModule', () => {
|
||||
describe('insertRelatedModule', () => {
|
||||
it('should call forwardRef() when forwardRef property exists', async () => {
|
||||
const module = { forwardRef: sinon.stub().returns({}) };
|
||||
|
||||
sinon.stub(container, 'addRelatedModule').returns({});
|
||||
await scanner.storeRelatedModule(module as any, [] as any, 'test');
|
||||
await scanner.insertRelatedModule(module as any, [] as any, 'test');
|
||||
expect(module.forwardRef.called).to.be.true;
|
||||
});
|
||||
describe('when "related" is nil', () => {
|
||||
it('should throw exception', () => {
|
||||
expect(
|
||||
scanner.storeRelatedModule(undefined, [] as any, 'test'),
|
||||
scanner.insertRelatedModule(undefined, [] as any, 'test'),
|
||||
).to.eventually.throws();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('storeComponent', () => {
|
||||
describe('insertProvider', () => {
|
||||
const token = 'token';
|
||||
|
||||
describe('when component is not custom', () => {
|
||||
it('should call container "addComponent" with expected args', () => {
|
||||
const component = {};
|
||||
describe('when provider is not custom', () => {
|
||||
it('should call container "addProvider" with expected args', () => {
|
||||
const provider = {};
|
||||
const expectation = mockContainer
|
||||
.expects('addComponent')
|
||||
.withArgs(component, token);
|
||||
.expects('addProvider')
|
||||
.withArgs(provider, token);
|
||||
|
||||
mockContainer.expects('addComponent').callsFake(() => false);
|
||||
scanner.storeComponent(component, token);
|
||||
mockContainer.expects('addProvider').callsFake(() => false);
|
||||
scanner.insertProvider(provider as any, token);
|
||||
|
||||
expectation.verify();
|
||||
});
|
||||
});
|
||||
describe('when component is custom', () => {
|
||||
describe('when provider is custom', () => {
|
||||
describe('and is global', () => {
|
||||
const component = {
|
||||
const provider = {
|
||||
provide: APP_INTERCEPTOR,
|
||||
useValue: true,
|
||||
};
|
||||
|
||||
it('should call container "addComponent" with expected args', () => {
|
||||
const expectation = mockContainer.expects('addComponent').atLeast(1);
|
||||
it('should call container "addProvider" with expected args', () => {
|
||||
const expectation = mockContainer.expects('addProvider').atLeast(1);
|
||||
|
||||
mockContainer.expects('addComponent').callsFake(() => false);
|
||||
scanner.storeComponent(component, token);
|
||||
mockContainer.expects('addProvider').callsFake(() => false);
|
||||
scanner.insertProvider(provider, token);
|
||||
|
||||
expectation.verify();
|
||||
});
|
||||
it('should push new object to "applicationProvidersApplyMap" array', () => {
|
||||
mockContainer.expects('addComponent').callsFake(() => false);
|
||||
scanner.storeComponent(component, token);
|
||||
mockContainer.expects('addProvider').callsFake(() => false);
|
||||
scanner.insertProvider(provider, token);
|
||||
const applyMap = (scanner as any).applicationProvidersApplyMap;
|
||||
|
||||
expect(applyMap).to.have.length(1);
|
||||
@@ -216,13 +217,13 @@ describe('DependenciesScanner', () => {
|
||||
provide: 'CUSTOM',
|
||||
useValue: true,
|
||||
};
|
||||
it('should call container "addComponent" with expected args', () => {
|
||||
it('should call container "addProvider" with expected args', () => {
|
||||
const expectation = mockContainer
|
||||
.expects('addComponent')
|
||||
.expects('addProvider')
|
||||
.withArgs(component, token);
|
||||
|
||||
mockContainer.expects('addComponent').callsFake(() => false);
|
||||
scanner.storeComponent(component, token);
|
||||
mockContainer.expects('addProvider').callsFake(() => false);
|
||||
scanner.insertProvider(component, token);
|
||||
|
||||
expectation.verify();
|
||||
});
|
||||
@@ -231,8 +232,8 @@ describe('DependenciesScanner', () => {
|
||||
0,
|
||||
);
|
||||
|
||||
mockContainer.expects('addComponent').callsFake(() => false);
|
||||
scanner.storeComponent(component, token);
|
||||
mockContainer.expects('addProvider').callsFake(() => false);
|
||||
scanner.insertProvider(component, token);
|
||||
expect((scanner as any).applicationProvidersApplyMap).to.have.length(
|
||||
0,
|
||||
);
|
||||
@@ -252,7 +253,7 @@ describe('DependenciesScanner', () => {
|
||||
const expectedInstance = {};
|
||||
mockContainer.expects('getModules').callsFake(() => ({
|
||||
get: () => ({
|
||||
components: { get: () => ({ instance: expectedInstance }) },
|
||||
providers: { get: () => ({ instance: expectedInstance }) },
|
||||
}),
|
||||
}));
|
||||
const applySpy = sinon.spy();
|
||||
|
||||
@@ -3,9 +3,9 @@ import { loadPackage } from '@nestjs/common/utils/load-package.util';
|
||||
import { isObject } from '@nestjs/common/utils/shared.utils';
|
||||
import { Observable } from 'rxjs';
|
||||
import { GRPC_DEFAULT_URL } from '../constants';
|
||||
import { InvalidGrpcPackageException } from '../exceptions/errors/invalid-grpc-package.exception';
|
||||
import { InvalidGrpcServiceException } from '../exceptions/errors/invalid-grpc-service.exception';
|
||||
import { InvalidProtoDefinitionException } from '../exceptions/errors/invalid-proto-definition.exception';
|
||||
import { InvalidGrpcPackageException } from '../errors/invalid-grpc-package.exception';
|
||||
import { InvalidGrpcServiceException } from '../errors/invalid-grpc-service.exception';
|
||||
import { InvalidProtoDefinitionException } from '../errors/invalid-proto-definition.exception';
|
||||
import { ClientGrpc, GrpcOptions } from '../interfaces';
|
||||
import { ClientOptions } from '../interfaces/client-metadata.interface';
|
||||
import { ClientProxy } from './client-proxy';
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
} from 'rxjs';
|
||||
import { map, mergeMap, take } from 'rxjs/operators';
|
||||
import { CONNECT_EVENT, ERROR_EVENT } from '../constants';
|
||||
import { InvalidMessageException } from '../exceptions/errors/invalid-message.exception';
|
||||
import { InvalidMessageException } from '../errors/invalid-message.exception';
|
||||
import {
|
||||
ClientOptions,
|
||||
PacketId,
|
||||
|
||||
@@ -27,8 +27,8 @@ export class RpcExceptionsHandler extends BaseRpcExceptionFilter {
|
||||
this.filters = filters;
|
||||
}
|
||||
|
||||
public invokeCustomFilters(
|
||||
exception,
|
||||
public invokeCustomFilters<T = any>(
|
||||
exception: T,
|
||||
host: ArgumentsHost,
|
||||
): Observable<any> | null {
|
||||
if (isEmpty(this.filters)) return null;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { fromEvent } from 'rxjs';
|
||||
import { takeUntil } from 'rxjs/operators';
|
||||
import { CANCEL_EVENT, GRPC_DEFAULT_URL } from '../constants';
|
||||
import { InvalidGrpcPackageException } from '../exceptions/errors/invalid-grpc-package.exception';
|
||||
import { InvalidProtoDefinitionException } from '../exceptions/errors/invalid-proto-definition.exception';
|
||||
import { InvalidGrpcPackageException } from '../errors/invalid-grpc-package.exception';
|
||||
import { InvalidProtoDefinitionException } from '../errors/invalid-proto-definition.exception';
|
||||
import { CustomTransportStrategy } from '../interfaces';
|
||||
import {
|
||||
GrpcOptions,
|
||||
|
||||
@@ -3,9 +3,9 @@ import { join } from 'path';
|
||||
import { Observable } from 'rxjs';
|
||||
import * as sinon from 'sinon';
|
||||
import { ClientGrpcProxy } from '../../client/client-grpc';
|
||||
import { InvalidGrpcPackageException } from '../../exceptions/errors/invalid-grpc-package.exception';
|
||||
import { InvalidGrpcServiceException } from '../../exceptions/errors/invalid-grpc-service.exception';
|
||||
import { InvalidProtoDefinitionException } from '../../exceptions/errors/invalid-proto-definition.exception';
|
||||
import { InvalidGrpcPackageException } from '../../errors/invalid-grpc-package.exception';
|
||||
import { InvalidGrpcServiceException } from '../../errors/invalid-grpc-service.exception';
|
||||
import { InvalidProtoDefinitionException } from '../../errors/invalid-proto-definition.exception';
|
||||
// tslint:disable:no-string-literal
|
||||
|
||||
class GrpcService {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { expect } from 'chai';
|
||||
import { of } from 'rxjs';
|
||||
import * as sinon from 'sinon';
|
||||
import { Guard, Injectable, UseGuards, UsePipes } from '../../../common';
|
||||
import { ApplicationConfig } from '../../../core/application-config';
|
||||
import { GuardsConsumer } from '../../../core/guards/guards-consumer';
|
||||
import { GuardsContextCreator } from '../../../core/guards/guards-context-creator';
|
||||
@@ -9,17 +10,10 @@ import { InterceptorsConsumer } from '../../../core/interceptors/interceptors-co
|
||||
import { InterceptorsContextCreator } from '../../../core/interceptors/interceptors-context-creator';
|
||||
import { PipesConsumer } from '../../../core/pipes/pipes-consumer';
|
||||
import { PipesContextCreator } from '../../../core/pipes/pipes-context-creator';
|
||||
import { RpcException } from '../../index';
|
||||
import {
|
||||
Component,
|
||||
Guard,
|
||||
Injectable,
|
||||
UseGuards,
|
||||
UsePipes,
|
||||
} from '../../../common';
|
||||
import { ExceptionFiltersContext } from '../../context/exception-filters-context';
|
||||
import { RpcContextCreator } from '../../context/rpc-context-creator';
|
||||
import { RpcProxy } from '../../context/rpc-proxy';
|
||||
import { RpcException } from '../../index';
|
||||
|
||||
@Guard()
|
||||
class TestGuard {
|
||||
@@ -45,7 +39,7 @@ describe('RpcContextCreator', () => {
|
||||
let module: string;
|
||||
|
||||
@UseGuards(TestGuard)
|
||||
@Component()
|
||||
@Injectable()
|
||||
class Test {
|
||||
@UsePipes(new TestPipe())
|
||||
test(data: string) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import { expect } from 'chai';
|
||||
import { join } from 'path';
|
||||
import { of } from 'rxjs';
|
||||
import * as sinon from 'sinon';
|
||||
import { InvalidGrpcPackageException } from '../../exceptions/errors/invalid-grpc-package.exception';
|
||||
import { InvalidGrpcPackageException } from '../../errors/invalid-grpc-package.exception';
|
||||
import { ServerGrpc } from '../../server/server-grpc';
|
||||
|
||||
describe('ServerGrpc', () => {
|
||||
|
||||
@@ -67,11 +67,11 @@ export class TestingModuleBuilder {
|
||||
return new TestingModule(this.container, [], root, this.applicationConfig);
|
||||
}
|
||||
|
||||
private override(typeOrToken, isComponent: boolean): OverrideBy {
|
||||
private override(typeOrToken, isProvider: boolean): OverrideBy {
|
||||
const addOverload = options => {
|
||||
this.overloadsMap.set(typeOrToken, {
|
||||
...options,
|
||||
isComponent,
|
||||
isProvider,
|
||||
});
|
||||
return this;
|
||||
};
|
||||
|
||||
@@ -7,8 +7,10 @@ import { filter, first, map, mergeMap, share, takeUntil } from 'rxjs/operators';
|
||||
import * as io from 'socket.io';
|
||||
import { CONNECTION_EVENT, DISCONNECT_EVENT } from '../constants';
|
||||
import { MessageMappingProperties } from '../gateway-metadata-explorer';
|
||||
import { BaseWsExceptionFilter } from './../exceptions/base-ws-exception-filter';
|
||||
|
||||
export class IoAdapter implements WebSocketAdapter {
|
||||
protected readonly baseExceptionFilter = new BaseWsExceptionFilter();
|
||||
protected readonly httpServer: Server;
|
||||
|
||||
constructor(appOrHttpServer?: INestApplicationContext | Server) {
|
||||
@@ -70,12 +72,14 @@ export class IoAdapter implements WebSocketAdapter {
|
||||
}),
|
||||
takeUntil(disconnect$),
|
||||
);
|
||||
source$.subscribe(([response, ack]) => {
|
||||
const onMessage = ([response, ack]) => {
|
||||
if (response.event) {
|
||||
return client.emit(response.event, response.data);
|
||||
}
|
||||
isFunction(ack) && ack(response);
|
||||
});
|
||||
};
|
||||
const onError = err => this.baseExceptionFilter.handleError(client, err);
|
||||
source$.subscribe(onMessage as any, onError);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import { EMPTY as empty, fromEvent, Observable } from 'rxjs';
|
||||
import { filter, first, mergeMap, share, takeUntil } from 'rxjs/operators';
|
||||
import { CLOSE_EVENT, CONNECTION_EVENT, ERROR_EVENT } from '../constants';
|
||||
import { MessageMappingProperties } from '../gateway-metadata-explorer';
|
||||
import { BaseWsExceptionFilter } from './../exceptions/base-ws-exception-filter';
|
||||
|
||||
let wsPackage: any = {};
|
||||
|
||||
@@ -22,6 +23,7 @@ enum READY_STATE {
|
||||
}
|
||||
|
||||
export class WsAdapter implements WebSocketAdapter {
|
||||
protected readonly baseExceptionFilter = new BaseWsExceptionFilter();
|
||||
protected readonly logger = new Logger(WsAdapter.name);
|
||||
protected readonly httpServer: Server;
|
||||
|
||||
@@ -79,13 +81,14 @@ export class WsAdapter implements WebSocketAdapter {
|
||||
),
|
||||
takeUntil(close$),
|
||||
);
|
||||
const handleMessage = response => {
|
||||
const onMessage = response => {
|
||||
if (client.readyState !== READY_STATE.OPEN_STATE) {
|
||||
return;
|
||||
}
|
||||
client.send(JSON.stringify(response));
|
||||
};
|
||||
source$.subscribe(handleMessage);
|
||||
const onError = err => this.baseExceptionFilter.handleError(client, err);
|
||||
source$.subscribe(onMessage, onError);
|
||||
}
|
||||
|
||||
public bindMessageHandler(
|
||||
|
||||
@@ -7,7 +7,7 @@ import { InterceptorsConsumer } from '@nestjs/core/interceptors/interceptors-con
|
||||
import { InterceptorsContextCreator } from '@nestjs/core/interceptors/interceptors-context-creator';
|
||||
import { PipesConsumer } from '@nestjs/core/pipes/pipes-consumer';
|
||||
import { PipesContextCreator } from '@nestjs/core/pipes/pipes-context-creator';
|
||||
import { WsException } from '../exceptions/ws-exception';
|
||||
import { WsException } from '../errors/ws-exception';
|
||||
import { ExceptionFiltersContext } from './exception-filters-context';
|
||||
import { WsProxy } from './ws-proxy';
|
||||
|
||||
|
||||
1
packages/websockets/errors/index.ts
Normal file
1
packages/websockets/errors/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export * from './ws-exception';
|
||||
@@ -1,7 +1,7 @@
|
||||
import { RuntimeException } from '@nestjs/core/errors/exceptions/runtime.exception';
|
||||
|
||||
export class InvalidSocketPortException extends RuntimeException {
|
||||
constructor(port, type) {
|
||||
super(`Invalid port (${port}) in Gateway ${type}!`);
|
||||
constructor(port: number | string, type: any) {
|
||||
super(`Invalid port (${port}) in gateway ${type}!`);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
export class WsException extends Error {
|
||||
public readonly message: any;
|
||||
|
||||
constructor(private readonly error: string | object) {
|
||||
super();
|
||||
this.message = error;
|
||||
@@ -1,16 +1,25 @@
|
||||
import { ArgumentsHost, WsExceptionFilter } from '@nestjs/common';
|
||||
import { isObject } from '@nestjs/common/utils/shared.utils';
|
||||
import { MESSAGES } from '@nestjs/core/constants';
|
||||
import { WsException } from './ws-exception';
|
||||
import { WsException } from '../errors/ws-exception';
|
||||
|
||||
export class BaseWsExceptionFilter<T = any> implements WsExceptionFilter<T> {
|
||||
catch(exception: T, host: ArgumentsHost) {
|
||||
const client = host.switchToWs().getClient();
|
||||
this.handleError(client, exception);
|
||||
}
|
||||
|
||||
handleError<IClient extends { emit: Function }>(
|
||||
client: IClient,
|
||||
exception: T,
|
||||
) {
|
||||
const status = 'error';
|
||||
|
||||
if (!(exception instanceof WsException)) {
|
||||
const errorMessage = MESSAGES.UNKNOWN_EXCEPTION_MESSAGE;
|
||||
return client.emit('exception', { status, message: errorMessage });
|
||||
return client.emit('exception', {
|
||||
status,
|
||||
message: MESSAGES.UNKNOWN_EXCEPTION_MESSAGE,
|
||||
});
|
||||
}
|
||||
const result = exception.getError();
|
||||
const message = isObject(result)
|
||||
@@ -19,6 +28,7 @@ export class BaseWsExceptionFilter<T = any> implements WsExceptionFilter<T> {
|
||||
status,
|
||||
message: result,
|
||||
};
|
||||
|
||||
client.emit('exception', message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export * from './base-ws-exception-filter';
|
||||
export * from './ws-exception';
|
||||
|
||||
@@ -2,7 +2,7 @@ import { ArgumentsHost } from '@nestjs/common';
|
||||
import { ExceptionFilterMetadata } from '@nestjs/common/interfaces/exceptions/exception-filter-metadata.interface';
|
||||
import { isEmpty } from '@nestjs/common/utils/shared.utils';
|
||||
import { InvalidExceptionFilterException } from '@nestjs/core/errors/exceptions/invalid-exception-filter.exception';
|
||||
import { WsException } from '../exceptions/ws-exception';
|
||||
import { WsException } from '../errors/ws-exception';
|
||||
import { BaseWsExceptionFilter } from './base-ws-exception-filter';
|
||||
|
||||
export class WsExceptionsHandler extends BaseWsExceptionFilter {
|
||||
@@ -23,7 +23,10 @@ export class WsExceptionsHandler extends BaseWsExceptionFilter {
|
||||
this.filters = filters;
|
||||
}
|
||||
|
||||
public invokeCustomFilters(exception, args: ArgumentsHost): boolean {
|
||||
public invokeCustomFilters<T = any>(
|
||||
exception: T,
|
||||
args: ArgumentsHost,
|
||||
): boolean {
|
||||
if (isEmpty(this.filters)) return false;
|
||||
|
||||
const filter = this.filters.find(({ exceptionMetatypes }) => {
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'reflect-metadata';
|
||||
|
||||
export * from './adapters/io-adapter';
|
||||
export * from './adapters/ws-adapter';
|
||||
export * from './errors';
|
||||
export * from './exceptions';
|
||||
export { MessageMappingProperties } from './gateway-metadata-explorer';
|
||||
export * from './interfaces';
|
||||
|
||||
@@ -22,7 +22,7 @@ export class SocketModule {
|
||||
private applicationConfig: ApplicationConfig;
|
||||
private webSocketsController: WebSocketsController;
|
||||
|
||||
public register(container, config) {
|
||||
public register<TContainer, TConfig>(container: any, config: any) {
|
||||
this.applicationConfig = config;
|
||||
this.webSocketsController = new WebSocketsController(
|
||||
new SocketServerProvider(this.socketsContainer, config),
|
||||
@@ -30,16 +30,16 @@ export class SocketModule {
|
||||
this.getContextCreator(container),
|
||||
);
|
||||
const modules = container.getModules();
|
||||
modules.forEach(({ components }, moduleName) =>
|
||||
this.hookGatewaysIntoServers(components, moduleName),
|
||||
modules.forEach(({ providers }, moduleName) =>
|
||||
this.hookGatewaysIntoServers(providers, moduleName),
|
||||
);
|
||||
}
|
||||
|
||||
public hookGatewaysIntoServers(
|
||||
components: Map<string, InstanceWrapper<Injectable>>,
|
||||
providers: Map<string, InstanceWrapper<Injectable>>,
|
||||
moduleName: string,
|
||||
) {
|
||||
components.forEach(wrapper =>
|
||||
providers.forEach(wrapper =>
|
||||
this.hookGatewayIntoServer(wrapper, moduleName),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { expect } from 'chai';
|
||||
import { of } from 'rxjs';
|
||||
import * as sinon from 'sinon';
|
||||
import { Guard, Injectable, UseGuards, UsePipes } from '../../../common';
|
||||
import { GuardsConsumer } from '../../../core/guards/guards-consumer';
|
||||
import { GuardsContextCreator } from '../../../core/guards/guards-context-creator';
|
||||
import { NestContainer } from '../../../core/injector/container';
|
||||
@@ -8,17 +9,10 @@ import { InterceptorsConsumer } from '../../../core/interceptors/interceptors-co
|
||||
import { InterceptorsContextCreator } from '../../../core/interceptors/interceptors-context-creator';
|
||||
import { PipesConsumer } from '../../../core/pipes/pipes-consumer';
|
||||
import { PipesContextCreator } from '../../../core/pipes/pipes-context-creator';
|
||||
import { WsException } from '../../index';
|
||||
import {
|
||||
Component,
|
||||
Guard,
|
||||
Injectable,
|
||||
UseGuards,
|
||||
UsePipes,
|
||||
} from '../../../common';
|
||||
import { ExceptionFiltersContext } from '../../context/exception-filters-context';
|
||||
import { WsContextCreator } from '../../context/ws-context-creator';
|
||||
import { WsProxy } from '../../context/ws-proxy';
|
||||
import { WsException } from '../../index';
|
||||
|
||||
@Guard()
|
||||
class TestGuard {
|
||||
@@ -44,7 +38,7 @@ describe('WsContextCreator', () => {
|
||||
let module: string;
|
||||
|
||||
@UseGuards(TestGuard)
|
||||
@Component()
|
||||
@Injectable()
|
||||
class Test {
|
||||
@UsePipes(new TestPipe())
|
||||
test(client: string, data: number) {
|
||||
|
||||
@@ -2,7 +2,7 @@ import * as sinon from 'sinon';
|
||||
import { expect } from 'chai';
|
||||
import { WsProxy } from '../../context/ws-proxy';
|
||||
import { WsExceptionsHandler } from '../../exceptions/ws-exceptions-handler';
|
||||
import { WsException } from '../../exceptions/ws-exception';
|
||||
import { WsException } from '../../errors/ws-exception';
|
||||
|
||||
describe('WsProxy', () => {
|
||||
let routerProxy: WsProxy;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import * as sinon from 'sinon';
|
||||
import { expect } from 'chai';
|
||||
import { WsException } from '../../exceptions/ws-exception';
|
||||
import { WsException } from '../../errors/ws-exception';
|
||||
|
||||
describe('WsException', () => {
|
||||
let instance: WsException;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as sinon from 'sinon';
|
||||
import { expect } from 'chai';
|
||||
import { WsExceptionsHandler } from '../../exceptions/ws-exceptions-handler';
|
||||
import { WsException } from '../../exceptions/ws-exception';
|
||||
import { WsException } from '../../errors/ws-exception';
|
||||
import { ExecutionContextHost } from '@nestjs/core/helpers/execution-context.host';
|
||||
|
||||
describe('WsExceptionsHandler', () => {
|
||||
|
||||
@@ -5,7 +5,7 @@ import * as sinon from 'sinon';
|
||||
import { MetadataScanner } from '../../core/metadata-scanner';
|
||||
import { PORT_METADATA } from '../constants';
|
||||
import { WsContextCreator } from '../context/ws-context-creator';
|
||||
import { InvalidSocketPortException } from '../exceptions/invalid-socket-port.exception';
|
||||
import { InvalidSocketPortException } from '../errors/invalid-socket-port.exception';
|
||||
import { GatewayMetadataExplorer } from '../gateway-metadata-explorer';
|
||||
import { IoAdapter } from '../index';
|
||||
import { SocketServerProvider } from '../socket-server-provider';
|
||||
|
||||
@@ -6,7 +6,7 @@ import { from as fromPromise, Observable, of, Subject } from 'rxjs';
|
||||
import { distinctUntilChanged, mergeAll } from 'rxjs/operators';
|
||||
import { GATEWAY_OPTIONS, PORT_METADATA } from './constants';
|
||||
import { WsContextCreator } from './context/ws-context-creator';
|
||||
import { InvalidSocketPortException } from './exceptions/invalid-socket-port.exception';
|
||||
import { InvalidSocketPortException } from './errors/invalid-socket-port.exception';
|
||||
import {
|
||||
GatewayMetadataExplorer,
|
||||
MessageMappingProperties,
|
||||
|
||||
Reference in New Issue
Block a user