All files / decorators/module module.decorator.ts

54.39% Statements 31/57
14.29% Branches 4/28
40% Functions 2/5
54.39% Lines 31/57

Press n or j to go to the next uncovered block, b, p or k for the previous block.

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 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 1081x 1x 1x 1x 1x   1x 1x   1x 1x 1x 1x 1x   1x   1x 1x 1x 1x 1x 1x 1x         1x 1x   1x   1x               1x         1x   1x         1x                                                                                           1x       1x 1x      
import { Container, ServiceMetadata } from '../../container';
import { CacheService } from '../../services/cache/cache-layer.service';
import { GenericConstruct } from '../../helpers/generic-constructor';
import { BootstrapLogger } from '../../services/bootstrap-logger/bootstrap-logger';
import { ResolverService } from '../../services/resolver/resolver.service';
import { ModuleArguments, ModuleWithServices } from '../module/module.interfaces';
import { MetadataService } from '../../services/metadata/metadata.service';
import { ModuleService } from '../../services/module/module.service';
 
const bootstrapLogger = Container.get(BootstrapLogger);
const resolverService = Container.get(ResolverService);
const cacheService = Container.get(CacheService);
const metadataService = Container.get(MetadataService);
const moduleService = Container.get(ModuleService);
 
export function Module<T, K extends keyof T>(module?: ModuleArguments<T, K>): Function {
 
    return (target) => {
        module = module || {};
        const original = Object.assign(target);
        const moduleName = target.name || target.constructor.name;
        const generatedHashData = metadataService.generateHashData(module, original);
        const uniqueModuleTemplate = metadataService.parseModuleTemplate(moduleName, generatedHashData, `${target}`);
        const uniqueHashForClass = metadataService.createUniqueHash(uniqueModuleTemplate);
 
        // console.log(`--------- ${moduleName} --------- Hash: ${uniqueHashForClass}---------`);
        // console.log(uniqueModuleTemplate);
 
        Object.defineProperty(original, 'originalName', { value: original.name || original.constructor.name, writable: false });
        Object.defineProperty(original, 'name', { value: uniqueHashForClass, writable: true });
 
        const currentModule = cacheService.createLayer<boolean>({ name: uniqueHashForClass });
 
        original['metadata'] = {
            moduleName: original['originalName'],
            moduleHash: uniqueHashForClass,
            options: null,
            type: 'module',
            raw: uniqueModuleTemplate
        };
 
        const constructorFunction: any = function (...args) {
            bootstrapLogger.log(`Bootstrap -> @Module('${original.originalName}')${bootstrapLogger.logHashes(`(${original.name})`)}: loading...`);
            return GenericConstruct(module, original, currentModule)(original, args);
        };
 
        Object.assign(constructorFunction, original);
 
        resolverService.resolveDependencies(uniqueHashForClass, original, moduleName)
            .subscribe(
                () => bootstrapLogger.log(`Start -> @Module('${original.originalName}')${bootstrapLogger.logHashes(`(${original.name})`)}: loaded!`)
            );
 
        Iif (original.forRoot) {
            constructorFunction.forRoot = original.forRoot;
            const originalForRoot = constructorFunction.forRoot;
            constructorFunction.forRoot = function (args) {
                const result: ModuleWithServices = originalForRoot(args);
 
                if (!result) {
                    throw new Error(`forRoot configuration inside ${constructorFunction.name} is returning undefined or null`);
                }
 
                if (result.frameworkImports) {
                    moduleService.setImports(result.frameworkImports, original);
                }
 
                if (result.services) {
                    moduleService.setServices(<any>result.services, original, currentModule);
                }
 
                if (result.components) {
                    moduleService.setComponents(<any>result.components, original, currentModule);
                }
 
                if (result.effects) {
                    moduleService.setEffects(<any>result.effects, original, currentModule);
                }
 
                if (result.controllers) {
                    moduleService.setControllers(<any>result.controllers, original, currentModule);
                }
 
                if (result.beforePlugins) {
                    moduleService.setBeforePlugins(result.beforePlugins, original, currentModule);
                }
 
                if (result.plugins) {
                    moduleService.setPlugins(result.plugins, original, currentModule);
                }
 
                if (result.afterPlugins) {
                    moduleService.setAfterPlugins(result.afterPlugins, original, currentModule);
                }
 
                return result.module ? result.module : result;
            };
        }
 
        const service: ServiceMetadata<T, K> = {
            type: constructorFunction
        };
 
        Container.set(service);
        return constructorFunction;
    };
}