import { Container, interfaces } from 'inversify'; import { ServiceIdentifiers } from './ServiceIdentifiers'; import { analyzersModule } from './modules/analyzers/AnalyzersModule'; import { codeTransformersModule } from './modules/code-transformers/CodeTransformersModule'; import { controlFlowTransformersModule } from './modules/node-transformers/ControlFlowTransformersModule'; import { convertingTransformersModule } from './modules/node-transformers/ConvertingTransformersModule'; import { customCodeHelpersModule } from './modules/custom-code-helpers/CustomCodeHelpersModule'; import { customNodesModule } from './modules/custom-nodes/CustomNodesModule'; import { deadCodeInjectionTransformersModule } from './modules/node-transformers/DeadCodeInjectionTransformersModule'; import { finalizingTransformersModule } from './modules/node-transformers/FinalizingTransformersModule'; import { generatorsModule } from './modules/generators/GeneratorsModule'; import { initializingTransformersModule } from './modules/node-transformers/InitializingTransformersModule'; import { nodeModule } from './modules/node/NodeModule'; import { nodeTransformersModule } from './modules/node-transformers/NodeTransformersModule'; import { optionsModule } from './modules/options/OptionsModule'; import { preparingTransformersModule } from './modules/node-transformers/PreparingTransformersModule'; import { renameIdentifiersTransformersModule } from './modules/node-transformers/RenameIdentifiersTransformersModule'; import { renamePropertiesTransformersModule } from './modules/node-transformers/RenamePropertiesTransformersModule'; import { simplifyingTransformersModule } from './modules/node-transformers/SimplifyingTransformersModule'; import { storagesModule } from './modules/storages/StoragesModule'; import { stringArrayTransformersModule } from './modules/node-transformers/StringArrayTransformersModule'; import { utilsModule } from './modules/utils/UtilsModule'; import { TInputOptions } from '../types/options/TInputOptions'; import { ICodeTransformersRunner } from '../interfaces/code-transformers/ICodeTransformersRunner'; import { IInversifyContainerFacade } from '../interfaces/container/IInversifyContainerFacade'; import { IJavaScriptObfuscator } from '../interfaces/IJavaScriptObfsucator'; import { ILogger } from '../interfaces/logger/ILogger'; import { IObfuscatedCode } from '../interfaces/source-code/IObfuscatedCode'; import { ISourceCode } from '../interfaces/source-code/ISourceCode'; import { INodeTransformersRunner } from '../interfaces/node-transformers/INodeTransformersRunner'; import { CodeTransformersRunner } from '../code-transformers/CodeTransformersRunner'; import { JavaScriptObfuscator } from '../JavaScriptObfuscator'; import { Logger } from '../logger/Logger'; import { NodeTransformersRunner } from '../node-transformers/NodeTransformersRunner'; import { ObfuscatedCode } from '../source-code/ObfuscatedCode'; import { SourceCode } from '../source-code/SourceCode'; export class InversifyContainerFacade implements IInversifyContainerFacade { /** * @type {interfaces.Container} */ private readonly container: interfaces.Container; public constructor () { this.container = new Container(); } /** * @param {interfaces.ServiceIdentifier} serviceIdentifier * @returns {U} */ public static getFactory ( serviceIdentifier: interfaces.ServiceIdentifier ): (context: interfaces.Context) => (bindingName: T) => U { return (context: interfaces.Context): (bindingName: T) => U => { return (bindingName: T): U => { return context.container.getNamed(serviceIdentifier, bindingName); }; }; } /** * @param {interfaces.ServiceIdentifier} serviceIdentifier * @returns {U} */ public static getCacheFactory ( serviceIdentifier: interfaces.ServiceIdentifier ): (context: interfaces.Context) => (bindingName: T) => U { return (context: interfaces.Context): (bindingName: T) => U => { const cache: Map = new Map(); return (bindingName: T): U => { if (cache.has(bindingName)) { return cache.get(bindingName); } const object: U = context.container.getNamed(serviceIdentifier, bindingName); cache.set(bindingName, object); return object; }; }; } /** * @param {interfaces.ServiceIdentifier>} serviceIdentifier * @param {interfaces.ServiceIdentifier>[]} dependencies * @returns {U} */ public static getConstructorFactory ( serviceIdentifier: interfaces.ServiceIdentifier>, ...dependencies: interfaces.ServiceIdentifier>>[] ): (context: interfaces.Context) => (bindingName: T) => U { return (context: interfaces.Context): (bindingName: T) => U => { const cache: Map> = new Map(); const cachedDependencies: Record[] = []; return (bindingName: T): U => { dependencies.forEach(( dependency: interfaces.ServiceIdentifier>>, index: number ) => { if (!cachedDependencies[index]) { cachedDependencies[index] = context.container.get(dependency); } }); if (cache.has(bindingName)) { return new (>cache.get(bindingName))(...cachedDependencies); } const constructor: interfaces.Newable = context.container .getNamed>( serviceIdentifier, bindingName ); cache.set(bindingName, constructor); return new constructor(...cachedDependencies); }; }; } /** * @param {interfaces.ServiceIdentifier} serviceIdentifier * @returns {T} */ public get (serviceIdentifier: interfaces.ServiceIdentifier): T { return this.container.get(serviceIdentifier); } /** * @param {interfaces.ServiceIdentifier} serviceIdentifier * @param {string | number | symbol} named * @returns {T} */ public getNamed (serviceIdentifier: interfaces.ServiceIdentifier, named: string | number | symbol): T { return this.container.getNamed(serviceIdentifier, named); } /** * @param {string} sourceCode * @param {string} sourceMap * @param {TInputOptions} options */ public load (sourceCode: string, sourceMap: string, options: TInputOptions): void { this.container .bind(ServiceIdentifiers.ISourceCode) .toDynamicValue(() => new SourceCode(sourceCode, sourceMap)) .inSingletonScope(); this.container .bind(ServiceIdentifiers.TInputOptions) .toDynamicValue(() => options) .inSingletonScope(); this.container .bind(ServiceIdentifiers.ILogger) .to(Logger) .inSingletonScope(); this.container .bind(ServiceIdentifiers.IJavaScriptObfuscator) .to(JavaScriptObfuscator) .inSingletonScope(); this.container .bind(ServiceIdentifiers.ICodeTransformersRunner) .to(CodeTransformersRunner) .inSingletonScope(); this.container .bind(ServiceIdentifiers.INodeTransformersRunner) .to(NodeTransformersRunner) .inSingletonScope(); this.container .bind(ServiceIdentifiers.IObfuscatedCode) .to(ObfuscatedCode); this.container .bind(ServiceIdentifiers.Factory__IObfuscatedCode) .toFactory((context: interfaces.Context) => { return (obfuscatedCodeAsString: string, sourceMapAsString: string): IObfuscatedCode => { const obfuscatedCode: IObfuscatedCode = context.container .get(ServiceIdentifiers.IObfuscatedCode); obfuscatedCode.initialize(obfuscatedCodeAsString, sourceMapAsString); return obfuscatedCode; }; }); // modules this.container.load(analyzersModule); this.container.load(codeTransformersModule); this.container.load(controlFlowTransformersModule); this.container.load(convertingTransformersModule); this.container.load(customCodeHelpersModule); this.container.load(customNodesModule); this.container.load(deadCodeInjectionTransformersModule); this.container.load(finalizingTransformersModule); this.container.load(generatorsModule); this.container.load(initializingTransformersModule); this.container.load(nodeModule); this.container.load(nodeTransformersModule); this.container.load(optionsModule); this.container.load(preparingTransformersModule); this.container.load(renameIdentifiersTransformersModule); this.container.load(renamePropertiesTransformersModule); this.container.load(simplifyingTransformersModule); this.container.load(storagesModule); this.container.load(stringArrayTransformersModule); this.container.load(utilsModule); } public unload (): void { this.container.unbindAll(); } }