From fc391a02e5c85bfa269f04ce8724c653e2f1d8e0 Mon Sep 17 00:00:00 2001 From: Xymorot Date: Sat, 8 Aug 2020 18:23:29 +0200 Subject: [PATCH] feat: make services gettable and injectable by simple strings and not needing to call Symbol.for every time --- src/main.ts | 10 +++---- src/main/core/container.ts | 28 +++++++++++++------ src/main/core/inject.ts | 5 ++++ src/main/modules/ipc/annotations/answer.ts | 2 +- src/main/modules/logger/logger.spec.ts | 14 +++++----- src/main/modules/nhentai/nhentai-api.ts | 5 ++-- .../modules/nhentai/nhentai-ipc-controller.ts | 2 +- src/main/modules/store/store.spec.ts | 2 +- .../modules/web-crawler/web-crawler.spec.ts | 10 +++---- src/main/modules/web-crawler/web-crawler.ts | 5 ++-- 10 files changed, 51 insertions(+), 32 deletions(-) create mode 100644 src/main/core/inject.ts diff --git a/src/main.ts b/src/main.ts index e92d78c..a250a1a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -13,22 +13,22 @@ import { ISession } from './main/modules/session/i-session'; * https://nodejs.org/api/process.html#process_event_unhandledrejection */ process.on('unhandledRejection', (reason) => { - const logger: ILogger = container.get(Symbol.for('logger')); + const logger: ILogger = container.get('logger'); void logger.fatal(`Unhandled Rejection, see ${logger.getExceptionsLogFile()}`); throw reason; }); process.on('uncaughtException', (error) => { - const logger: ILogger = container.get(Symbol.for('logger')); + const logger: ILogger = container.get('logger'); void logger.exception(error); throw error; }); async function createWindow(): Promise { - const session: ISession = container.get(Symbol.for('session')); + const session: ISession = container.get('session'); session.setHeaders(); - const appWindowMain: IAppWindow = container.get(Symbol.for('app-window-main')); + const appWindowMain: IAppWindow = container.get('app-window-main'); // and load the index.html of the app. await appWindowMain.open(); @@ -57,7 +57,7 @@ app.on('window-all-closed', () => { app.on('activate', async () => { // On OS X it"s common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. - const appWindowMain: IAppWindow = container.get(Symbol.for('app-window-main')); + const appWindowMain: IAppWindow = container.get('app-window-main'); if (appWindowMain.isClosed()) { await createWindow(); } diff --git a/src/main/core/container.ts b/src/main/core/container.ts index 96ea370..6ab9cee 100644 --- a/src/main/core/container.ts +++ b/src/main/core/container.ts @@ -1,5 +1,5 @@ import 'reflect-metadata'; -import { Container } from 'inversify'; +import { Container, interfaces } from 'inversify'; import { MainAppWindow } from '../modules/app-window/main-app-window'; import { Logger } from '../modules/logger/logger'; import { NhentaiApi } from '../modules/nhentai/nhentai-api'; @@ -7,17 +7,29 @@ import '../modules/nhentai/nhentai-ipc-controller'; import { Session } from '../modules/session/session'; import { Store } from '../modules/store/store'; import { WebCrawler } from '../modules/web-crawler/web-crawler'; +import BindingToSyntax = interfaces.BindingToSyntax; -export const container = new Container({ defaultScope: 'Singleton' }); +export const container = { + original: new Container({ defaultScope: 'Singleton' }), + bind(key: string): BindingToSyntax { + return this.original.bind(Symbol.for(key)); + }, + unbind(key: string): void { + return this.original.unbind(Symbol.for(key)); + }, + get(key: string): T { + return this.original.get(Symbol.for(key)); + }, +}; -container.bind(Symbol.for('store')).to(Store); +container.bind('store').to(Store); -container.bind(Symbol.for('web-crawler')).to(WebCrawler); +container.bind('web-crawler').to(WebCrawler); -container.bind(Symbol.for('nhentai-api')).to(NhentaiApi); +container.bind('nhentai-api').to(NhentaiApi); -container.bind(Symbol.for('app-window-main')).to(MainAppWindow); +container.bind('app-window-main').to(MainAppWindow); -container.bind(Symbol.for('session')).to(Session); +container.bind('session').to(Session); -container.bind(Symbol.for('logger')).to(Logger); +container.bind('logger').to(Logger); diff --git a/src/main/core/inject.ts b/src/main/core/inject.ts new file mode 100644 index 0000000..d4172d5 --- /dev/null +++ b/src/main/core/inject.ts @@ -0,0 +1,5 @@ +import { inject as inversifyInject } from 'inversify'; + +export function inject(key: string): ReturnType { + return inversifyInject(Symbol.for(key)); +} diff --git a/src/main/modules/ipc/annotations/answer.ts b/src/main/modules/ipc/annotations/answer.ts index 6ecefd4..b20cff5 100644 --- a/src/main/modules/ipc/annotations/answer.ts +++ b/src/main/modules/ipc/annotations/answer.ts @@ -1,6 +1,6 @@ import { registerHandler } from '../ipc-server'; -export function answer(channel: IpcChannel): DecoratorFactory { +export function answer(channel: IpcChannel): DecoratorFactory { return function (target: IIpcController, propertyKey): void { registerHandler(channel, target, propertyKey); }; diff --git a/src/main/modules/logger/logger.spec.ts b/src/main/modules/logger/logger.spec.ts index 041e35b..7aa20c6 100644 --- a/src/main/modules/logger/logger.spec.ts +++ b/src/main/modules/logger/logger.spec.ts @@ -53,20 +53,20 @@ describe('Logger Service', () => { }); it('creates log files', () => { - const logger: ILogger = container.get(Symbol.for('logger')); + const logger: ILogger = container.get('logger'); expect(logger.getLogFile()).path('log file is not created'); expect(logger.getExceptionsLogFile()).path('exception log file is not created'); }); it('logs exceptions', async () => { - const logger: ILogger = container.get(Symbol.for('logger')); + const logger: ILogger = container.get('logger'); await logger.exception(new Error('this is an error')); }); it("default log file doesn't get bigger than 50KB @slow", async () => { - const logger: ILogger = container.get(Symbol.for('logger')); + const logger: ILogger = container.get('logger'); for (let i = 0; i < maxLogSize; i++) { await logger.log(4, 'your waifu is trash'); @@ -77,7 +77,7 @@ describe('Logger Service', () => { }).timeout(15000); it("exception log file doesn't get bigger than 50KB @slow", async () => { - const logger: ILogger = container.get(Symbol.for('logger')); + const logger: ILogger = container.get('logger'); for (let i = 0; i < maxLogSize; ++i) { await logger.exception(new Error('your waifu is trash')); @@ -88,7 +88,7 @@ describe('Logger Service', () => { }).timeout(15000); it('logs different levels directly', () => { - const logger: ILogger = container.get(Symbol.for('logger')); + const logger: ILogger = container.get('logger'); return fc.assert( fc.asyncProperty(logLevelArbitrary as LogLevelArbitrary, fc.string(), async (logLevel, message) => { @@ -104,7 +104,7 @@ describe('Logger Service', () => { }); it('logs different levels indirectly via the generic log function', () => { - const logger: ILogger = container.get(Symbol.for('logger')); + const logger: ILogger = container.get('logger'); return fc.assert( fc.asyncProperty(logLevelNumberArbitrary, fc.string(), async (logLevelNumber, message) => { @@ -123,7 +123,7 @@ describe('Logger Service', () => { }); it('logs debug only in dev mode', async () => { - const logger: ILogger = container.get(Symbol.for('logger')); + const logger: ILogger = container.get('logger'); setDev(); await logger.debug('this is a development message'); diff --git a/src/main/modules/nhentai/nhentai-api.ts b/src/main/modules/nhentai/nhentai-api.ts index afe018a..336c50e 100644 --- a/src/main/modules/nhentai/nhentai-api.ts +++ b/src/main/modules/nhentai/nhentai-api.ts @@ -1,6 +1,7 @@ -import { inject, injectable } from 'inversify'; +import { injectable } from 'inversify'; import { JSDOM } from 'jsdom'; import { RequestInit, Response } from 'node-fetch'; +import { inject } from '../../core/inject'; import { WebCrawlerFormError } from '../error/web-crawler-form-error'; import { WebCrawlerLoginError } from '../error/web-crawler-login-error'; import { IWebCrawler } from '../web-crawler/i-web-crawler'; @@ -33,7 +34,7 @@ interface ILoginParams extends ILoginMeta, ILoginAuth {} export class NhentaiApi implements INhentaiApi { private webCrawler: IWebCrawler; - public constructor(@inject(Symbol.for('web-crawler')) webCrawler: IWebCrawler) { + public constructor(@inject('web-crawler') webCrawler: IWebCrawler) { this.webCrawler = webCrawler; } diff --git a/src/main/modules/nhentai/nhentai-ipc-controller.ts b/src/main/modules/nhentai/nhentai-ipc-controller.ts index bc64295..b6d6553 100644 --- a/src/main/modules/nhentai/nhentai-ipc-controller.ts +++ b/src/main/modules/nhentai/nhentai-ipc-controller.ts @@ -20,7 +20,7 @@ export class NhentaiIpcController implements IIpcController { } public get(): NhentaiIpcController { - const nhentaiApi: INhentaiApi = container.get(Symbol.for('nhentai-api')); + const nhentaiApi: INhentaiApi = container.get('nhentai-api'); return new NhentaiIpcController(nhentaiApi); } } diff --git a/src/main/modules/store/store.spec.ts b/src/main/modules/store/store.spec.ts index c806bbf..21bb3bc 100644 --- a/src/main/modules/store/store.spec.ts +++ b/src/main/modules/store/store.spec.ts @@ -18,7 +18,7 @@ describe('Store Service', function () { }); it('loads saved data', () => { - const store: IStore = container.get(Symbol.for('store')); + const store: IStore = container.get('store'); const testData = { something: 'gaga', somethingElse: 0, diff --git a/src/main/modules/web-crawler/web-crawler.spec.ts b/src/main/modules/web-crawler/web-crawler.spec.ts index d1b5710..4d85f6a 100644 --- a/src/main/modules/web-crawler/web-crawler.spec.ts +++ b/src/main/modules/web-crawler/web-crawler.spec.ts @@ -17,8 +17,8 @@ describe('Web Crawler', function () { before(() => { rewiremock.enable(); - container.unbind(Symbol.for('store')); - container.bind(Symbol.for('store')).to(StoreMock); + container.unbind('store'); + container.bind('store').to(StoreMock); }); beforeEach(() => { @@ -34,8 +34,8 @@ describe('Web Crawler', function () { after(() => { rewiremock.disable(); - container.unbind(Symbol.for('store')); - container.bind(Symbol.for('store')).to(Store); + container.unbind('store'); + container.bind('store').to(Store); }); it('fetches websites', async () => { @@ -54,7 +54,7 @@ describe('Web Crawler', function () { ) .persist(); - const webCrawler: IWebCrawler = container.get(Symbol.for('web-crawler')); + const webCrawler: IWebCrawler = container.get('web-crawler'); const res: Response = await webCrawler.fetch(testUrl); expect(callback.callCount).to.equal(1, 'multiple requests (or none) are sent when only one should be'); diff --git a/src/main/modules/web-crawler/web-crawler.ts b/src/main/modules/web-crawler/web-crawler.ts index 3438aed..e9aafb7 100644 --- a/src/main/modules/web-crawler/web-crawler.ts +++ b/src/main/modules/web-crawler/web-crawler.ts @@ -1,6 +1,7 @@ -import { inject, injectable } from 'inversify'; +import { injectable } from 'inversify'; import { CookieJar } from 'jsdom'; import nodeFetch, { RequestInit, Response } from 'node-fetch'; +import { inject } from '../../core/inject'; import { CookieSaveError } from '../error/cookie-save-error'; import { IStore } from '../store/i-store'; import { IWebCrawler } from './i-web-crawler'; @@ -13,7 +14,7 @@ export class WebCrawler implements IWebCrawler { private store: IStore; - public constructor(@inject(Symbol.for('store')) store: IStore) { + public constructor(@inject('store') store: IStore) { this.initialized = false; this.cookieJar = new CookieJar(); this.store = store;