diff --git a/.eslintrc.json b/.eslintrc.json index 17088ed..8098206 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -150,7 +150,7 @@ { "selector": "interface", "format": ["PascalCase"], - "prefix": ["I"] + "suffix": ["Interface"] } ], "@typescript-eslint/explicit-member-accessibility": "error", diff --git a/src/main.ts b/src/main.ts index ae3d1a6..dc8c124 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,21 +4,20 @@ import './main/core/install'; import { app } from 'electron'; import { isDev } from './main/core/env'; -import { IAppWindow } from './main/modules/app-window/i-app-window'; -import { ILogger } from './main/modules/logger/i-logger'; +import type { AppWindowInterface } from './main/modules/app-window/app-window-interface'; /** * have a read: https://github.com/nodejs/node/issues/20392, over 100 comments as of 2020-07-26 * https://nodejs.org/api/process.html#process_event_unhandledrejection */ process.on('unhandledRejection', (reason) => { - const logger: ILogger = container.get('logger'); + const logger: LoggerInterface = container.get('logger'); void logger.fatal(`Unhandled Rejection, see ${logger.getExceptionsLogFile()}`); throw reason; }); process.on('uncaughtException', (error) => { - const logger: ILogger = container.get('logger'); + const logger: LoggerInterface = container.get('logger'); void logger.exception(error); if (isDev()) { // eslint-disable-next-line no-console -- only for development purposes @@ -27,7 +26,7 @@ process.on('uncaughtException', (error) => { }); async function createWindow(): Promise { - const appWindowMain: IAppWindow = container.get('app-window-main'); + const appWindowMain: AppWindowInterface = container.get('app-window-main'); await appWindowMain.open(); appWindowMain.window?.on('closed', () => { @@ -48,7 +47,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('app-window-main'); + const appWindowMain: AppWindowInterface = container.get('app-window-main'); if (appWindowMain.isClosed()) { await createWindow(); } diff --git a/src/main/core/database.ts b/src/main/core/database.ts index 29ca1a1..4ba83a7 100644 --- a/src/main/core/database.ts +++ b/src/main/core/database.ts @@ -1,6 +1,6 @@ import path from 'path'; import { Connection, createConnection as ormCreateConnection } from 'typeorm'; -import { BetterSqlite3ConnectionOptions } from 'typeorm/driver/better-sqlite3/BetterSqlite3ConnectionOptions'; +import type { BetterSqlite3ConnectionOptions } from 'typeorm/driver/better-sqlite3/BetterSqlite3ConnectionOptions'; import { appPath } from './app-path'; export enum Database { diff --git a/src/main/entities/library/author-name.ts b/src/main/entities/library/author-name.ts index 59b23b3..cb52395 100644 --- a/src/main/entities/library/author-name.ts +++ b/src/main/entities/library/author-name.ts @@ -2,7 +2,7 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { Author } from './author'; @Entity() -export class AuthorName implements IIdentifiableEntity, INameEntity { +export class AuthorName implements IdentifiableEntityInterface, NameEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/author-role-name.ts b/src/main/entities/library/author-role-name.ts index f890a10..9130870 100644 --- a/src/main/entities/library/author-role-name.ts +++ b/src/main/entities/library/author-role-name.ts @@ -2,7 +2,7 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { AuthorRole } from './author-role'; @Entity() -export class AuthorRoleName implements IIdentifiableEntity, INameEntity { +export class AuthorRoleName implements IdentifiableEntityInterface, NameEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/author-role.ts b/src/main/entities/library/author-role.ts index fab2bcc..636ee86 100644 --- a/src/main/entities/library/author-role.ts +++ b/src/main/entities/library/author-role.ts @@ -7,7 +7,7 @@ import { WorkAuthor } from './work-author'; * Examples: story writing, drawing, animating, publishing, ... */ @Entity() -export class AuthorRole implements IIdentifiableEntity, IMultiNamedEntity, IDescribableEntity { +export class AuthorRole implements IdentifiableEntityInterface, MultiNamedEntityInterface, DescribableEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/author.ts b/src/main/entities/library/author.ts index b2ad1fb..6f45bc4 100644 --- a/src/main/entities/library/author.ts +++ b/src/main/entities/library/author.ts @@ -6,7 +6,7 @@ import { WorkAuthor } from './work-author'; * This entity represents a single real-world entity, be it a person or named group of persons. */ @Entity() -export class Author implements IIdentifiableEntity, IMultiNamedEntity { +export class Author implements IdentifiableEntityInterface, MultiNamedEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/character-tag.ts b/src/main/entities/library/character-tag.ts index e8f4a09..e323034 100644 --- a/src/main/entities/library/character-tag.ts +++ b/src/main/entities/library/character-tag.ts @@ -8,7 +8,7 @@ import { WorkCharacter } from './work-character'; */ @Entity() @PercentCheck('weight') -export class CharacterTag implements IIdentifiableEntity, IWeightedEntity { +export class CharacterTag implements IdentifiableEntityInterface, WeightedEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/collection-name.ts b/src/main/entities/library/collection-name.ts index 6fd5179..3e8bf13 100644 --- a/src/main/entities/library/collection-name.ts +++ b/src/main/entities/library/collection-name.ts @@ -2,7 +2,7 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { Collection } from './collection'; @Entity() -export class CollectionName implements IIdentifiableEntity, INameEntity { +export class CollectionName implements IdentifiableEntityInterface, NameEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/collection-part.ts b/src/main/entities/library/collection-part.ts index 3125879..4f59aef 100644 --- a/src/main/entities/library/collection-part.ts +++ b/src/main/entities/library/collection-part.ts @@ -7,7 +7,7 @@ import { Work } from './work'; * The main use case is chronological ordering. */ @Entity() -export class CollectionPart implements IIdentifiableEntity, IOrderableEntity { +export class CollectionPart implements IdentifiableEntityInterface, OrderableEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/collection.ts b/src/main/entities/library/collection.ts index 1e8d06a..efa37c5 100644 --- a/src/main/entities/library/collection.ts +++ b/src/main/entities/library/collection.ts @@ -11,7 +11,7 @@ import { CollectionPart } from './collection-part'; * If authors of works see them as belonging together, they are a collection */ @Entity() -export class Collection implements IIdentifiableEntity, IMultiNamedEntity { +export class Collection implements IdentifiableEntityInterface, MultiNamedEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/copy.ts b/src/main/entities/library/copy.ts index 8ba198f..d2074c9 100644 --- a/src/main/entities/library/copy.ts +++ b/src/main/entities/library/copy.ts @@ -9,7 +9,7 @@ import { Work } from './work'; * Multiple works can have multiple copies (think of different scans of a physical work, or lossy compression). */ @Entity() -export class Copy implements IIdentifiableEntity { +export class Copy implements IdentifiableEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/i-describable-entity.d.ts b/src/main/entities/library/describable-entity-interface.d.ts similarity index 79% rename from src/main/entities/library/i-describable-entity.d.ts rename to src/main/entities/library/describable-entity-interface.d.ts index f72dd3b..d89fa3e 100644 --- a/src/main/entities/library/i-describable-entity.d.ts +++ b/src/main/entities/library/describable-entity-interface.d.ts @@ -1,7 +1,7 @@ /** * Entities extending this one have a user-maintained description. */ -declare interface IDescribableEntity { +interface DescribableEntityInterface { /** * a text describing this entity */ diff --git a/src/main/entities/library/i-hierachical-entity.d.ts b/src/main/entities/library/hierarchical-entity-interface.d.ts similarity index 81% rename from src/main/entities/library/i-hierachical-entity.d.ts rename to src/main/entities/library/hierarchical-entity-interface.d.ts index c429c96..12129a1 100644 --- a/src/main/entities/library/i-hierachical-entity.d.ts +++ b/src/main/entities/library/hierarchical-entity-interface.d.ts @@ -1,7 +1,7 @@ /** * Entities implementing this interface build a hierarchy. */ -declare interface IHierachicalEntity { +interface HierarchicalEntityInterface { /** * parent entities */ diff --git a/src/main/entities/library/i-identifiable-entity.d.ts b/src/main/entities/library/identifiable-entity-interface.d.ts similarity index 80% rename from src/main/entities/library/i-identifiable-entity.d.ts rename to src/main/entities/library/identifiable-entity-interface.d.ts index 3bdbcb2..5ee85ee 100644 --- a/src/main/entities/library/i-identifiable-entity.d.ts +++ b/src/main/entities/library/identifiable-entity-interface.d.ts @@ -2,7 +2,7 @@ * Every database entity should implement this one. * It does nothing more but guarantee there is an id column. */ -declare interface IIdentifiableEntity { +interface IdentifiableEntityInterface { /** * the entity id */ diff --git a/src/main/entities/library/interaction-tag.ts b/src/main/entities/library/interaction-tag.ts index 46ddbf7..a95525b 100644 --- a/src/main/entities/library/interaction-tag.ts +++ b/src/main/entities/library/interaction-tag.ts @@ -8,7 +8,7 @@ import { WorkCharacter } from './work-character'; */ @Entity() @PercentCheck('weight') -export class InteractionTag implements IIdentifiableEntity, IWeightedEntity { +export class InteractionTag implements IdentifiableEntityInterface, WeightedEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/i-multi-named-entity.d.ts b/src/main/entities/library/multi-named-entity-interface.d.ts similarity index 72% rename from src/main/entities/library/i-multi-named-entity.d.ts rename to src/main/entities/library/multi-named-entity-interface.d.ts index e86118c..ec4809a 100644 --- a/src/main/entities/library/i-multi-named-entity.d.ts +++ b/src/main/entities/library/multi-named-entity-interface.d.ts @@ -1,7 +1,7 @@ /** * Entities extending this interface can have multiple names. */ -declare interface IMultiNamedEntity { +interface MultiNamedEntityInterface { /** * the name which is displayed in the user interface */ @@ -10,5 +10,5 @@ declare interface IMultiNamedEntity { /** * other names for the entity */ - names: Promise; + names: Promise; } diff --git a/src/main/entities/library/i-name-entity.d.ts b/src/main/entities/library/name-entity-interface.d.ts similarity index 69% rename from src/main/entities/library/i-name-entity.d.ts rename to src/main/entities/library/name-entity-interface.d.ts index 1b85eb7..a358d43 100644 --- a/src/main/entities/library/i-name-entity.d.ts +++ b/src/main/entities/library/name-entity-interface.d.ts @@ -1,7 +1,7 @@ /** * This entity describes a single name of an entity with multiple names. */ -declare interface INameEntity { +interface NameEntityInterface { /** * the name */ @@ -10,5 +10,5 @@ declare interface INameEntity { /** * the entity to which the names belong */ - entity: Promise; + entity: Promise; } diff --git a/src/main/entities/library/i-orderable-entity.d.ts b/src/main/entities/library/orderable-entity-interface.d.ts similarity index 78% rename from src/main/entities/library/i-orderable-entity.d.ts rename to src/main/entities/library/orderable-entity-interface.d.ts index d1c227f..d238872 100644 --- a/src/main/entities/library/i-orderable-entity.d.ts +++ b/src/main/entities/library/orderable-entity-interface.d.ts @@ -1,7 +1,7 @@ /** * Entities implementing this interface can be ordered. */ -declare interface IOrderableEntity { +interface OrderableEntityInterface { /** * a lower number means a higher ordering */ diff --git a/src/main/entities/library/site-name.ts b/src/main/entities/library/site-name.ts index 9b5ba3e..6b6d3b1 100644 --- a/src/main/entities/library/site-name.ts +++ b/src/main/entities/library/site-name.ts @@ -2,7 +2,7 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { Site } from './site'; @Entity() -export class SiteName implements IIdentifiableEntity, INameEntity { +export class SiteName implements IdentifiableEntityInterface, NameEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/site.ts b/src/main/entities/library/site.ts index 17b0ae4..6ea75f6 100644 --- a/src/main/entities/library/site.ts +++ b/src/main/entities/library/site.ts @@ -6,7 +6,7 @@ import { Source } from './source'; * This non-user-maintained entity describes an online provider of works which can be scraped. */ @Entity() -export class Site implements IIdentifiableEntity, IMultiNamedEntity { +export class Site implements IdentifiableEntityInterface, MultiNamedEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/source.ts b/src/main/entities/library/source.ts index 464fd64..c458634 100644 --- a/src/main/entities/library/source.ts +++ b/src/main/entities/library/source.ts @@ -6,7 +6,7 @@ import { Site } from './site'; * This entity describes an external source of a copy, in most cases that is a website. */ @Entity() -export class Source implements IIdentifiableEntity { +export class Source implements IdentifiableEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/tag-name.ts b/src/main/entities/library/tag-name.ts index 0d3a3d8..a4bbdec 100644 --- a/src/main/entities/library/tag-name.ts +++ b/src/main/entities/library/tag-name.ts @@ -2,7 +2,7 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { Tag } from './tag'; @Entity() -export class TagName implements IIdentifiableEntity, INameEntity { +export class TagName implements IdentifiableEntityInterface, NameEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/tag.ts b/src/main/entities/library/tag.ts index fcc9c01..35c3d0f 100644 --- a/src/main/entities/library/tag.ts +++ b/src/main/entities/library/tag.ts @@ -11,7 +11,12 @@ import { WorkTag } from './work-tag'; * They can also be in a hierarchy */ @Entity() -export class Tag implements IIdentifiableEntity, IMultiNamedEntity, IDescribableEntity, IHierachicalEntity { +export class Tag + implements + IdentifiableEntityInterface, + MultiNamedEntityInterface, + DescribableEntityInterface, + HierarchicalEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/transformation-type-name.ts b/src/main/entities/library/transformation-type-name.ts index 5b80845..3efa365 100644 --- a/src/main/entities/library/transformation-type-name.ts +++ b/src/main/entities/library/transformation-type-name.ts @@ -2,7 +2,7 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { TransformationType } from './transformation-type'; @Entity() -export class TransformationTypeName implements IIdentifiableEntity, INameEntity { +export class TransformationTypeName implements IdentifiableEntityInterface, NameEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/transformation-type.ts b/src/main/entities/library/transformation-type.ts index a943ac5..ed47ebc 100644 --- a/src/main/entities/library/transformation-type.ts +++ b/src/main/entities/library/transformation-type.ts @@ -7,7 +7,8 @@ import { TransformationTypeName } from './transformation-type-name'; * Possible type: translation, decensor, collection, ... */ @Entity() -export class TransformationType implements IIdentifiableEntity, IMultiNamedEntity, IDescribableEntity { +export class TransformationType + implements IdentifiableEntityInterface, MultiNamedEntityInterface, DescribableEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/transformation.ts b/src/main/entities/library/transformation.ts index fe7c2c1..29b7987 100644 --- a/src/main/entities/library/transformation.ts +++ b/src/main/entities/library/transformation.ts @@ -6,7 +6,7 @@ import { Work } from './work'; * This entity describes how one work is transformed to another. */ @Entity() -export class Transformation implements IIdentifiableEntity, IOrderableEntity { +export class Transformation implements IdentifiableEntityInterface, OrderableEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/i-weighted-entity.d.ts b/src/main/entities/library/weighted-entity-interface.d.ts similarity index 88% rename from src/main/entities/library/i-weighted-entity.d.ts rename to src/main/entities/library/weighted-entity-interface.d.ts index 84c2e3d..785b552 100644 --- a/src/main/entities/library/i-weighted-entity.d.ts +++ b/src/main/entities/library/weighted-entity-interface.d.ts @@ -1,7 +1,7 @@ /** * An entity implementing this interface has a weight property. */ -declare interface IWeightedEntity { +interface WeightedEntityInterface { /** * the weight, mathematically a number (0,1], practically between (0,Number.MAX_SAFE_INTEGER] * the weight can also be not not defined, null in the database diff --git a/src/main/entities/library/work-author.ts b/src/main/entities/library/work-author.ts index 28cce24..ef3d261 100644 --- a/src/main/entities/library/work-author.ts +++ b/src/main/entities/library/work-author.ts @@ -7,7 +7,7 @@ import { Work } from './work'; * This entity connects authors with their work and their role therein. */ @Entity() -export class WorkAuthor implements IIdentifiableEntity, IOrderableEntity { +export class WorkAuthor implements IdentifiableEntityInterface, OrderableEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/work-character-name.ts b/src/main/entities/library/work-character-name.ts index 8b3e0ba..6fe4241 100644 --- a/src/main/entities/library/work-character-name.ts +++ b/src/main/entities/library/work-character-name.ts @@ -2,7 +2,7 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { WorkCharacter } from './work-character'; @Entity() -export class WorkCharacterName implements IIdentifiableEntity, INameEntity { +export class WorkCharacterName implements IdentifiableEntityInterface, NameEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/work-character.ts b/src/main/entities/library/work-character.ts index 371c696..0e246fe 100644 --- a/src/main/entities/library/work-character.ts +++ b/src/main/entities/library/work-character.ts @@ -10,7 +10,7 @@ import { WorldCharacter } from './world-character'; * The character can be original or based on one or more existing characters. */ @Entity() -export class WorkCharacter implements IIdentifiableEntity, IMultiNamedEntity { +export class WorkCharacter implements IdentifiableEntityInterface, MultiNamedEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/work-name.ts b/src/main/entities/library/work-name.ts index abebcd9..e7bb189 100644 --- a/src/main/entities/library/work-name.ts +++ b/src/main/entities/library/work-name.ts @@ -2,7 +2,7 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { Work } from './work'; @Entity() -export class WorkName implements IIdentifiableEntity, INameEntity { +export class WorkName implements IdentifiableEntityInterface, NameEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/work-tag.ts b/src/main/entities/library/work-tag.ts index 639b80e..dce059e 100644 --- a/src/main/entities/library/work-tag.ts +++ b/src/main/entities/library/work-tag.ts @@ -8,7 +8,7 @@ import { Work } from './work'; */ @Entity() @PercentCheck('weight') -export class WorkTag implements IIdentifiableEntity, IWeightedEntity { +export class WorkTag implements IdentifiableEntityInterface, WeightedEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/work.ts b/src/main/entities/library/work.ts index 36df648..1b609a2 100644 --- a/src/main/entities/library/work.ts +++ b/src/main/entities/library/work.ts @@ -17,7 +17,7 @@ import { World } from './world'; */ @Entity() @PercentCheck('rating') -export class Work implements IIdentifiableEntity, IMultiNamedEntity { +export class Work implements IdentifiableEntityInterface, MultiNamedEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/world-character-name.ts b/src/main/entities/library/world-character-name.ts index 062f4fc..233f64c 100644 --- a/src/main/entities/library/world-character-name.ts +++ b/src/main/entities/library/world-character-name.ts @@ -2,7 +2,7 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { WorldCharacter } from './world-character'; @Entity() -export class WorldCharacterName implements IIdentifiableEntity, INameEntity { +export class WorldCharacterName implements IdentifiableEntityInterface, NameEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/world-character.ts b/src/main/entities/library/world-character.ts index 2ffd6a9..6666ee3 100644 --- a/src/main/entities/library/world-character.ts +++ b/src/main/entities/library/world-character.ts @@ -7,7 +7,8 @@ import { WorldCharacterName } from './world-character-name'; * This entity describes a canon character in a fictional world. */ @Entity() -export class WorldCharacter implements IIdentifiableEntity, IMultiNamedEntity, IHierachicalEntity { +export class WorldCharacter + implements IdentifiableEntityInterface, MultiNamedEntityInterface, HierarchicalEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/world-name.ts b/src/main/entities/library/world-name.ts index 0769ce2..4bedd3d 100644 --- a/src/main/entities/library/world-name.ts +++ b/src/main/entities/library/world-name.ts @@ -2,7 +2,7 @@ import { Column, Entity, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; import { World } from './world'; @Entity() -export class WorldName implements IIdentifiableEntity, INameEntity { +export class WorldName implements IdentifiableEntityInterface, NameEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/entities/library/world.ts b/src/main/entities/library/world.ts index 805df00..fc60b56 100644 --- a/src/main/entities/library/world.ts +++ b/src/main/entities/library/world.ts @@ -7,7 +7,8 @@ import { WorldName } from './world-name'; * This entity describes a fictional world. */ @Entity() -export class World implements IIdentifiableEntity, IMultiNamedEntity, IHierachicalEntity { +export class World + implements IdentifiableEntityInterface, MultiNamedEntityInterface, HierarchicalEntityInterface { @PrimaryGeneratedColumn() public id!: number; diff --git a/src/main/migrations/library/1597705000730-initial_migration.ts b/src/main/migrations/library/1597705000730-initial_migration.ts index e52aa8c..a58d000 100644 --- a/src/main/migrations/library/1597705000730-initial_migration.ts +++ b/src/main/migrations/library/1597705000730-initial_migration.ts @@ -1,4 +1,4 @@ -import { MigrationInterface, QueryRunner } from 'typeorm'; +import type { MigrationInterface, QueryRunner } from 'typeorm'; export class initialMigration1597705000730 implements MigrationInterface { name = 'initialMigration1597705000730'; diff --git a/src/main/migrations/store/1587511036078-initial_migration.ts b/src/main/migrations/store/1587511036078-initial_migration.ts index d75ddf9..c2b4e80 100644 --- a/src/main/migrations/store/1587511036078-initial_migration.ts +++ b/src/main/migrations/store/1587511036078-initial_migration.ts @@ -1,4 +1,4 @@ -import { MigrationInterface, QueryRunner } from 'typeorm'; +import type { MigrationInterface, QueryRunner } from 'typeorm'; export class initialMigration1587511036078 implements MigrationInterface { name = 'initialMigration1587511036078'; diff --git a/src/main/modules/app-window/i-app-window.d.ts b/src/main/modules/app-window/app-window-interface.d.ts similarity index 59% rename from src/main/modules/app-window/i-app-window.d.ts rename to src/main/modules/app-window/app-window-interface.d.ts index 00d6bc8..9e62999 100644 --- a/src/main/modules/app-window/i-app-window.d.ts +++ b/src/main/modules/app-window/app-window-interface.d.ts @@ -1,6 +1,6 @@ -import BrowserWindow = Electron.BrowserWindow; +import { BrowserWindow } from 'electron'; -export interface IAppWindow { +interface AppWindowInterface { window: BrowserWindow | null; open(): Promise; close(force?: boolean): void; diff --git a/src/main/modules/app-window/app-window.ts b/src/main/modules/app-window/app-window.ts index 202a62b..91cd97b 100644 --- a/src/main/modules/app-window/app-window.ts +++ b/src/main/modules/app-window/app-window.ts @@ -2,8 +2,8 @@ import { app, BrowserWindow, Event, LoadFileOptions, LoadURLOptions, NewWindowWe import os from 'os'; import path from 'path'; import { isDev } from '../../core/env'; -import { ISessionHelper } from '../session/i-session-helper'; -import { IAppWindow } from './i-app-window'; +import type { SessionHelperInterface } from '../session/session-helper-interface'; +import type { AppWindowInterface } from './app-window-interface'; import BrowserWindowConstructorOptions = Electron.BrowserWindowConstructorOptions; let defaultOptions: BrowserWindowConstructorOptions = { @@ -30,12 +30,12 @@ switch (os.platform()) { break; } -export abstract class AppWindow implements IAppWindow { +export abstract class AppWindow implements AppWindowInterface { protected static default = {}; protected _window: BrowserWindow | null = null; - protected readonly sessionHelper: ISessionHelper; + protected readonly sessionHelper: SessionHelperInterface; protected options: BrowserWindowConstructorOptions; @@ -43,7 +43,11 @@ export abstract class AppWindow implements IAppWindow { protected abstract loadOptions: LoadFileOptions | LoadURLOptions; - protected constructor(sessionHelper: ISessionHelper, uri: string, options: BrowserWindowConstructorOptions = {}) { + protected constructor( + sessionHelper: SessionHelperInterface, + uri: string, + options: BrowserWindowConstructorOptions = {} + ) { this.sessionHelper = sessionHelper; this.options = { ...defaultOptions, ...options }; this.uri = uri; @@ -85,7 +89,7 @@ export abstract class AppWindow implements IAppWindow { return !this._window; } - protected getCsp(): IContentSecurityPolicy { + protected getCsp(): Session.ContentSecurityPolicy { return {}; } diff --git a/src/main/modules/app-window/file-app-window.ts b/src/main/modules/app-window/file-app-window.ts index 14693fe..28b3e93 100644 --- a/src/main/modules/app-window/file-app-window.ts +++ b/src/main/modules/app-window/file-app-window.ts @@ -1,12 +1,12 @@ -import { BrowserWindow, BrowserWindowConstructorOptions, LoadFileOptions } from 'electron'; -import { ISessionHelper } from '../session/i-session-helper'; +import type { BrowserWindow, BrowserWindowConstructorOptions, LoadFileOptions } from 'electron'; +import type { SessionHelperInterface } from '../session/session-helper-interface'; import { AppWindow } from './app-window'; export abstract class FileAppWindow extends AppWindow { protected loadOptions: LoadFileOptions; protected constructor( - sessionHelper: ISessionHelper, + sessionHelper: SessionHelperInterface, uri: string, options: BrowserWindowConstructorOptions = {}, loadOptions: LoadFileOptions = {} diff --git a/src/main/modules/app-window/i-site-app-window.d.ts b/src/main/modules/app-window/i-site-app-window.d.ts deleted file mode 100644 index bff88b9..0000000 --- a/src/main/modules/app-window/i-site-app-window.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { IUrlAppWindow } from './i-url-app-window'; - -export interface ISiteAppWindow extends IUrlAppWindow { - /** - * @see IMutex.acquire - */ - acquireLock(): Promise; -} diff --git a/src/main/modules/app-window/i-url-app-window.d.ts b/src/main/modules/app-window/i-url-app-window.d.ts deleted file mode 100644 index 136e69e..0000000 --- a/src/main/modules/app-window/i-url-app-window.d.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { LoadURLOptions } from 'electron'; -import { IAppWindow } from './i-app-window'; - -export interface IUrlAppWindow extends IAppWindow { - downloadUrlSafe(url: string, savePath: string, options?: LoadURLOptions): Promise; - - loadUrlSafe(url: string, options?: LoadURLOptions): Promise; -} diff --git a/src/main/modules/app-window/main-app-window.ts b/src/main/modules/app-window/main-app-window.ts index 49e3561..d83a41b 100644 --- a/src/main/modules/app-window/main-app-window.ts +++ b/src/main/modules/app-window/main-app-window.ts @@ -1,11 +1,11 @@ import { injectable } from 'inversify'; import { inject } from '../../core/inject'; -import { ISessionHelper } from '../session/i-session-helper'; +import type { SessionHelperInterface } from '../session/session-helper-interface'; import { FileAppWindow } from './file-app-window'; @injectable() export class MainAppWindow extends FileAppWindow { - public constructor(@inject('session-helper') sessionHelper: ISessionHelper) { + public constructor(@inject('session-helper') sessionHelper: SessionHelperInterface) { super(sessionHelper, 'frontend/index.html', { webPreferences: { nodeIntegration: true, diff --git a/src/main/modules/app-window/site-app-window-interface.d.ts b/src/main/modules/app-window/site-app-window-interface.d.ts new file mode 100644 index 0000000..a15701a --- /dev/null +++ b/src/main/modules/app-window/site-app-window-interface.d.ts @@ -0,0 +1,8 @@ +import type { UrlAppWindowInterface } from './url-app-window-interface'; + +interface SiteAppWindowInterface extends UrlAppWindowInterface { + /** + * @see IMutex.acquire + */ + acquireLock(): Promise; +} diff --git a/src/main/modules/app-window/site-app-window.ts b/src/main/modules/app-window/site-app-window.ts index 9328678..cc44f2b 100644 --- a/src/main/modules/app-window/site-app-window.ts +++ b/src/main/modules/app-window/site-app-window.ts @@ -1,18 +1,18 @@ -import { BrowserWindowConstructorOptions, LoadURLOptions } from 'electron'; +import type { BrowserWindowConstructorOptions, LoadURLOptions } from 'electron'; import { SimpleMutex } from '../mutex/simple-mutex'; -import { ISessionHelper } from '../session/i-session-helper'; -import { ISiteAppWindow } from './i-site-app-window'; +import type { SessionHelperInterface } from '../session/session-helper-interface'; +import type { SiteAppWindowInterface } from './site-app-window-interface'; import { UrlAppWindow } from './url-app-window'; /** * This class represents an app window of a site which need to be crawled via the built-in chromium of Electron. * It offers a lock so that multiple calls do executed simultaneously on the same chromium window. */ -export abstract class SiteAppWindow extends UrlAppWindow implements ISiteAppWindow { - private windowLock: IMutex; +export abstract class SiteAppWindow extends UrlAppWindow implements SiteAppWindowInterface { + private windowLock: MutexInterface; protected constructor( - sessionHelper: ISessionHelper, + sessionHelper: SessionHelperInterface, uri: string, options: BrowserWindowConstructorOptions = {}, loadOptions: LoadURLOptions = {} diff --git a/src/main/modules/app-window/url-app-window-interface.d.ts b/src/main/modules/app-window/url-app-window-interface.d.ts new file mode 100644 index 0000000..62a296e --- /dev/null +++ b/src/main/modules/app-window/url-app-window-interface.d.ts @@ -0,0 +1,8 @@ +import type { LoadURLOptions } from 'electron'; +import type { AppWindowInterface } from './app-window-interface'; + +interface UrlAppWindowInterface extends AppWindowInterface { + downloadUrlSafe(url: string, savePath: string, options?: LoadURLOptions): Promise; + + loadUrlSafe(url: string, options?: LoadURLOptions): Promise; +} diff --git a/src/main/modules/app-window/url-app-window.ts b/src/main/modules/app-window/url-app-window.ts index c9206b7..f0fdc97 100644 --- a/src/main/modules/app-window/url-app-window.ts +++ b/src/main/modules/app-window/url-app-window.ts @@ -1,12 +1,12 @@ -import { BrowserWindow, BrowserWindowConstructorOptions, LoadURLOptions } from 'electron'; +import type { BrowserWindow, BrowserWindowConstructorOptions, LoadURLOptions } from 'electron'; import { promisify } from 'util'; -import { ISessionHelper } from '../session/i-session-helper'; +import type { SessionHelperInterface } from '../session/session-helper-interface'; import { AppWindow } from './app-window'; -import { IUrlAppWindow } from './i-url-app-window'; +import type { UrlAppWindowInterface } from './url-app-window-interface'; import { WindowClosedError } from './window-closed-error'; import Timeout = NodeJS.Timeout; -export abstract class UrlAppWindow extends AppWindow implements IUrlAppWindow { +export abstract class UrlAppWindow extends AppWindow implements UrlAppWindowInterface { protected loadOptions: LoadURLOptions; /** @@ -32,7 +32,7 @@ export abstract class UrlAppWindow extends AppWindow implements IUrlAppWindow { private loadWait: Promise = Promise.resolve(); protected constructor( - sessionHelper: ISessionHelper, + sessionHelper: SessionHelperInterface, uri: string, options: BrowserWindowConstructorOptions = {}, loadOptions: LoadURLOptions = {} diff --git a/src/main/modules/dialog/i-dialog.d.ts b/src/main/modules/dialog/dialog-interface.d.ts similarity index 83% rename from src/main/modules/dialog/i-dialog.d.ts rename to src/main/modules/dialog/dialog-interface.d.ts index 53c73b2..903de34 100644 --- a/src/main/modules/dialog/i-dialog.d.ts +++ b/src/main/modules/dialog/dialog-interface.d.ts @@ -1,5 +1,5 @@ import { dialog, OpenDialogOptions } from 'electron'; -interface IDialog { +interface DialogInterface { selectFolder(options: OpenDialogOptions): ReturnType; } diff --git a/src/main/modules/dialog/dialog.ts b/src/main/modules/dialog/dialog.ts index 7158622..7306627 100644 --- a/src/main/modules/dialog/dialog.ts +++ b/src/main/modules/dialog/dialog.ts @@ -1,14 +1,13 @@ import { dialog, OpenDialogOptions } from 'electron'; import { injectable } from 'inversify'; import { inject } from '../../core/inject'; -import { II18nTranslator } from '../i18n/i-i18n-translator'; -import { IDialog } from './i-dialog'; +import type { DialogInterface } from './dialog-interface'; @injectable() -export class Dialog implements IDialog { - private readonly translator: II18nTranslator; +export class Dialog implements DialogInterface { + private readonly translator: I18nTranslatorInterface; - public constructor(@inject('i18n-translator') translator: II18nTranslator) { + public constructor(@inject('i18n-translator') translator: I18nTranslatorInterface) { this.translator = translator; } diff --git a/src/main/modules/i18n/i-i18n-translator.d.ts b/src/main/modules/i18n/i-i18n-translator.d.ts deleted file mode 100644 index d6b0311..0000000 --- a/src/main/modules/i18n/i-i18n-translator.d.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface II18nTranslator { - t(text: string): string; -} diff --git a/src/main/modules/i18n/i18n-translator-interface.d.ts b/src/main/modules/i18n/i18n-translator-interface.d.ts new file mode 100644 index 0000000..53e362e --- /dev/null +++ b/src/main/modules/i18n/i18n-translator-interface.d.ts @@ -0,0 +1,3 @@ +interface I18nTranslatorInterface { + t(text: string): string; +} diff --git a/src/main/modules/i18n/i18n-translator.ts b/src/main/modules/i18n/i18n-translator.ts index 75b82bb..bcc1705 100644 --- a/src/main/modules/i18n/i18n-translator.ts +++ b/src/main/modules/i18n/i18n-translator.ts @@ -1,8 +1,7 @@ import { injectable } from 'inversify'; -import { II18nTranslator } from './i-i18n-translator'; @injectable() -export class I18nTranslator implements II18nTranslator { +export class I18nTranslator implements I18nTranslatorInterface { public t(text: string): string { return text; } diff --git a/src/main/modules/ipc/annotations/answer.ts b/src/main/modules/ipc/annotations/answer.ts index 811db5c..e88726b 100644 --- a/src/main/modules/ipc/annotations/answer.ts +++ b/src/main/modules/ipc/annotations/answer.ts @@ -1,7 +1,7 @@ import { registerHandler } from '../ipc-server'; export function answer(channel: IpcChannel): IpcControllerMethodDecorator { - return function (target: IIpcController, propertyKey): void { + return function (target: IpcController, propertyKey): void { registerHandler(channel, target, propertyKey); }; } diff --git a/src/main/modules/ipc/ipc-server.ts b/src/main/modules/ipc/ipc-server.ts index d33221a..17f6490 100644 --- a/src/main/modules/ipc/ipc-server.ts +++ b/src/main/modules/ipc/ipc-server.ts @@ -1,12 +1,12 @@ import { ipcMain } from 'electron'; import IpcMainEvent = Electron.IpcMainEvent; -export function registerHandler(channel: IpcChannel, controller: IIpcController, handler: string): void { - ipcMain.on(channel, (event: IpcMainEvent, payload: IIpcPayload) => { +export function registerHandler(channel: IpcChannel, controller: IpcController, handler: string): void { + ipcMain.on(channel, (event: IpcMainEvent, payload: IpcPayload) => { ((controller.get() as unknown) as { [x: string]: IpcHandler }) [handler](payload.data) .then((result: unknown) => { - const response: IIpcResponse = { + const response: IpcResponse = { id: payload.id, success: true, data: result, @@ -14,7 +14,7 @@ export function registerHandler(channel: IpcChannel, controller: IIpcController, event.reply(channel, response); }) .catch((reason: Error) => { - const response: IIpcResponse = { + const response: IpcResponse = { id: payload.id, success: false, error: reason.message, diff --git a/src/main/modules/logger/i-logger.d.ts b/src/main/modules/logger/logger-interface.d.ts similarity index 91% rename from src/main/modules/logger/i-logger.d.ts rename to src/main/modules/logger/logger-interface.d.ts index 99e7e82..994dd20 100644 --- a/src/main/modules/logger/i-logger.d.ts +++ b/src/main/modules/logger/logger-interface.d.ts @@ -1,8 +1,8 @@ /** * A Logger provides methods to save a developer message somewhere it can be retrieved - * @see ILogger.getLogFile + * @see LoggerInterface.getLogFile */ -export interface ILogger { +interface LoggerInterface { /** * default logging method, the logging level needs to be specified * @see LogLevel @@ -47,7 +47,7 @@ export interface ILogger { /** * logs the error, preferably with stack trace - * @see ILogger.getExceptionsLogFile + * @see LoggerInterface.getExceptionsLogFile */ exception(error: Error): Promise; diff --git a/src/main/modules/logger/logger.mock.ts b/src/main/modules/logger/logger.mock.ts index 9588379..3abe3ce 100644 --- a/src/main/modules/logger/logger.mock.ts +++ b/src/main/modules/logger/logger.mock.ts @@ -1,11 +1,10 @@ import { injectable } from 'inversify'; -import { ILogger } from './i-logger'; /** * Mock of a logger, does not log anywhere */ @injectable() -export class LoggerMock implements ILogger { +export class LoggerMock implements LoggerInterface { public getLogFile(): string { return ''; } diff --git a/src/main/modules/logger/logger.spec.ts b/src/main/modules/logger/logger.spec.ts index 89f52bb..19fc608 100644 --- a/src/main/modules/logger/logger.spec.ts +++ b/src/main/modules/logger/logger.spec.ts @@ -6,7 +6,6 @@ import fc from 'fast-check'; import fs from 'fs-extra'; import { container } from '../../core/container'; import { setDev } from '../../core/env.spec'; -import { ILogger } from './i-logger'; import { LogLevel } from './log-level'; chai.use(chaiFs); @@ -25,7 +24,7 @@ describe('Logger Service', () => { }); } - function getDefaultLogReadLineInterface(logger: ILogger) { + function getDefaultLogReadLineInterface(logger: LoggerInterface) { return createInterface(fs.createReadStream(logger.getLogFile())); } @@ -42,20 +41,20 @@ describe('Logger Service', () => { const logLevelNumberArbitrary = fc.constantFrom(...logLevelsNumber); it('creates log files', () => { - const logger: ILogger = container.get('logger'); + const logger: LoggerInterface = 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('logger'); + const logger: LoggerInterface = 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('logger'); + const logger: LoggerInterface = container.get('logger'); let prevLogFileSize = (await fs.stat(logger.getLogFile())).size; let minNumberOfLines = maxLogSize; @@ -76,7 +75,7 @@ describe('Logger Service', () => { }).timeout(15000); it("exception log file doesn't get bigger than 50KB @slow", async () => { - const logger: ILogger = container.get('logger'); + const logger: LoggerInterface = container.get('logger'); let prevLogFileSize = (await fs.stat(logger.getExceptionsLogFile())).size; let minNumberOfLines = maxLogSize; @@ -97,7 +96,7 @@ describe('Logger Service', () => { }).timeout(15000); it('logs different levels directly', () => { - const logger: ILogger = container.get('logger'); + const logger: LoggerInterface = container.get('logger'); return fc.assert( fc.asyncProperty(logLevelArbitrary as LogLevelArbitrary, fc.string(), async (logLevel, message) => { @@ -113,7 +112,7 @@ describe('Logger Service', () => { }); it('logs different levels indirectly via the generic log function', () => { - const logger: ILogger = container.get('logger'); + const logger: LoggerInterface = container.get('logger'); return fc.assert( fc.asyncProperty(logLevelNumberArbitrary, fc.string(), async (logLevelNumber, message) => { @@ -132,7 +131,7 @@ describe('Logger Service', () => { }); it('logs debug only in dev mode', async () => { - const logger: ILogger = container.get('logger'); + const logger: LoggerInterface = container.get('logger'); setDev(); await logger.debug('this is a development message'); diff --git a/src/main/modules/logger/logger.ts b/src/main/modules/logger/logger.ts index 39ce8cc..8688053 100644 --- a/src/main/modules/logger/logger.ts +++ b/src/main/modules/logger/logger.ts @@ -4,7 +4,6 @@ import * as fs from 'fs-extra'; import { injectable } from 'inversify'; import { appPath } from '../../core/app-path'; import { isDev } from '../../core/env'; -import { ILogger } from './i-logger'; import { LogLevel } from './log-level'; const loggingDir = path.resolve(appPath, 'logs'); @@ -16,7 +15,7 @@ const maxLogSize = 50000; * A logger not using winston to log to files in the appPath. */ @injectable() -export class Logger implements ILogger { +export class Logger implements LoggerInterface { public constructor() { fs.createFileSync(logFile); fs.createFileSync(exceptionLogFile); diff --git a/src/main/modules/mutex/i-mutex.d.ts b/src/main/modules/mutex/mutex-interface.d.ts similarity index 97% rename from src/main/modules/mutex/i-mutex.d.ts rename to src/main/modules/mutex/mutex-interface.d.ts index 20f5060..4aa9a7a 100644 --- a/src/main/modules/mutex/i-mutex.d.ts +++ b/src/main/modules/mutex/mutex-interface.d.ts @@ -3,7 +3,7 @@ * * Acquiring this lock returns a release function function (via promise) which needs to be called to release the lock again. */ -interface IMutex { +interface MutexInterface { /** * acquires the lock and returns a Promise with the release function to be called when the lock shall be released. * This release function needs to be called or the lock will never release and execution of subsequent consumers will not take place. diff --git a/src/main/modules/mutex/simple-mutex.ts b/src/main/modules/mutex/simple-mutex.ts index d7c62b9..4e8302e 100644 --- a/src/main/modules/mutex/simple-mutex.ts +++ b/src/main/modules/mutex/simple-mutex.ts @@ -1,7 +1,7 @@ /** * This class implements a simple mutex using a semaphore. */ -export class SimpleMutex implements IMutex { +export class SimpleMutex implements MutexInterface { /** * This queue is an array of promise resolve functions. * Calling them signals the corresponding consumer that the lock is now free. diff --git a/src/main/modules/nhentai/i-nhentai-app-window.d.ts b/src/main/modules/nhentai/i-nhentai-app-window.d.ts deleted file mode 100644 index f1409b6..0000000 --- a/src/main/modules/nhentai/i-nhentai-app-window.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { ISiteAppWindow } from '../app-window/i-site-app-window'; - -export interface INhentaiAppWindow extends ISiteAppWindow { - getFavorites(): Promise; -} diff --git a/src/main/modules/nhentai/i-nhentai-api.d.ts b/src/main/modules/nhentai/nhentai-api-interface.d.ts similarity index 61% rename from src/main/modules/nhentai/i-nhentai-api.d.ts rename to src/main/modules/nhentai/nhentai-api-interface.d.ts index 1680000..ade8ffe 100644 --- a/src/main/modules/nhentai/i-nhentai-api.d.ts +++ b/src/main/modules/nhentai/nhentai-api-interface.d.ts @@ -1,3 +1,3 @@ -export interface INhentaiApi { +interface NhentaiApiInterface { getFavorites(): Promise; } diff --git a/src/main/modules/nhentai/nhentai-api.ts b/src/main/modules/nhentai/nhentai-api.ts index 1c0d7f9..82cfe5f 100644 --- a/src/main/modules/nhentai/nhentai-api.ts +++ b/src/main/modules/nhentai/nhentai-api.ts @@ -1,13 +1,12 @@ import { injectable } from 'inversify'; import { inject } from '../../core/inject'; -import { INhentaiApi } from './i-nhentai-api'; -import { INhentaiAppWindow } from './i-nhentai-app-window'; +import type { NhentaiAppWindowInterface } from './nhentai-app-window-interface'; @injectable() -export class NhentaiApi implements INhentaiApi { - private readonly appWindow: INhentaiAppWindow; +export class NhentaiApi implements NhentaiApiInterface { + private readonly appWindow: NhentaiAppWindowInterface; - public constructor(@inject('nhentai-app-window') appWindow: INhentaiAppWindow) { + public constructor(@inject('nhentai-app-window') appWindow: NhentaiAppWindowInterface) { this.appWindow = appWindow; } diff --git a/src/main/modules/nhentai/nhentai-app-window-interface.d.ts b/src/main/modules/nhentai/nhentai-app-window-interface.d.ts new file mode 100644 index 0000000..8e70f91 --- /dev/null +++ b/src/main/modules/nhentai/nhentai-app-window-interface.d.ts @@ -0,0 +1,5 @@ +import type { SiteAppWindowInterface } from '../app-window/site-app-window-interface'; + +interface NhentaiAppWindowInterface extends SiteAppWindowInterface { + getFavorites(): Promise; +} diff --git a/src/main/modules/nhentai/nhentai-app-window.ts b/src/main/modules/nhentai/nhentai-app-window.ts index 906f34b..d0627f1 100644 --- a/src/main/modules/nhentai/nhentai-app-window.ts +++ b/src/main/modules/nhentai/nhentai-app-window.ts @@ -1,4 +1,4 @@ -import { WebContents } from 'electron'; +import type { WebContents } from 'electron'; import os from 'os'; import path from 'path'; import { Readable } from 'stream'; @@ -8,9 +8,8 @@ import { injectable } from 'inversify'; import { inject } from '../../core/inject'; import { SiteAppWindow } from '../app-window/site-app-window'; import { WindowClosedError } from '../app-window/window-closed-error'; -import { ISessionHelper } from '../session/i-session-helper'; -import { INhentaiAppWindow } from './i-nhentai-app-window'; -import { IFavorite } from './nhentai'; +import type { SessionHelperInterface } from '../session/session-helper-interface'; +import type { NhentaiAppWindowInterface } from './nhentai-app-window-interface'; import { url as nhentaiUrl, hostname as nhentaiHostname, @@ -25,8 +24,8 @@ import { const waitInterval = 2000; @injectable() -export class NhentaiAppWindow extends SiteAppWindow implements INhentaiAppWindow { - public constructor(@inject('session-helper') sessionHelper: ISessionHelper) { +export class NhentaiAppWindow extends SiteAppWindow implements NhentaiAppWindowInterface { + public constructor(@inject('session-helper') sessionHelper: SessionHelperInterface) { super(sessionHelper, nhentaiUrl); } @@ -52,7 +51,7 @@ export class NhentaiAppWindow extends SiteAppWindow implements INhentaiAppWindow } const readable = Readable.from( - (async function* (thisArg): AsyncGenerator { + (async function* (thisArg): AsyncGenerator { for (let i = 0; i < bookUrls.length; i++) { const bookUrl = bookUrls[i]; yield await thisArg.getBookTorrent(bookUrl); @@ -76,7 +75,7 @@ export class NhentaiAppWindow extends SiteAppWindow implements INhentaiAppWindow } } - protected getCsp(): IContentSecurityPolicy { + protected getCsp(): Session.ContentSecurityPolicy { return { 'default-src': ['nhentai.net'], 'script-src': ['nhentai.net', "'unsafe-eval'"], @@ -163,7 +162,7 @@ export class NhentaiAppWindow extends SiteAppWindow implements INhentaiAppWindow return; } - private async getBookTorrent(bookUrl: string): Promise { + private async getBookTorrent(bookUrl: string): Promise { if (!this._window) { throw new WindowClosedError(); } diff --git a/src/main/modules/nhentai/nhentai-ipc-controller.ts b/src/main/modules/nhentai/nhentai-ipc-controller.ts index f99e6b9..5deb2dc 100644 --- a/src/main/modules/nhentai/nhentai-ipc-controller.ts +++ b/src/main/modules/nhentai/nhentai-ipc-controller.ts @@ -1,20 +1,17 @@ import path from 'path'; import { createWriteStream } from 'fs-extra'; import { container } from '../../core/container'; -import { IDialog } from '../dialog/i-dialog'; -import { II18nTranslator } from '../i18n/i-i18n-translator'; +import type { DialogInterface } from '../dialog/dialog-interface'; import { answer } from '../ipc/annotations/answer'; -import { INhentaiApi } from './i-nhentai-api'; -import { IFavorite } from './nhentai'; -export class NhentaiIpcController implements IIpcController { - private readonly nhentaiApi: INhentaiApi; +export class NhentaiIpcController implements IpcController { + private readonly nhentaiApi: NhentaiApiInterface; - private readonly translator: II18nTranslator; + private readonly translator: I18nTranslatorInterface; - private readonly dialog: IDialog; + private readonly dialog: DialogInterface; - private constructor(nhentaiApi: INhentaiApi, translator: II18nTranslator, dialog: IDialog) { + private constructor(nhentaiApi: NhentaiApiInterface, translator: I18nTranslatorInterface, dialog: DialogInterface) { this.nhentaiApi = nhentaiApi; this.translator = translator; this.dialog = dialog; @@ -33,7 +30,7 @@ export class NhentaiIpcController implements IIpcController { const favoritesStream = await this.nhentaiApi.getFavorites(); return new Promise((resolve) => { - favoritesStream.on('data', (favorite: IFavorite) => { + favoritesStream.on('data', (favorite: Nhentai.Favorite) => { const writable = createWriteStream(path.resolve(result.filePaths[0], favorite.name)); favorite.torrentFile.pipe(writable); }); @@ -43,9 +40,9 @@ export class NhentaiIpcController implements IIpcController { } public get(): NhentaiIpcController { - const nhentaiApi: INhentaiApi = container.get('nhentai-api'); - const translator: II18nTranslator = container.get('i18n-translator'); - const dialog: IDialog = container.get('dialog'); + const nhentaiApi: NhentaiApiInterface = container.get('nhentai-api'); + const translator: I18nTranslatorInterface = container.get('i18n-translator'); + const dialog: DialogInterface = container.get('dialog'); return new NhentaiIpcController(nhentaiApi, translator, dialog); } } diff --git a/src/main/modules/nhentai/nhentai.d.ts b/src/main/modules/nhentai/nhentai.d.ts index 9f49f49..60be1ac 100644 --- a/src/main/modules/nhentai/nhentai.d.ts +++ b/src/main/modules/nhentai/nhentai.d.ts @@ -1,4 +1,6 @@ -export interface IFavorite { - name: string; - torrentFile: NodeJS.ReadableStream; +declare namespace Nhentai { + type Favorite = { + name: string; + torrentFile: NodeJS.ReadableStream; + }; } diff --git a/src/main/modules/session/i-session-helper.d.ts b/src/main/modules/session/i-session-helper.d.ts deleted file mode 100644 index 3fc070a..0000000 --- a/src/main/modules/session/i-session-helper.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { BrowserWindow } from 'electron'; - -export interface ISessionHelper { - setCsp(window: BrowserWindow, csp: IContentSecurityPolicy): void; -} diff --git a/src/main/modules/session/session-helper-interface.d.ts b/src/main/modules/session/session-helper-interface.d.ts new file mode 100644 index 0000000..a5abdca --- /dev/null +++ b/src/main/modules/session/session-helper-interface.d.ts @@ -0,0 +1,5 @@ +import { BrowserWindow } from 'electron'; + +interface SessionHelperInterface { + setCsp(window: BrowserWindow, csp: Session.ContentSecurityPolicy): void; +} diff --git a/src/main/modules/session/session-helper.ts b/src/main/modules/session/session-helper.ts index 97c7190..59ce6c7 100644 --- a/src/main/modules/session/session-helper.ts +++ b/src/main/modules/session/session-helper.ts @@ -1,23 +1,26 @@ import { injectable } from 'inversify'; import { isDev } from '../../core/env'; -import { ISessionHelper } from './i-session-helper'; +import type { SessionHelperInterface } from './session-helper-interface'; -const defaultCsp: IContentSecurityPolicy = { +const defaultCsp: Session.ContentSecurityPolicy = { 'default-src': ["'self'"], 'style-src': ["'unsafe-inline'"], 'object-src': ["'none'"], }; @injectable() -export class SessionHelper implements ISessionHelper { - private static stringifyCspHeader(csp: IContentSecurityPolicy): string { +export class SessionHelper implements SessionHelperInterface { + private static stringifyCspHeader(csp: Session.ContentSecurityPolicy): string { return Object.entries(csp) - .map((directive: [string, CspValue[]]) => `${directive[0]} ${directive[1]?.join(' ')}`) + .map( + (directive: [string, Session.CspValue[] | undefined]) => + `${directive[0]} ${directive[1] ? directive[1]?.join(' ') : ''}` + ) .join('; '); } - public setCsp(window: Electron.BrowserWindow, csp: IContentSecurityPolicy): void { - const mergedCsp: IContentSecurityPolicy = { ...defaultCsp, ...csp }; + public setCsp(window: Electron.BrowserWindow, csp: Session.ContentSecurityPolicy): void { + const mergedCsp: Session.ContentSecurityPolicy = { ...defaultCsp, ...csp }; if (isDev()) { mergedCsp['default-src'] = ['devtools:'].concat(mergedCsp['default-src'] ?? []); diff --git a/src/main/modules/session/session.d.ts b/src/main/modules/session/session.d.ts index fb1350c..e58d7f4 100644 --- a/src/main/modules/session/session.d.ts +++ b/src/main/modules/session/session.d.ts @@ -1,23 +1,25 @@ -type CspValue = '*' | "'none'" | "'self'" | "'unsafe-inline'" | "'unsafe-eval'" | string; +declare namespace Session { + type CspValue = '*' | "'none'" | "'self'" | "'unsafe-inline'" | "'unsafe-eval'" | string; -/** - * This interface represents a content security policy. - * - * @see https://www.w3.org/TR/CSP/ - * @see https://content-security-policy.com/ - */ -interface IContentSecurityPolicy { - 'child-src'?: CspValue[]; - 'connect-src'?: CspValue[]; - 'default-src'?: CspValue[]; - 'font-src'?: CspValue[]; - 'frame-src'?: CspValue[]; - 'img-src'?: CspValue[]; - 'media-src'?: CspValue[]; - 'object-src'?: ["'none'"]; - 'script-src'?: CspValue[]; - 'script-src-elem'?: CspValue[]; - 'script-src-attr'?: CspValue[]; - 'style-src'?: CspValue[]; - 'worker-src'?: CspValue[]; + /** + * This interface represents a content security policy. + * + * @see https://www.w3.org/TR/CSP/ + * @see https://content-security-policy.com/ + */ + type ContentSecurityPolicy = { + 'child-src'?: CspValue[]; + 'connect-src'?: CspValue[]; + 'default-src'?: CspValue[]; + 'font-src'?: CspValue[]; + 'frame-src'?: CspValue[]; + 'img-src'?: CspValue[]; + 'media-src'?: CspValue[]; + 'object-src'?: ["'none'"]; + 'script-src'?: CspValue[]; + 'script-src-elem'?: CspValue[]; + 'script-src-attr'?: CspValue[]; + 'style-src'?: CspValue[]; + 'worker-src'?: CspValue[]; + }; } diff --git a/src/main/modules/store/i-store.d.ts b/src/main/modules/store/store-interface.d.ts similarity index 79% rename from src/main/modules/store/i-store.d.ts rename to src/main/modules/store/store-interface.d.ts index 30fe859..78abbe3 100644 --- a/src/main/modules/store/i-store.d.ts +++ b/src/main/modules/store/store-interface.d.ts @@ -1,4 +1,4 @@ -export interface IStore { +interface StoreInterface { load: (key: StoreKey) => Promise; save: (key: StoreKey, data: unknown) => Promise; } diff --git a/src/main/modules/store/store.mock.ts b/src/main/modules/store/store.mock.ts index 314aad3..ed57819 100644 --- a/src/main/modules/store/store.mock.ts +++ b/src/main/modules/store/store.mock.ts @@ -1,11 +1,10 @@ import { injectable } from 'inversify'; -import { IStore } from './i-store'; /** * This mock store saves the data in memory. */ @injectable() -export class StoreMock implements IStore { +export class StoreMock implements StoreInterface { private store: { [x in StoreKey]?: unknown } = {}; public load(key: StoreKey): Promise { diff --git a/src/main/modules/store/store.spec.ts b/src/main/modules/store/store.spec.ts index 833f91e..cb4b772 100644 --- a/src/main/modules/store/store.spec.ts +++ b/src/main/modules/store/store.spec.ts @@ -1,13 +1,12 @@ import { expect } from 'chai'; import 'mocha'; import { container } from '../../core/container'; -import { IStore } from './i-store'; describe('Store Service', function () { this.timeout(10000); it('loads saved data', () => { - const store: IStore = container.get('store'); + const store: StoreInterface = container.get('store'); const testData = { something: 'gaga', somethingElse: 0, diff --git a/src/main/modules/store/store.ts b/src/main/modules/store/store.ts index 6a1436f..1003201 100644 --- a/src/main/modules/store/store.ts +++ b/src/main/modules/store/store.ts @@ -1,12 +1,11 @@ import { injectable } from 'inversify'; import { Database, getConnection } from '../../core/database'; import { StoreValue } from '../../entities/store/store-value'; -import { IStore } from './i-store'; const CACHE_ID = 'store'; @injectable() -export class Store implements IStore { +export class Store implements StoreInterface { public async load(key: StoreKey): Promise { const c = await getConnection(Database.STORE); const repository = c.getRepository(StoreValue); diff --git a/src/renderer/services/api.ts b/src/renderer/services/api.ts index af65dd2..4ef95ad 100644 --- a/src/renderer/services/api.ts +++ b/src/renderer/services/api.ts @@ -2,16 +2,16 @@ import { ipcRenderer } from 'electron'; import { uuid } from '../../services/uuid'; import IpcRendererEvent = Electron.IpcRendererEvent; -const ipcClient: IIpcClient = { +const ipcClient: IpcClient = { ask: (channel: IpcChannel, data?: unknown): Promise => { const id = uuid(); - const payload: IIpcPayload = { + const payload: IpcPayload = { id, data, }; return new Promise((resolve: (value?: unknown) => void, reject: (reason?: Error) => void): void => { - const listener = (event: IpcRendererEvent, response: IIpcResponse): void => { + const listener = (event: IpcRendererEvent, response: IpcResponse): void => { if (response.id === id) { if (response.success) { resolve(response.data); diff --git a/tsconfig.json b/tsconfig.json index e1b1778..99370fb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,8 @@ "sourceMap": true, "preserveConstEnums": false, "experimentalDecorators": true, - "emitDecoratorMetadata": true + "emitDecoratorMetadata": true, + "importsNotUsedAsValues": "error" }, "include": ["declarations/**/*.ts", "types/**/*.ts", "src/main.ts", "src/main/**/*.ts", "src/services/**/*.ts"] } diff --git a/tsconfig.renderer.json b/tsconfig.renderer.json index 2ddde11..0d6ed5d 100644 --- a/tsconfig.renderer.json +++ b/tsconfig.renderer.json @@ -6,7 +6,8 @@ "noImplicitAny": true, "removeComments": true, "sourceMap": true, - "preserveConstEnums": false + "preserveConstEnums": false, + "importsNotUsedAsValues": "error" }, "include": [ "declarations/**/*.ts", diff --git a/types/ipc-controller-method-decorator.d.ts b/types/ipc-controller-method-decorator.d.ts index 8689b6f..6625f6c 100644 --- a/types/ipc-controller-method-decorator.d.ts +++ b/types/ipc-controller-method-decorator.d.ts @@ -2,7 +2,7 @@ * @see MethodDecorator */ type IpcControllerMethodDecorator = ( - target: IIpcController, + target: IpcController, propertyKey: string, descriptor: TypedPropertyDescriptor ) => void; diff --git a/types/ipc.d.ts b/types/ipc.d.ts index fc3f050..5964495 100644 --- a/types/ipc.d.ts +++ b/types/ipc.d.ts @@ -2,26 +2,25 @@ declare const enum IpcChannel { NHENTAI_SAVE_FAVORITES = 'NHENTAI_SAVE_FAVORITES', } -interface IIpcPayload { +type IpcPayload = { id: string; data: unknown; -} +}; -interface IIpcResponse { +type IpcResponse = { id: string; success: boolean; data?: unknown; // just the error message error?: string; -} +}; -interface IIpcClient { +type IpcClient = { ask: (channel: IpcChannel, data?: unknown) => Promise; -} +}; type IpcHandler = (data?: unknown) => Promise; -// eslint-disable-next-line @typescript-eslint/no-unused-vars -- https://github.com/typescript-eslint/typescript-eslint/issues/2714 -interface IIpcController { - get(): IIpcController; -} +type IpcController = { + get(): IpcController; +};