All files / common/decorators/modules module.decorator.ts

100% Statements 28/28
91.67% Branches 11/12
100% Functions 8/8
100% Lines 26/26
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 701x 1x   1x   1x                 1x 119x 14x 31x 30x   1x   14x                       1x 14x   14x 13x 13x   13x 13x 46x 46x             13x       13x             13x   13x   13x 13x    
import * as deprecate from 'deprecate';
import { METADATA as metadataConstants } from '../../constants';
import { ModuleMetadata } from '../../interfaces/modules/module-metadata.interface';
import { InvalidModuleConfigException } from './exceptions/invalid-module-config.exception';
 
const metadataKeys = [
  metadataConstants.MODULES,
  metadataConstants.IMPORTS,
  metadataConstants.EXPORTS,
  metadataConstants.COMPONENTS,
  metadataConstants.CONTROLLERS,
  metadataConstants.PROVIDERS,
];
 
const validateKeys = (keys: string[]) => {
  const isKeyInvalid = key => metadataKeys.findIndex(k => k === key) < 0;
  const validateKey = key => {
    if (!isKeyInvalid(key)) {
      return;
    }
    throw new InvalidModuleConfigException(key);
  };
  keys.forEach(validateKey);
};
 
/**
 * Defines the module
 * - `imports` - the set of the 'imported' modules
 * - `controllers` - the list of controllers (e.g. HTTP controllers)
 * - `providers` - the list of providers that belong to this module. They can be injected between themselves.
 * - `exports` - the set of components, which should be available for modules, which imports this module
 * - `components` - @deprecated the list of components that belong to this module. They can be injected between themselves.
 * @param options {ModuleMetadata} Module metadata
 */
export function Module(metadata: ModuleMetadata): ClassDecorator {
  const propsKeys = Object.keys(metadata);
 
  validateKeys(propsKeys);
  showDeprecatedWarnings(metadata);
  overrideModuleMetadata(metadata);
 
  return (target: object) => {
    for (const property in metadata) {
      Eif (metadata.hasOwnProperty(property)) {
        Reflect.defineMetadata(property, metadata[property], target);
      }
    }
  };
}
 
function overrideModuleMetadata(moduleMetadata: ModuleMetadata) {
  moduleMetadata.modules = moduleMetadata.imports
    ? moduleMetadata.imports
    : moduleMetadata.modules;
 
  moduleMetadata.components = moduleMetadata.providers
    ? moduleMetadata.providers
    : moduleMetadata.components;
}
 
function showDeprecatedWarnings(moduleMetadata: ModuleMetadata) {
  const MODULES_DEPRECATED_WARNING =
    'The "modules" key in the @Module() decorator is deprecated and will be removed within next major release. Use the "imports" key instead.';
  const COMPONENTS_DEPRECATED_WARNING =
    'The "components" key in the @Module() decorator is deprecated and will be removed within next major release. Use the "providers" key instead.';
 
  moduleMetadata.modules && deprecate(MODULES_DEPRECATED_WARNING);
  moduleMetadata.components && deprecate(COMPONENTS_DEPRECATED_WARNING);
}