All files / src dependencyInjector.ts

98.33% Statements 59/60
66.66% Branches 2/3
100% Functions 11/11
98.33% Lines 59/60

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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 1248x 8x 8x 8x                 8x 8x 8x 8x 8x   8x 8x 8x   8x   8x 8x     8x 8x 8x 8x     8x           8x   8x       161x 8x     161x       131x     8x     22x     8x       8x 8x 8x 8x       8x   8x 8x 8x 8x 8x 8x 8x 8x   8x   8x 8x 8x   8x 8x 8x 8x   8x           8x     32x   5x 22x   22x   22x             22x   22x    
import { Container, interfaces } from 'inversify';
import GmailCardOperationStrategy from './gmail/strategies/gmailCardOperationStrategy';
import GmailTransactionProvider from './gmail/providers/gmailTransactionProvider';
import TransactionRepository from './core/repositories/transactionRepository';
import {
    ICardOperationStrategy,
    ICrossBorderTransferFeeStrategy,
    ICrossBorderTransferStrategy,
    IDeskWithdrawalStrategy,
    IStandardFeeStrategy,
    IStandardTransferStrategy
} from "./core/types/paymentDetailsStrategies";
import { injectables } from './core/types/injectables';
import GmailStandardTransferStrategy from './gmail/strategies/gmailStandardTransferStrategy';
import GmailStandardFeeStrategy from './gmail/strategies/gmailStandardFeeStrategy';
import GmailDeskWithdrawalStrategy from './gmail/strategies/gmailDeskWIthdrawalStrategy';
import GmailCrossBorderTransferStrategy from './gmail/strategies/gmailCrossBorderTransferStrategy';
import ITransactionDataProvider from './core/contracts/ITransactionDataProvider';
import GmailTransactionDataProvider from './gmail/providers/gmailTransactionDataProvider';
import PaymentDetailsFactory from './core/factories/paymentDetailsFactory';
import PaymentDetailsContext from './core/contexts/paymentDetailsContext';
import ITransactionSourceProvider from './core/contracts/ITransactionSourceProvider';
import GmailTransactionSourceProvider from './gmail/providers/gmailTransactionSourceProvider';
import ILogger from './core/contracts/ILogger';
import WinstonLokiLogger from './core/loggers/winstonLokiLogger';
import GmailCrossBorderTransferFeeStrategy from './gmail/strategies/gmailCrossBorderTransferFeeStrategy';
import GoogleOAuth2Identifiers from './googleOAuth2/types/googleOAuth2Identifiers';
import IUsesGoogleOAuth2 from './googleOAuth2/contracts/IUsesGoogleOAuth2';
import GoogleOAuth2TokensRepository from './googleOAuth2/repositories/googleOAuth2TokensRepository';
import GoogleOAuth2ClientProvider from './googleOAuth2/providers/googleOAuth2ClientProvider';
import GmailApiClient from './gmail/clients/gmailApiClient';
import ServiceContexts from './core/enums/serviceContexts';
import ITransactionProvider from './core/contracts/ITransactionProvider';
 
export class DependencyInjector {
    private static singleton: DependencyInjector;
 
    private readonly container: Container;
    
    private constructor() {
        this.container = new Container();
 
        this.registerCoreServices();
    }
 
    public static get Singleton() {
        if (this.singleton === undefined) {
            this.singleton = new this();
        }
 
        return this.singleton;
    }
 
    public resolve<T>(serviceIdentifier: interfaces.ServiceIdentifier<T>) {
        return this.container.get<T>(serviceIdentifier);
    }
 
    public generateGmailServiceAsync = <T>(
        providerIdentifier: interfaces.ServiceIdentifier<interfaces.Provider<T>>,
        oauth2Identifiers: GoogleOAuth2Identifiers) => 
            this.generateServiceAsync(providerIdentifier, oauth2Identifiers);
 
    public registerGmailServices() {
        this.registerServicesByContext(ServiceContexts.GMAIL);
    }
 
    private registerCoreServices() {
        this.container.bind<ILogger>(injectables.ILogger).to(WinstonLokiLogger).inSingletonScope();
        this.container.bind<PaymentDetailsFactory>(injectables.PaymentDetailsFactory).to(PaymentDetailsFactory);
        this.container.bind<PaymentDetailsContext>(injectables.PaymentDetailsContext).to(PaymentDetailsContext);
        this.container.bind<TransactionRepository>(injectables.TransactionRepository).to(TransactionRepository);
    }
 
    private registerServicesByContext(context: ServiceContexts) {
        switch(context) {
            case ServiceContexts.GMAIL:
                this.container.bind<ICardOperationStrategy>(injectables.ICardOperationStrategy).to(GmailCardOperationStrategy);
                this.container.bind<ICrossBorderTransferStrategy>(injectables.ICrossBorderTransferStrategy).to(GmailCrossBorderTransferStrategy);
                this.container.bind<ICrossBorderTransferFeeStrategy>(injectables.ICrossBorderTransferFeeStrategy).to(GmailCrossBorderTransferFeeStrategy);
                this.container.bind<IDeskWithdrawalStrategy>(injectables.IDeskWithdrawalStrategy).to(GmailDeskWithdrawalStrategy);
                this.container.bind<IStandardFeeStrategy>(injectables.IStandardFeeStrategy).to(GmailStandardFeeStrategy);
                this.container.bind<IStandardTransferStrategy>(injectables.IStandardTransferStrategy).to(GmailStandardTransferStrategy);
                this.container.bind<ITransactionDataProvider>(injectables.ITransactionDataProvider).to(GmailTransactionDataProvider);
                this.container.bind<ITransactionProvider>(injectables.ITransactionProvider).to(GmailTransactionProvider);
 
                this.container.bind<GoogleOAuth2TokensRepository>(injectables.GoogleOAuth2TokensRepository).to(GoogleOAuth2TokensRepository);
 
                this.container.bind<ITransactionSourceProvider>(injectables.ITransactionSourceProvider).to(GmailTransactionSourceProvider);
                this.container.bind<GoogleOAuth2ClientProvider>(injectables.GoogleOAuth2ClientProvider).to(GoogleOAuth2ClientProvider).inRequestScope();
                this.container.bind<GmailApiClient>(injectables.GmailApiClient).to(GmailApiClient).inRequestScope();
 
                this.registerGoogleServiceGenerator(injectables.GoogleOAuth2ClientProviderGenerator, injectables.GoogleOAuth2ClientProvider);
                this.registerGoogleServiceGenerator(injectables.GmailApiClientGenerator, injectables.GmailApiClient);
                this.registerGoogleServiceGenerator(injectables.GmailTransactionSourceProviderGenerator, injectables.ITransactionSourceProvider);
                this.registerGoogleServiceGenerator(injectables.GmailTransactionProviderGenerator, injectables.ITransactionProvider);
 
                break;
            default:
                throw new Error(`Unrecognised service context '${context}'`);
        }
    }
 
    private registerGoogleServiceGenerator = <T extends IUsesGoogleOAuth2>(
        generatorIdentifier: interfaces.ServiceIdentifier<interfaces.Provider<T>>,
        serviceIdentifier: interfaces.ServiceIdentifier<T>) => 
            this.container.bind<interfaces.Provider<T>>(generatorIdentifier)
                .toProvider((context) => {
                    return async (identifiers: GoogleOAuth2Identifiers) => {
                        const service = context.container.get<T>(serviceIdentifier);
        
                        await service.useOAuth2IdentifiersAsync(identifiers);
        
                        return service;
                    }
                });
 
    private generateServiceAsync<T>(
        providerIdentifier: interfaces.ServiceIdentifier<interfaces.Provider<T>>,
        ...args: Record<string, unknown>[]) {
        const provider = this.container.get<interfaces.Provider<T>>(providerIdentifier);
 
        return provider(...args) as Promise<T>;
    }
}