feat: implement entity API and reactive store-like modules in frontend
Also does a bunch of other stuff.
This commit is contained in:
parent
55a5047328
commit
4bb6e5c166
|
@ -11,3 +11,6 @@ charset = utf-8
|
|||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.handlebars]
|
||||
insert_final_newline = false
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
# except these file types
|
||||
!*.js
|
||||
!*.ts
|
||||
!*.svelte
|
||||
|
||||
# but ignore stuff from .gitignore
|
||||
node_modules
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"root": true,
|
||||
"plugins": ["@typescript-eslint", "import"],
|
||||
"extends": ["eslint:recommended", "prettier", "plugin:import/recommended"],
|
||||
"plugins": ["@typescript-eslint", "import", "promise", "svelte3"],
|
||||
"extends": ["eslint:recommended", "prettier", "plugin:import/recommended", "plugin:promise/recommended"],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2019,
|
||||
"ecmaVersion": 2020,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"env": {
|
||||
|
@ -91,16 +91,24 @@
|
|||
"order": "asc"
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
|
||||
"promise/valid-params": "off",
|
||||
"promise/always-return": "off"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["src/**/*.*"],
|
||||
"rules": {
|
||||
"no-console": "warn"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["**/*.ts"],
|
||||
"extends": [
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
||||
"prettier/@typescript-eslint",
|
||||
"plugin:import/typescript",
|
||||
"plugin:import/electron"
|
||||
],
|
||||
|
@ -115,7 +123,6 @@
|
|||
}
|
||||
},
|
||||
"rules": {
|
||||
"no-console": "warn",
|
||||
"no-magic-numbers": "off",
|
||||
"no-shadow": "off",
|
||||
|
||||
|
@ -183,7 +190,7 @@
|
|||
{
|
||||
"selector": "interface",
|
||||
"format": ["PascalCase"],
|
||||
"suffix": ["Interface"]
|
||||
"suffix": ["Interface", "Function"]
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/explicit-member-accessibility": "warn",
|
||||
|
@ -198,7 +205,10 @@
|
|||
"allowNullish": false
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-shadow": ["warn"]
|
||||
"@typescript-eslint/no-shadow": ["warn"],
|
||||
"@typescript-eslint/no-extra-semi": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"@typescript-eslint/consistent-type-assertions": ["warn"]
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@ -207,6 +217,10 @@
|
|||
"project": "./tsconfig.renderer.json"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": ["**/*.svelte"],
|
||||
"processor": "svelte3/svelte3"
|
||||
},
|
||||
{
|
||||
"files": ["src/shared/types/**/*"],
|
||||
"rules": {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
_
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npm run precommit
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npm run prepush
|
|
@ -2,7 +2,6 @@
|
|||
*.*
|
||||
|
||||
# except these file types
|
||||
!*.html
|
||||
!*.handlebars
|
||||
!*.json
|
||||
!*.yml
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
trailingComma: 'es5'
|
||||
trailingComma: all
|
||||
tabWidth: 2
|
||||
semi: true
|
||||
singleQuote: true
|
||||
|
@ -6,13 +6,10 @@ quoteProps: consistent
|
|||
arrowParens: always
|
||||
printWidth: 120
|
||||
endOfLine: lf
|
||||
|
||||
svelteStrictMode: true
|
||||
|
||||
overrides:
|
||||
- files: '*.svelte'
|
||||
options:
|
||||
parser: html
|
||||
- files: '*.handlebars'
|
||||
options:
|
||||
parser: html
|
||||
- files: '*.drawio'
|
||||
options:
|
||||
parser: html
|
||||
parser: xml
|
||||
|
|
|
@ -11,6 +11,8 @@ Nothing in this project is set in stone (even this rule). I might not know what
|
|||
1. [Formatting and Linters](CONTRIBUTING.md#formatting-and-linters)
|
||||
1. [Testing](CONTRIBUTING.md#testing)
|
||||
1. [Updating](CONTRIBUTING.md#updating-dependencies)
|
||||
1. [Frontend](CONTRIBUTING.md#frontend)
|
||||
1. [Translation](CONTRIBUTING.md#translation)
|
||||
1. [Design](CONTRIBUTING.md#design)
|
||||
|
||||
## Currently Most Wanted
|
||||
|
@ -45,6 +47,10 @@ The [ideas folder](workspace/ideas) is a collection of possible features for the
|
|||
|
||||
I could use another developer (experienced or not) to take a look or two at this code base and voice their opinion.
|
||||
|
||||
#### LF: TypeScript Magician
|
||||
|
||||
Do a search over the whole code-base for `@ts-ignore` or ` as [A-Z]` (regex for type assertions) and try to fix my typings. Good luck!
|
||||
|
||||
## Communication
|
||||
|
||||
Every contribution is valuable. Open a ticket [here](https://git.fuwafuwa.moe/Xymorot/RenaiApp/issues) or write me an [email](mailto:xymorot@mailbox.org).
|
||||
|
@ -141,7 +147,7 @@ The point of these libraries is to make uniform code possible over various edito
|
|||
|
||||
The testing framework of choice is [Mocha](https://mochajs.org/). Call `npm run test` to run all tests. Tests are written in typescript and need to be transpiled before testing.
|
||||
|
||||
- assertion is (mainly) done by [Chai](https://www.chaijs.com/)should not be compromised
|
||||
- assertion is (mainly) done by [Chai](https://www.chaijs.com/)
|
||||
- spies, stubs and mocks are provided by [Sinon.JS](https://sinonjs.org/)
|
||||
- HTTP server mocking is done by [nock](https://github.com/nock/nock)
|
||||
- property based testing is made possible by [fast-check](https://github.com/dubzzz/fast-check)
|
||||
|
@ -182,6 +188,15 @@ This also means potentially updating:
|
|||
- the `@types/node` package
|
||||
- the electron version in the `target` field of the [webpack config](scripts/webpack.config.js)
|
||||
- the `compilerOptions.target` fields of the [main](tsconfig.json) and [renderer](tsconfig.renderer.json) typescript configuration files
|
||||
- the `parserOptions.ecmaVersion` field in the [ESLint configuration](.eslintrc.json)
|
||||
|
||||
Also might be worth checking out https://github.com/electron/electron/issues/21457 if the project can be converted to transpile to ES Modules.
|
||||
|
||||
### Frontend
|
||||
|
||||
#### Translation
|
||||
|
||||
With the help of [intl-messageformat](https://www.npmjs.com/package/intl-messageformat) frontend message can be defined in the [ICU Message Format](https://unicode-org.github.io/icu/userguide/format_parse/messages/). The corresponding code can be found [here](src/shared/services/translation/t.ts). I don't think a language other than English will be necessary, but the formatting features are nice anyway.
|
||||
|
||||
## Design
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
declare module '*.svelte' {
|
||||
import { SvelteComponentTyped } from 'svelte';
|
||||
// noinspection JSUnusedGlobalSymbols -- because it is used
|
||||
export class Component extends SvelteComponentTyped {}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
89
package.json
89
package.json
|
@ -11,9 +11,11 @@
|
|||
},
|
||||
"main": "src/main.js",
|
||||
"engines": {
|
||||
"node": "12"
|
||||
"node": "14",
|
||||
"npm": "7"
|
||||
},
|
||||
"scripts": {
|
||||
"prepare": "husky install",
|
||||
"postinstall": "npm run rebuild",
|
||||
"postupdate": "npm run rebuild",
|
||||
"start": "electron . --enable-logging --env=dev",
|
||||
|
@ -45,69 +47,68 @@
|
|||
"prepush": "npm run build && npm run coverage"
|
||||
},
|
||||
"dependencies": {
|
||||
"better-sqlite3": "^7.1.2",
|
||||
"better-sqlite3": "^7.4.0",
|
||||
"electron-squirrel-startup": "^1.0.0",
|
||||
"fs-extra": "^9.1.0",
|
||||
"inversify": "^5.0.1",
|
||||
"fs-extra": "^10.0.0",
|
||||
"intl-messageformat": "^9.6.14",
|
||||
"inversify": "^5.1.1",
|
||||
"minimist": "^1.2.5",
|
||||
"reflect-metadata": "^0.1.13",
|
||||
"typeorm": "^0.2.30",
|
||||
"typeorm": "^0.2.32",
|
||||
"uuid": "^8.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-forge/cli": "^6.0.0-beta.54",
|
||||
"@electron-forge/maker-squirrel": "^6.0.0-beta.54",
|
||||
"@electron-forge/cli": "^6.0.0-beta.55",
|
||||
"@electron-forge/maker-squirrel": "^6.0.0-beta.55",
|
||||
"@prettier/plugin-xml": "^0.13.1",
|
||||
"@types/better-sqlite3": "^5.4.1",
|
||||
"@types/chai": "^4.2.14",
|
||||
"@types/chai": "^4.2.18",
|
||||
"@types/chai-fs": "^2.0.2",
|
||||
"@types/deep-equal-in-any-order": "^1.0.1",
|
||||
"@types/fs-extra": "^9.0.6",
|
||||
"@types/fs-extra": "^9.0.11",
|
||||
"@types/glob": "^7.1.3",
|
||||
"@types/minimist": "^1.2.1",
|
||||
"@types/mocha": "^8.2.0",
|
||||
"@types/node": "^12.19.15",
|
||||
"@types/sinon": "^9.0.10",
|
||||
"@types/mocha": "^8.2.2",
|
||||
"@types/node": "^14.17.0",
|
||||
"@types/sinon": "^10.0.0",
|
||||
"@types/uuid": "^8.3.0",
|
||||
"@types/webpack": "^4.41.26",
|
||||
"@typescript-eslint/eslint-plugin": "^4.14.0",
|
||||
"@typescript-eslint/parser": "^4.14.0",
|
||||
"chai": "^4.2.0",
|
||||
"@types/webpack": "^5.28.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.24.0",
|
||||
"@typescript-eslint/parser": "^4.24.0",
|
||||
"chai": "^4.3.4",
|
||||
"chai-fs": "^2.0.0",
|
||||
"chokidar": "^3.5.1",
|
||||
"concurrently": "^5.3.0",
|
||||
"deep-equal-in-any-order": "^1.0.28",
|
||||
"electron": "^10.3.0",
|
||||
"concurrently": "^6.1.0",
|
||||
"deep-equal-in-any-order": "^1.1.4",
|
||||
"electron": "^13.0.1",
|
||||
"electron-mocha": "^10.0.0",
|
||||
"electron-rebuild": "^2.3.4",
|
||||
"eslint": "^7.18.0",
|
||||
"eslint-config-prettier": "^7.2.0",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"fast-check": "^2.12.0",
|
||||
"glob": "^7.1.6",
|
||||
"handlebars": "^4.7.6",
|
||||
"husky": "^4.3.8",
|
||||
"lodash": "^4.17.20",
|
||||
"mocha": "^8.2.1",
|
||||
"nock": "^13.0.6",
|
||||
"electron-rebuild": "^2.3.5",
|
||||
"eslint": "^7.26.0",
|
||||
"eslint-config-prettier": "^8.3.0",
|
||||
"eslint-plugin-import": "^2.23.2",
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"eslint-plugin-svelte3": "^3.2.0",
|
||||
"fast-check": "^2.14.0",
|
||||
"glob": "^7.1.7",
|
||||
"handlebars": "^4.7.7",
|
||||
"husky": "^6.0.0",
|
||||
"lodash": "^4.17.21",
|
||||
"mocha": "^8.4.0",
|
||||
"nock": "^13.0.11",
|
||||
"nyc": "^15.1.0",
|
||||
"prettier": "^2.2.1",
|
||||
"sinon": "^9.2.4",
|
||||
"svelte": "^3.31.2",
|
||||
"svelte-loader": "^3.0.0",
|
||||
"ts-loader": "^8.0.14",
|
||||
"typescript": "^4.1.3",
|
||||
"webpack": "^5.17.0",
|
||||
"webpack-cli": "^4.4.0"
|
||||
"prettier": "^2.3.0",
|
||||
"prettier-plugin-svelte": "^2.3.0",
|
||||
"sinon": "^11.1.1",
|
||||
"svelte": "^3.38.2",
|
||||
"svelte-loader": "^3.1.1",
|
||||
"ts-loader": "^9.2.0",
|
||||
"typescript": "^4.2.4",
|
||||
"webpack": "^5.37.1",
|
||||
"webpack-cli": "^4.7.0"
|
||||
},
|
||||
"repository": "https://git.fuwafuwa.moe/Xymorot/RenaiApp",
|
||||
"bugs": "https://git.fuwafuwa.moe/Xymorot/RenaiApp/issues",
|
||||
"config": {
|
||||
"forge": "scripts/forge.config.js"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"pre-commit": "npm run precommit",
|
||||
"pre-push": "npm run prepush"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ const name = packageJson.productName;
|
|||
|
||||
if (name !== 'Renai') {
|
||||
throw new TypeError(
|
||||
`The product name "${name}" in package.json is not "Renai"! Change it before building but do not commit it.`
|
||||
`The product name "${name}" in package.json is not "Renai"! Change it before building but do not commit it.`,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ const path = require('path');
|
|||
module.exports = {
|
||||
mode: 'production',
|
||||
entry: path.resolve(__dirname, '../src/renderer.ts'),
|
||||
target: 'electron10-renderer',
|
||||
target: 'electron13-renderer',
|
||||
output: {
|
||||
path: path.resolve(__dirname, '../frontend'),
|
||||
filename: 'bundle.js',
|
||||
|
@ -21,14 +21,9 @@ module.exports = {
|
|||
configFile: path.resolve('tsconfig.renderer.json'),
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.mjs$/,
|
||||
include: /node_modules/,
|
||||
type: 'javascript/auto',
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.js', '.mjs'],
|
||||
extensions: ['.ts', '.js'],
|
||||
},
|
||||
};
|
||||
|
|
15
src/main.ts
15
src/main.ts
|
@ -1,23 +1,22 @@
|
|||
/* eslint-disable import/order -- this is the entry point for the application and some things have to happen before others */
|
||||
import { container } from './main/core/container';
|
||||
import './main/core/install';
|
||||
|
||||
import { app } from 'electron';
|
||||
import { container, Service } from './main/core/container';
|
||||
import './main/core/controller';
|
||||
import { isDev } from './main/core/env';
|
||||
import type { AppWindowInterface } from './main/modules/app-window/app-window-interface';
|
||||
import './main/core/install';
|
||||
|
||||
/**
|
||||
* 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: LoggerInterface = container.get('logger');
|
||||
const logger = container.get(Service.LOGGER);
|
||||
void logger.fatal(`Unhandled Rejection, see ${logger.getExceptionsLogFile()}`);
|
||||
throw reason;
|
||||
});
|
||||
|
||||
process.on('uncaughtException', (error) => {
|
||||
const logger: LoggerInterface = container.get('logger');
|
||||
const logger = container.get(Service.LOGGER);
|
||||
void logger.exception(error);
|
||||
if (isDev()) {
|
||||
// eslint-disable-next-line no-console -- only for development purposes
|
||||
|
@ -26,7 +25,7 @@ process.on('uncaughtException', (error) => {
|
|||
});
|
||||
|
||||
async function createWindow(): Promise<void> {
|
||||
const appWindowMain: AppWindowInterface = container.get('app-window-main');
|
||||
const appWindowMain = container.get(Service.APP_WINDOW_MAIN);
|
||||
await appWindowMain.open();
|
||||
|
||||
appWindowMain.window?.on('closed', () => {
|
||||
|
@ -49,7 +48,7 @@ app.on('window-all-closed', () => {
|
|||
app.on('activate', () => {
|
||||
// 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: AppWindowInterface = container.get('app-window-main');
|
||||
const appWindowMain = container.get(Service.APP_WINDOW_MAIN);
|
||||
if (appWindowMain.isClosed()) {
|
||||
void createWindow();
|
||||
}
|
||||
|
|
|
@ -1,40 +1,185 @@
|
|||
import 'reflect-metadata';
|
||||
import { Container, interfaces } from 'inversify';
|
||||
import type { AppWindowInterface } from '../modules/app-window/app-window-interface';
|
||||
import { MainAppWindow } from '../modules/app-window/main-app-window';
|
||||
import { Dialog } from '../modules/dialog/dialog';
|
||||
import { I18nTranslator } from '../modules/i18n/i18n-translator';
|
||||
import type { DialogInterface } from '../modules/dialog/dialog-interface';
|
||||
import { Logger } from '../modules/logger/logger';
|
||||
import { NhentaiApi } from '../modules/nhentai/nhentai-api';
|
||||
import '../modules/nhentai/nhentai-ipc-controller';
|
||||
import { NhentaiAppWindow } from '../modules/nhentai/nhentai-app-window';
|
||||
import type { NhentaiAppWindowInterface } from '../modules/nhentai/nhentai-app-window-interface';
|
||||
import { NhentaiSourceGetter } from '../modules/nhentai/nhentai-source-getter';
|
||||
import { AuthorNameSerializer } from '../modules/serialization/serializers/author-name-serializer';
|
||||
import { AuthorRoleNameSerializer } from '../modules/serialization/serializers/author-role-name-serializer';
|
||||
import { AuthorRoleSerializer } from '../modules/serialization/serializers/author-role-serializer';
|
||||
import { AuthorSerializer } from '../modules/serialization/serializers/author-serializer';
|
||||
import { CharacterTagSerializer } from '../modules/serialization/serializers/character-tag-serializer';
|
||||
import { CollectionNameSerializer } from '../modules/serialization/serializers/collection-name-serializer';
|
||||
import { CollectionPartSerializer } from '../modules/serialization/serializers/collection-part-serializer';
|
||||
import { CollectionSerializer } from '../modules/serialization/serializers/collection-serializer';
|
||||
import { CopySerializer } from '../modules/serialization/serializers/copy-serializer';
|
||||
import { InteractionTagSerializer } from '../modules/serialization/serializers/interaction-tag-serializer';
|
||||
import { LanguageSerializer } from '../modules/serialization/serializers/language-serializer';
|
||||
import { SiteNameSerializer } from '../modules/serialization/serializers/site-name-serializer';
|
||||
import { SiteSerializer } from '../modules/serialization/serializers/site-serializer';
|
||||
import { SourceSerializer } from '../modules/serialization/serializers/source-serializer';
|
||||
import { TagNameSerializer } from '../modules/serialization/serializers/tag-name-serializer';
|
||||
import { TagSerializer } from '../modules/serialization/serializers/tag-serializer';
|
||||
import { TransformationSerializer } from '../modules/serialization/serializers/transformation-serializer';
|
||||
import { TransformationTypeNameSerializer } from '../modules/serialization/serializers/transformation-type-name-serializer';
|
||||
import { TransformationTypeSerializer } from '../modules/serialization/serializers/transformation-type-serializer';
|
||||
import { WorkAuthorSerializer } from '../modules/serialization/serializers/work-author-serializer';
|
||||
import { WorkCharacterNameSerializer } from '../modules/serialization/serializers/work-character-name-serializer';
|
||||
import { WorkCharacterSerializer } from '../modules/serialization/serializers/work-character-serializer';
|
||||
import { WorkNameSerializer } from '../modules/serialization/serializers/work-name-serializer';
|
||||
import { WorkSerializer } from '../modules/serialization/serializers/work-serializer';
|
||||
import { WorkTagSerializer } from '../modules/serialization/serializers/work-tag-serializer';
|
||||
import { WorldCharacterNameSerializer } from '../modules/serialization/serializers/world-character-name-serializer';
|
||||
import { WorldCharacterSerializer } from '../modules/serialization/serializers/world-character-serializer';
|
||||
import { WorldNameSerializer } from '../modules/serialization/serializers/world-name-serializer';
|
||||
import { WorldSerializer } from '../modules/serialization/serializers/world-serializer';
|
||||
import type { SourceGetterInterface } from '../modules/source/source-getter-interface';
|
||||
import { Store } from '../modules/store/store';
|
||||
import '../modules/entity-api/entity-api-ipc-controller';
|
||||
import BindingToSyntax = interfaces.BindingToSyntax;
|
||||
|
||||
export const enum Service {
|
||||
LOGGER = 'LOGGER',
|
||||
|
||||
AUTHOR_SERIALIZER = 'AUTHOR_SERIALIZER',
|
||||
AUTHOR_NAME_SERIALIZER = 'AUTHOR_NAME_SERIALIZER',
|
||||
AUTHOR_ROLE_SERIALIZER = 'AUTHOR_ROLE_SERIALIZER',
|
||||
AUTHOR_ROLE_NAME_SERIALIZER = 'AUTHOR_ROLE_NAME_SERIALIZER',
|
||||
CHARACTER_TAG_SERIALIZER = 'CHARACTER_TAG_SERIALIZER',
|
||||
COLLECTION_SERIALIZER = 'COLLECTION_SERIALIZER',
|
||||
COLLECTION_NAME_SERIALIZER = 'COLLECTION_NAME_SERIALIZER',
|
||||
COLLECTION_PART_SERIALIZER = 'COLLECTION_PART_SERIALIZER',
|
||||
COPY_SERIALIZER = 'COPY_SERIALIZER',
|
||||
INTERACTION_TAG_SERIALIZER = 'INTERACTION_TAG_SERIALIZER',
|
||||
LANGUAGE_SERIALIZER = 'LANGUAGE_SERIALIZER',
|
||||
SITE_SERIALIZER = 'SITE_SERIALIZER',
|
||||
SITE_NAME_SERIALIZER = 'SITE_NAME_SERIALIZER',
|
||||
SOURCE_SERIALIZER = 'SOURCE_SERIALIZER',
|
||||
TAG_SERIALIZER = 'TAG_SERIALIZER',
|
||||
TAG_NAME_SERIALIZER = 'TAG_NAME_SERIALIZER',
|
||||
TRANSFORMATION_SERIALIZER = 'TRANSFORMATION_SERIALIZER',
|
||||
TRANSFORMATION_TYPE_SERIALIZER = 'TRANSFORMATION_TYPE_SERIALIZER',
|
||||
TRANSFORMATION_TYPE_NAME_SERIALIZER = 'TRANSFORMATION_TYPE_NAME_SERIALIZER',
|
||||
WORK_AUTHOR_SERIALIZER = 'WORK_AUTHOR_SERIALIZER',
|
||||
WORK_CHARACTER_SERIALIZER = 'WORK_CHARACTER_SERIALIZER',
|
||||
WORK_CHARACTER_NAME_SERIALIZER = 'WORK_CHARACTER_NAME_SERIALIZER',
|
||||
WORK_SERIALIZER = 'WORK_SERIALIZER',
|
||||
WORK_NAME_SERIALIZER = 'WORK_NAME_SERIALIZER',
|
||||
WORK_TAG_SERIALIZER = 'WORK_TAG_SERIALIZER',
|
||||
WORLD_SERIALIZER = 'WORLD_SERIALIZER',
|
||||
WORLD_NAME_SERIALIZER = 'WORLD_NAME_SERIALIZER',
|
||||
WORLD_CHARACTER_SERIALIZER = 'WORLD_CHARACTER_SERIALIZER',
|
||||
WORLD_CHARACTER_NAME_SERIALIZER = 'WORLD_CHARACTER_NAME_SERIALIZER',
|
||||
|
||||
DIALOG = 'DIALOG',
|
||||
|
||||
STORE = 'STORE',
|
||||
|
||||
NHENTAI_APP_WINDOW = 'NHENTAI_APP_WINDOW',
|
||||
NHENTAI_API = 'NHENTAI_API',
|
||||
NHENTAI_SOURCE_GETTER = 'NHENTAI_SOURCE_GETTER',
|
||||
|
||||
APP_WINDOW_MAIN = 'APP_WINDOW_MAIN',
|
||||
}
|
||||
|
||||
type ServiceType = {
|
||||
[Service.LOGGER]: LoggerInterface;
|
||||
|
||||
[Service.AUTHOR_SERIALIZER]: AuthorSerializer;
|
||||
[Service.AUTHOR_NAME_SERIALIZER]: AuthorNameSerializer;
|
||||
[Service.AUTHOR_ROLE_SERIALIZER]: AuthorRoleSerializer;
|
||||
[Service.AUTHOR_ROLE_NAME_SERIALIZER]: AuthorRoleNameSerializer;
|
||||
[Service.CHARACTER_TAG_SERIALIZER]: CharacterTagSerializer;
|
||||
[Service.COLLECTION_SERIALIZER]: CollectionSerializer;
|
||||
[Service.COLLECTION_NAME_SERIALIZER]: CollectionNameSerializer;
|
||||
[Service.COLLECTION_PART_SERIALIZER]: CollectionPartSerializer;
|
||||
[Service.COPY_SERIALIZER]: CopySerializer;
|
||||
[Service.INTERACTION_TAG_SERIALIZER]: InteractionTagSerializer;
|
||||
[Service.LANGUAGE_SERIALIZER]: LanguageSerializer;
|
||||
[Service.SITE_SERIALIZER]: SiteSerializer;
|
||||
[Service.SITE_NAME_SERIALIZER]: SiteNameSerializer;
|
||||
[Service.SOURCE_SERIALIZER]: SourceSerializer;
|
||||
[Service.TAG_SERIALIZER]: TagSerializer;
|
||||
[Service.TAG_NAME_SERIALIZER]: TagNameSerializer;
|
||||
[Service.TRANSFORMATION_SERIALIZER]: TransformationSerializer;
|
||||
[Service.TRANSFORMATION_TYPE_SERIALIZER]: TransformationTypeSerializer;
|
||||
[Service.TRANSFORMATION_TYPE_NAME_SERIALIZER]: TransformationTypeNameSerializer;
|
||||
[Service.WORK_AUTHOR_SERIALIZER]: WorkAuthorSerializer;
|
||||
[Service.WORK_CHARACTER_SERIALIZER]: WorkCharacterSerializer;
|
||||
[Service.WORK_CHARACTER_NAME_SERIALIZER]: WorkCharacterNameSerializer;
|
||||
[Service.WORK_SERIALIZER]: WorkSerializer;
|
||||
[Service.WORK_NAME_SERIALIZER]: WorkNameSerializer;
|
||||
[Service.WORK_TAG_SERIALIZER]: WorkTagSerializer;
|
||||
[Service.WORLD_SERIALIZER]: WorldSerializer;
|
||||
[Service.WORLD_NAME_SERIALIZER]: WorldNameSerializer;
|
||||
[Service.WORLD_CHARACTER_SERIALIZER]: WorldCharacterSerializer;
|
||||
[Service.WORLD_CHARACTER_NAME_SERIALIZER]: WorldCharacterNameSerializer;
|
||||
|
||||
[Service.DIALOG]: DialogInterface;
|
||||
|
||||
[Service.STORE]: StoreInterface;
|
||||
|
||||
[Service.NHENTAI_APP_WINDOW]: NhentaiAppWindowInterface;
|
||||
[Service.NHENTAI_API]: NhentaiApiInterface;
|
||||
[Service.NHENTAI_SOURCE_GETTER]: SourceGetterInterface;
|
||||
[Service.APP_WINDOW_MAIN]: AppWindowInterface;
|
||||
};
|
||||
|
||||
export const container = {
|
||||
original: new Container({ defaultScope: 'Singleton', skipBaseClassChecks: true }),
|
||||
bind<T>(key: string): BindingToSyntax<T> {
|
||||
return this.original.bind<T>(Symbol.for(key));
|
||||
bind<S extends Service>(key: S): BindingToSyntax<ServiceType[S]> {
|
||||
return this.original.bind<ServiceType[S]>(Symbol.for(key));
|
||||
},
|
||||
unbind(key: string): void {
|
||||
unbind(key: Service): void {
|
||||
return this.original.unbind(Symbol.for(key));
|
||||
},
|
||||
get<T>(key: string): T {
|
||||
return this.original.get<T>(Symbol.for(key));
|
||||
get<S extends Service>(key: S): ServiceType[S] {
|
||||
return this.original.get<ServiceType[S]>(Symbol.for(key));
|
||||
},
|
||||
};
|
||||
|
||||
container.bind('logger').to(Logger);
|
||||
container.bind(Service.LOGGER).to(Logger);
|
||||
|
||||
container.bind('i18n-translator').to(I18nTranslator);
|
||||
container.bind(Service.AUTHOR_SERIALIZER).to(AuthorSerializer);
|
||||
container.bind(Service.AUTHOR_NAME_SERIALIZER).to(AuthorNameSerializer);
|
||||
container.bind(Service.AUTHOR_ROLE_SERIALIZER).to(AuthorRoleSerializer);
|
||||
container.bind(Service.AUTHOR_ROLE_NAME_SERIALIZER).to(AuthorRoleNameSerializer);
|
||||
container.bind(Service.CHARACTER_TAG_SERIALIZER).to(CharacterTagSerializer);
|
||||
container.bind(Service.COLLECTION_SERIALIZER).to(CollectionSerializer);
|
||||
container.bind(Service.COLLECTION_NAME_SERIALIZER).to(CollectionNameSerializer);
|
||||
container.bind(Service.COLLECTION_PART_SERIALIZER).to(CollectionPartSerializer);
|
||||
container.bind(Service.COPY_SERIALIZER).to(CopySerializer);
|
||||
container.bind(Service.INTERACTION_TAG_SERIALIZER).to(InteractionTagSerializer);
|
||||
container.bind(Service.LANGUAGE_SERIALIZER).to(LanguageSerializer);
|
||||
container.bind(Service.SITE_SERIALIZER).to(SiteSerializer);
|
||||
container.bind(Service.SITE_NAME_SERIALIZER).to(SiteNameSerializer);
|
||||
container.bind(Service.SOURCE_SERIALIZER).to(SourceSerializer);
|
||||
container.bind(Service.TAG_SERIALIZER).to(TagSerializer);
|
||||
container.bind(Service.TAG_NAME_SERIALIZER).to(TagNameSerializer);
|
||||
container.bind(Service.TRANSFORMATION_SERIALIZER).to(TransformationSerializer);
|
||||
container.bind(Service.TRANSFORMATION_TYPE_SERIALIZER).to(TransformationTypeSerializer);
|
||||
container.bind(Service.TRANSFORMATION_TYPE_NAME_SERIALIZER).to(TransformationTypeNameSerializer);
|
||||
container.bind(Service.WORK_AUTHOR_SERIALIZER).to(WorkAuthorSerializer);
|
||||
container.bind(Service.WORK_CHARACTER_SERIALIZER).to(WorkCharacterSerializer);
|
||||
container.bind(Service.WORK_CHARACTER_NAME_SERIALIZER).to(WorkCharacterNameSerializer);
|
||||
container.bind(Service.WORK_SERIALIZER).to(WorkSerializer);
|
||||
container.bind(Service.WORK_NAME_SERIALIZER).to(WorkNameSerializer);
|
||||
container.bind(Service.WORK_TAG_SERIALIZER).to(WorkTagSerializer);
|
||||
container.bind(Service.WORLD_SERIALIZER).to(WorldSerializer);
|
||||
container.bind(Service.WORLD_NAME_SERIALIZER).to(WorldNameSerializer);
|
||||
container.bind(Service.WORLD_CHARACTER_SERIALIZER).to(WorldCharacterSerializer);
|
||||
container.bind(Service.WORLD_CHARACTER_NAME_SERIALIZER).to(WorldCharacterNameSerializer);
|
||||
|
||||
container.bind('dialog').to(Dialog);
|
||||
container.bind(Service.DIALOG).to(Dialog);
|
||||
|
||||
container.bind('store').to(Store);
|
||||
container.bind(Service.STORE).to(Store);
|
||||
|
||||
container.bind('nhentai-app-window').to(NhentaiAppWindow);
|
||||
container.bind('nhentai-api').to(NhentaiApi);
|
||||
container.bind('nhentai-source-getter').to(NhentaiSourceGetter);
|
||||
container.bind(Service.NHENTAI_APP_WINDOW).to(NhentaiAppWindow);
|
||||
container.bind(Service.NHENTAI_API).to(NhentaiApi);
|
||||
container.bind(Service.NHENTAI_SOURCE_GETTER).to(NhentaiSourceGetter);
|
||||
|
||||
container.bind('app-window-main').to(MainAppWindow);
|
||||
container.bind(Service.APP_WINDOW_MAIN).to(MainAppWindow);
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
import '../modules/nhentai/nhentai-ipc-controller';
|
||||
import '../modules/entity-api/entity-api-ipc-controller';
|
|
@ -1,5 +1,5 @@
|
|||
import path from 'path';
|
||||
import { Connection, createConnection as ormCreateConnection } from 'typeorm';
|
||||
import { Connection, createConnection as ormCreateConnection, EntityManager, EntityTarget, Repository } from 'typeorm';
|
||||
import type { BetterSqlite3ConnectionOptions } from 'typeorm/driver/better-sqlite3/BetterSqlite3ConnectionOptions';
|
||||
import { appPath } from './app-path';
|
||||
|
||||
|
@ -50,5 +50,16 @@ const connections = {
|
|||
};
|
||||
|
||||
export function getConnection(database: Database): Promise<Connection> {
|
||||
return Promise.resolve(connections[database]);
|
||||
return connections[database];
|
||||
}
|
||||
|
||||
export function getManager(database: Database): Promise<EntityManager> {
|
||||
return getConnection(database).then((c) => c.manager);
|
||||
}
|
||||
|
||||
export function getRepository<T>(
|
||||
target: EntityTarget<T>,
|
||||
database: Database = Database.LIBRARY,
|
||||
): Promise<Repository<T>> {
|
||||
return getManager(database).then((m) => m.getRepository(target));
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { inject as inversifyInject } from 'inversify';
|
||||
import type { Service } from './container';
|
||||
|
||||
export function inject(key: string): ReturnType<typeof inversifyInject> {
|
||||
export function inject(key: Service): ReturnType<typeof inversifyInject> {
|
||||
return inversifyInject(Symbol.for(key));
|
||||
}
|
||||
|
|
|
@ -9,6 +9,6 @@ export const maxValue = Number.MAX_SAFE_INTEGER;
|
|||
export function PercentCheck(column: string): ClassDecorator & PropertyDecorator {
|
||||
return Check(
|
||||
`${column} needs to be between ${minValue} and ${maxValue}`,
|
||||
`${column} >= ${minValue} AND ${column} <= ${maxValue}`
|
||||
`${column} >= ${minValue} AND ${column} <= ${maxValue}`,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,6 @@ export class Author implements AuthorEntityInterface {
|
|||
@OneToMany(() => AuthorName, (authorName: AuthorNameEntityInterface) => authorName.entity)
|
||||
public names!: Promise<AuthorNameEntityInterface[]>;
|
||||
|
||||
@OneToMany(() => WorkAuthor, (workAuthor: WorkAuthorEntityInterface) => workAuthor.author, {})
|
||||
@OneToMany(() => WorkAuthor, (workAuthor: WorkAuthorEntityInterface) => workAuthor.author)
|
||||
public workAuthors!: Promise<WorkAuthorEntityInterface[]>;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,12 @@ import { Work } from './work';
|
|||
@Entity()
|
||||
export class Language implements LanguageEntityInterface {
|
||||
@PrimaryColumn()
|
||||
public code!: string;
|
||||
public readonly code!: LangCode;
|
||||
|
||||
@ManyToMany(() => Work, (work: WorkEntityInterface) => work.languages)
|
||||
public works!: Promise<WorkEntityInterface[]>;
|
||||
|
||||
public get id(): LangCode {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ export class TransformationTypeName implements TransformationTypeNameEntityInter
|
|||
nullable: false,
|
||||
onDelete: 'CASCADE',
|
||||
onUpdate: 'CASCADE',
|
||||
}
|
||||
},
|
||||
)
|
||||
public entity!: Promise<TransformationTypeEntityInterface>;
|
||||
|
||||
|
|
|
@ -16,7 +16,6 @@ export class TransformationType implements TransformationTypeEntityInterface {
|
|||
@OneToMany(
|
||||
() => TransformationTypeName,
|
||||
(transformationTypeName: TransformationTypeNameEntityInterface) => transformationTypeName.entity,
|
||||
{}
|
||||
)
|
||||
public names!: Promise<TransformationTypeNameEntityInterface[]>;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ export class Transformation implements TransformationEntityInterface {
|
|||
nullable: false,
|
||||
onDelete: 'RESTRICT',
|
||||
onUpdate: 'CASCADE',
|
||||
}
|
||||
},
|
||||
)
|
||||
public type!: Promise<TransformationTypeEntityInterface>;
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ export class Work implements WorkEntityInterface {
|
|||
@OneToMany(() => WorkName, (workName: WorkNameEntityInterface) => workName.entity)
|
||||
public names!: Promise<WorkNameEntityInterface[]>;
|
||||
|
||||
@OneToMany(() => Copy, (copy: CopyEntityInterface) => copy.original, {})
|
||||
@OneToMany(() => Copy, (copy: CopyEntityInterface) => copy.original)
|
||||
public copies!: Promise<CopyEntityInterface[]>;
|
||||
|
||||
@OneToMany(() => Transformation, (transformation: TransformationEntityInterface) => transformation.byWork)
|
||||
|
|
|
@ -16,7 +16,7 @@ export class WorldCharacter implements WorldCharacterEntityInterface {
|
|||
|
||||
@OneToMany(
|
||||
() => WorldCharacterName,
|
||||
(worldCharacterName: WorldCharacterNameEntityInterface) => worldCharacterName.entity
|
||||
(worldCharacterName: WorldCharacterNameEntityInterface) => worldCharacterName.entity,
|
||||
)
|
||||
public names!: Promise<WorldCharacterNameEntityInterface[]>;
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -65,7 +65,7 @@ export class addLanguages1611508644004 implements MigrationInterface {
|
|||
await queryRunner.query(`INSERT INTO language VALUES('${LangCode.HIRI_MOTU}')`);
|
||||
await queryRunner.query(`INSERT INTO language VALUES('${LangCode.HUNGARIAN}')`);
|
||||
await queryRunner.query(
|
||||
`INSERT INTO language VALUES('${LangCode.INTERLINGUA_INTERNATIONAL_AUXILIARY_LANGUAGE_ASSOCIATION}')`
|
||||
`INSERT INTO language VALUES('${LangCode.INTERLINGUA_INTERNATIONAL_AUXILIARY_LANGUAGE_ASSOCIATION}')`,
|
||||
);
|
||||
await queryRunner.query(`INSERT INTO language VALUES('${LangCode.INDONESIAN}')`);
|
||||
await queryRunner.query(`INSERT INTO language VALUES('${LangCode.INTERLINGUE_OCCIDENTAL}')`);
|
||||
|
@ -124,7 +124,7 @@ export class addLanguages1611508644004 implements MigrationInterface {
|
|||
await queryRunner.query(`INSERT INTO language VALUES('${LangCode.OCCITAN}')`);
|
||||
await queryRunner.query(`INSERT INTO language VALUES('${LangCode.OJIBWA}')`);
|
||||
await queryRunner.query(
|
||||
`INSERT INTO language VALUES('${LangCode.CHURCH_SLAVIC_OLD_SLAVONIC_CHURCH_SLAVONIC_OLD_BULGARIAN_OLD_CHURCH_SLAVONIC}')`
|
||||
`INSERT INTO language VALUES('${LangCode.CHURCH_SLAVIC_OLD_SLAVONIC_CHURCH_SLAVONIC_OLD_BULGARIAN_OLD_CHURCH_SLAVONIC}')`,
|
||||
);
|
||||
await queryRunner.query(`INSERT INTO language VALUES('${LangCode.OROMO}')`);
|
||||
await queryRunner.query(`INSERT INTO language VALUES('${LangCode.ORIYA}')`);
|
||||
|
|
|
@ -6,11 +6,11 @@ export class initialMigration1587511036078 implements MigrationInterface {
|
|||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "store_value" ("key" varchar PRIMARY KEY NOT NULL, "value" text NOT NULL)`,
|
||||
undefined
|
||||
undefined,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "query-result-cache" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "identifier" varchar, "time" bigint NOT NULL, "duration" integer NOT NULL, "query" text NOT NULL, "result" text NOT NULL)`,
|
||||
undefined
|
||||
undefined,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ export abstract class AppWindow implements AppWindowInterface {
|
|||
})
|
||||
.catch(() => {
|
||||
void this.logger.warning(
|
||||
`Could not get the of the presumed HTMLTimeElement with the selector '${selector}'.`
|
||||
`Could not get the of the presumed HTMLTimeElement with the selector '${selector}'.`,
|
||||
);
|
||||
resolve(undefined);
|
||||
});
|
||||
|
|
|
@ -8,7 +8,7 @@ export abstract class FileAppWindow extends AppWindow {
|
|||
logger: LoggerInterface,
|
||||
uri: string,
|
||||
options: BrowserWindowConstructorOptions = {},
|
||||
loadOptions: LoadFileOptions = {}
|
||||
loadOptions: LoadFileOptions = {},
|
||||
) {
|
||||
super(logger, uri, options);
|
||||
this.loadOptions = loadOptions;
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Service } from '../../core/container';
|
||||
import { inject } from '../../core/inject';
|
||||
import { FileAppWindow } from './file-app-window';
|
||||
|
||||
@injectable()
|
||||
export class MainAppWindow extends FileAppWindow {
|
||||
public constructor(@inject('logger') logger: LoggerInterface) {
|
||||
public constructor(@inject(Service.LOGGER) logger: LoggerInterface) {
|
||||
super(logger, 'frontend/index.html', {
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ export abstract class SiteAppWindow extends UrlAppWindow implements SiteAppWindo
|
|||
logger: LoggerInterface,
|
||||
uri: string,
|
||||
options: BrowserWindowConstructorOptions = {},
|
||||
loadOptions: LoadURLOptions = {}
|
||||
loadOptions: LoadURLOptions = {},
|
||||
) {
|
||||
super(logger, uri, options, loadOptions);
|
||||
this.windowLock = new SimpleMutex();
|
||||
|
|
|
@ -16,6 +16,6 @@ interface UrlAppWindowInterface extends AppWindowInterface {
|
|||
loadUrlSafe(
|
||||
url: string,
|
||||
readyCheck?: (webContents: WebContents) => Promise<boolean>,
|
||||
options?: LoadURLOptions
|
||||
options?: LoadURLOptions,
|
||||
): Promise<void>;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ export abstract class UrlAppWindow extends AppWindow implements UrlAppWindowInte
|
|||
logger: LoggerInterface,
|
||||
uri: string,
|
||||
options: BrowserWindowConstructorOptions = {},
|
||||
loadOptions: LoadURLOptions = {}
|
||||
loadOptions: LoadURLOptions = {},
|
||||
) {
|
||||
super(logger, uri, {
|
||||
...options,
|
||||
|
@ -78,36 +78,38 @@ export abstract class UrlAppWindow extends AppWindow implements UrlAppWindowInte
|
|||
public async loadUrlSafe(
|
||||
url: string,
|
||||
readyCheck?: (webContents: WebContents) => Promise<boolean>,
|
||||
options?: LoadURLOptions
|
||||
options?: LoadURLOptions,
|
||||
): Promise<void> {
|
||||
return this.loadWait.then(async () => {
|
||||
let failedLoad = true;
|
||||
while (failedLoad) {
|
||||
await this.loadUrl(url, options).then((httpResponseCode) => {
|
||||
failedLoad = HttpCode.BAD_REQUEST <= httpResponseCode;
|
||||
if (HttpCode.TOO_MANY_REQUESTS === httpResponseCode) {
|
||||
// go slower
|
||||
this.loadWaitTime += this.loadWaitTimeStep;
|
||||
// but go faster again after a time
|
||||
clearTimeout(this.loadWaitTimeStepResetTimeout);
|
||||
this.loadWaitTimeStepResetTimeout = setTimeout(() => {
|
||||
this.loadWaitTime = 0;
|
||||
}, this.loadWaitTimeResetTimeoutTime);
|
||||
}
|
||||
});
|
||||
if (failedLoad) {
|
||||
await promisify(setTimeout)(this.waitInterval);
|
||||
}
|
||||
await this.loadWait;
|
||||
let failedLoad = true;
|
||||
while (failedLoad) {
|
||||
const httpResponseCode = await this.loadUrl(url, options);
|
||||
failedLoad = HttpCode.BAD_REQUEST <= httpResponseCode;
|
||||
switch (httpResponseCode) {
|
||||
case HttpCode.NOT_FOUND:
|
||||
throw new Error(`Loading ${url} gave the unrecoverable HTTP status code ${httpResponseCode}.`);
|
||||
case HttpCode.TOO_MANY_REQUESTS:
|
||||
// go slower
|
||||
this.loadWaitTime += this.loadWaitTimeStep;
|
||||
// but go faster again after a time
|
||||
clearTimeout(this.loadWaitTimeStepResetTimeout);
|
||||
this.loadWaitTimeStepResetTimeout = setTimeout(() => {
|
||||
this.loadWaitTime = 0;
|
||||
}, this.loadWaitTimeResetTimeoutTime);
|
||||
break;
|
||||
}
|
||||
this.loadWait = promisify(setTimeout)(this.loadWaitTime);
|
||||
if (readyCheck) {
|
||||
let isReady = await readyCheck(this.getWindow().webContents);
|
||||
do {
|
||||
await promisify(setTimeout)(Milliseconds.TEN);
|
||||
isReady = await readyCheck(this.getWindow().webContents);
|
||||
} while (!isReady);
|
||||
if (failedLoad) {
|
||||
await promisify(setTimeout)(this.waitInterval);
|
||||
}
|
||||
});
|
||||
}
|
||||
this.loadWait = promisify(setTimeout)(this.loadWaitTime);
|
||||
if (readyCheck) {
|
||||
let isReady = await readyCheck(this.getWindow().webContents);
|
||||
do {
|
||||
await promisify(setTimeout)(Milliseconds.TEN);
|
||||
isReady = await readyCheck(this.getWindow().webContents);
|
||||
} while (!isReady);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -9,7 +9,7 @@ export abstract class CloudflareSiteAppWindow extends SiteAppWindow {
|
|||
const onDidNavigate: (event: Event, url: string, httpResponseCode: number) => void = async (
|
||||
event,
|
||||
navigationUrl,
|
||||
httpResponseCode
|
||||
httpResponseCode,
|
||||
) => {
|
||||
if (!(await isCloudFlareSite(this.getWindow().webContents))) {
|
||||
this.getWindow().webContents.removeListener('did-navigate', onDidNavigate);
|
||||
|
|
|
@ -15,12 +15,12 @@ export const cloudflareSiteCsp: ContentSecurityPolicy = {
|
|||
|
||||
export function humanInteractionRequired(webContents: WebContents): Promise<boolean> {
|
||||
return webContents.executeJavaScript(
|
||||
"[...document.querySelectorAll('iframe')].map(iframe => (new URL(iframe.src)).hostname.match(/hcaptcha/)).some(e => e)"
|
||||
"[...document.querySelectorAll('iframe')].map(iframe => (new URL(iframe.src)).hostname.match(/hcaptcha/)).some(e => e)",
|
||||
) as Promise<boolean>;
|
||||
}
|
||||
|
||||
export function isCloudFlareSite(webContents: WebContents): Promise<boolean> {
|
||||
return webContents.executeJavaScript(
|
||||
"!!document.querySelector('.cf-browser-verification, #cf-content, #cf-wrapper') || !!window._cf_translation"
|
||||
"!!document.querySelector('.cf-browser-verification, #cf-content, #cf-wrapper') || !!window._cf_translation",
|
||||
) as Promise<boolean>;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export function dateObjectToString(date: Date): string {
|
||||
return `${date.getUTCFullYear()}-${`${date.getUTCMonth()}`.padStart(2, '0')}-${`${date.getUTCDate()}`.padStart(
|
||||
2,
|
||||
'0'
|
||||
'0',
|
||||
)}`;
|
||||
}
|
||||
|
|
|
@ -1,20 +1,14 @@
|
|||
import { dialog, OpenDialogOptions } from 'electron';
|
||||
import { injectable } from 'inversify';
|
||||
import { inject } from '../../core/inject';
|
||||
import { t } from '../../../shared/services/translation/t';
|
||||
import type { DialogInterface } from './dialog-interface';
|
||||
|
||||
@injectable()
|
||||
export class Dialog implements DialogInterface {
|
||||
private readonly translator: I18nTranslatorInterface;
|
||||
|
||||
public constructor(@inject('i18n-translator') translator: I18nTranslatorInterface) {
|
||||
this.translator = translator;
|
||||
}
|
||||
|
||||
public selectFolder(options: OpenDialogOptions): ReturnType<typeof dialog.showOpenDialog> {
|
||||
return dialog.showOpenDialog({
|
||||
...{
|
||||
title: this.translator.t('select a folder'),
|
||||
title: t('imperatives.dialog.select_folder'),
|
||||
},
|
||||
...options,
|
||||
...{
|
||||
|
|
|
@ -0,0 +1,265 @@
|
|||
import type { EntityTarget } from 'typeorm';
|
||||
import { container, Service } from '../../core/container';
|
||||
import { Database, getManager } from '../../core/database';
|
||||
import { Author } from '../../entities/library/author';
|
||||
import { AuthorName } from '../../entities/library/author-name';
|
||||
import { AuthorRole } from '../../entities/library/author-role';
|
||||
import { AuthorRoleName } from '../../entities/library/author-role-name';
|
||||
import { CharacterTag } from '../../entities/library/character-tag';
|
||||
import { Collection } from '../../entities/library/collection';
|
||||
import { CollectionName } from '../../entities/library/collection-name';
|
||||
import { CollectionPart } from '../../entities/library/collection-part';
|
||||
import { Copy } from '../../entities/library/copy';
|
||||
import { InteractionTag } from '../../entities/library/interaction-tag';
|
||||
import { Site } from '../../entities/library/site';
|
||||
import { SiteName } from '../../entities/library/site-name';
|
||||
import { Source } from '../../entities/library/source';
|
||||
import { Tag } from '../../entities/library/tag';
|
||||
import { TagName } from '../../entities/library/tag-name';
|
||||
import { Transformation } from '../../entities/library/transformation';
|
||||
import { TransformationType } from '../../entities/library/transformation-type';
|
||||
import { TransformationTypeName } from '../../entities/library/transformation-type-name';
|
||||
import { Work } from '../../entities/library/work';
|
||||
import { WorkAuthor } from '../../entities/library/work-author';
|
||||
import { WorkCharacter } from '../../entities/library/work-character';
|
||||
import { WorkCharacterName } from '../../entities/library/work-character-name';
|
||||
import { WorkName } from '../../entities/library/work-name';
|
||||
import { WorkTag } from '../../entities/library/work-tag';
|
||||
import { World } from '../../entities/library/world';
|
||||
import { WorldCharacter } from '../../entities/library/world-character';
|
||||
import { WorldCharacterName } from '../../entities/library/world-character-name';
|
||||
import { WorldName } from '../../entities/library/world-name';
|
||||
import { ipcServer } from '../ipc/ipc-server';
|
||||
import type { Serializer } from '../serialization/serializer';
|
||||
|
||||
type CreateSerializedType = {
|
||||
[IpcChannel.ENTITY_CREATE_AUTHOR]: AuthorSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_AUTHOR_NAME]: AuthorNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_AUTHOR_ROLE]: AuthorRoleSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_AUTHOR_ROLE_NAME]: AuthorRoleNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_CHARACTER_TAG]: CharacterTagSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_COLLECTION]: CollectionSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_COLLECTION_NAME]: CollectionNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_COLLECTION_PART]: CollectionPartSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_COPY]: CopySerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_INTERACTION_TAG]: InteractionTagSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_SITE]: SiteSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_SITE_NAME]: SiteNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_SOURCE]: SourceSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_TAG]: TagSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_TAG_NAME]: TagNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_TRANSFORMATION]: TransformationSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_TRANSFORMATION_TYPE]: TransformationTypeSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_TRANSFORMATION_TYPE_NAME]: TransformationTypeNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_WORK_AUTHOR]: WorkAuthorSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_WORK_CHARACTER]: WorkCharacterSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_WORK_CHARACTER_NAME]: WorkCharacterNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_WORK]: WorkSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_WORK_NAME]: WorkNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_WORK_TAG]: WorkTagSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_WORLD]: WorldSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_WORLD_NAME]: WorldNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_WORLD_CHARACTER]: WorldCharacterSerializedInterface;
|
||||
[IpcChannel.ENTITY_CREATE_WORLD_CHARACTER_NAME]: WorldCharacterNameSerializedInterface;
|
||||
};
|
||||
|
||||
type CreateEntityType = {
|
||||
[IpcChannel.ENTITY_CREATE_AUTHOR]: Author;
|
||||
[IpcChannel.ENTITY_CREATE_AUTHOR_NAME]: AuthorName;
|
||||
[IpcChannel.ENTITY_CREATE_AUTHOR_ROLE]: AuthorRole;
|
||||
[IpcChannel.ENTITY_CREATE_AUTHOR_ROLE_NAME]: AuthorRoleName;
|
||||
[IpcChannel.ENTITY_CREATE_CHARACTER_TAG]: CharacterTag;
|
||||
[IpcChannel.ENTITY_CREATE_COLLECTION]: Collection;
|
||||
[IpcChannel.ENTITY_CREATE_COLLECTION_NAME]: CollectionName;
|
||||
[IpcChannel.ENTITY_CREATE_COLLECTION_PART]: CollectionPart;
|
||||
[IpcChannel.ENTITY_CREATE_COPY]: Copy;
|
||||
[IpcChannel.ENTITY_CREATE_INTERACTION_TAG]: InteractionTag;
|
||||
[IpcChannel.ENTITY_CREATE_SITE]: Site;
|
||||
[IpcChannel.ENTITY_CREATE_SITE_NAME]: SiteName;
|
||||
[IpcChannel.ENTITY_CREATE_SOURCE]: Source;
|
||||
[IpcChannel.ENTITY_CREATE_TAG]: Tag;
|
||||
[IpcChannel.ENTITY_CREATE_TAG_NAME]: TagName;
|
||||
[IpcChannel.ENTITY_CREATE_TRANSFORMATION]: Transformation;
|
||||
[IpcChannel.ENTITY_CREATE_TRANSFORMATION_TYPE]: TransformationType;
|
||||
[IpcChannel.ENTITY_CREATE_TRANSFORMATION_TYPE_NAME]: TransformationTypeName;
|
||||
[IpcChannel.ENTITY_CREATE_WORK_AUTHOR]: WorkAuthor;
|
||||
[IpcChannel.ENTITY_CREATE_WORK_CHARACTER]: WorkCharacter;
|
||||
[IpcChannel.ENTITY_CREATE_WORK_CHARACTER_NAME]: WorkCharacterName;
|
||||
[IpcChannel.ENTITY_CREATE_WORK]: Work;
|
||||
[IpcChannel.ENTITY_CREATE_WORK_NAME]: WorkName;
|
||||
[IpcChannel.ENTITY_CREATE_WORK_TAG]: WorkTag;
|
||||
[IpcChannel.ENTITY_CREATE_WORLD]: World;
|
||||
[IpcChannel.ENTITY_CREATE_WORLD_NAME]: WorldName;
|
||||
[IpcChannel.ENTITY_CREATE_WORLD_CHARACTER]: WorldCharacter;
|
||||
[IpcChannel.ENTITY_CREATE_WORLD_CHARACTER_NAME]: WorldCharacterName;
|
||||
};
|
||||
|
||||
async function create<T extends keyof CreateSerializedType>(
|
||||
partial: Partial<CreateSerializedType[T]>,
|
||||
entityTarget: EntityTarget<CreateEntityType[T]>,
|
||||
serializer: Serializer<CreateEntityType[T], CreateSerializedType[T]>,
|
||||
): Promise<CreateSerializedType[T]> {
|
||||
const manager = await getManager(Database.LIBRARY);
|
||||
const entity = manager.create(entityTarget, serializer.deserialize(partial) as DeepPartial<CreateEntityType[T]>);
|
||||
return serializer.serialize(await manager.save(entity));
|
||||
}
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_AUTHOR, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_AUTHOR>(partial, Author, container.get(Service.AUTHOR_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_AUTHOR_NAME, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_AUTHOR_NAME>(partial, AuthorName, container.get(Service.AUTHOR_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_AUTHOR_ROLE, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_AUTHOR_ROLE>(partial, AuthorRole, container.get(Service.AUTHOR_ROLE_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_AUTHOR_ROLE_NAME, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_AUTHOR_ROLE_NAME>(
|
||||
partial,
|
||||
AuthorRoleName,
|
||||
container.get(Service.AUTHOR_ROLE_NAME_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_CHARACTER_TAG, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_CHARACTER_TAG>(
|
||||
partial,
|
||||
CharacterTag,
|
||||
container.get(Service.CHARACTER_TAG_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_COLLECTION, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_COLLECTION>(partial, Collection, container.get(Service.COLLECTION_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_COLLECTION_NAME, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_COLLECTION_NAME>(
|
||||
partial,
|
||||
CollectionName,
|
||||
container.get(Service.COLLECTION_NAME_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_COLLECTION_PART, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_COLLECTION_PART>(
|
||||
partial,
|
||||
CollectionPart,
|
||||
container.get(Service.COLLECTION_PART_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_COPY, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_COPY>(partial, Copy, container.get(Service.COPY_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_INTERACTION_TAG, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_INTERACTION_TAG>(
|
||||
partial,
|
||||
InteractionTag,
|
||||
container.get(Service.INTERACTION_TAG_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_SITE, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_SITE>(partial, Site, container.get(Service.SITE_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_SITE_NAME, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_SITE_NAME>(partial, SiteName, container.get(Service.SITE_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_SOURCE, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_SOURCE>(partial, Source, container.get(Service.SOURCE_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_TAG, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_TAG>(partial, Tag, container.get(Service.TAG_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_TAG_NAME, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_TAG_NAME>(partial, TagName, container.get(Service.TAG_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_TRANSFORMATION, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_TRANSFORMATION>(
|
||||
partial,
|
||||
Transformation,
|
||||
container.get(Service.TRANSFORMATION_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_TRANSFORMATION_TYPE, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_TRANSFORMATION_TYPE>(
|
||||
partial,
|
||||
TransformationType,
|
||||
container.get(Service.TRANSFORMATION_TYPE_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_TRANSFORMATION_TYPE_NAME, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_TRANSFORMATION_TYPE_NAME>(
|
||||
partial,
|
||||
TransformationTypeName,
|
||||
container.get(Service.TRANSFORMATION_TYPE_NAME_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_WORK_AUTHOR, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_WORK_AUTHOR>(partial, WorkAuthor, container.get(Service.WORK_AUTHOR_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_WORK_CHARACTER, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_WORK_CHARACTER>(
|
||||
partial,
|
||||
WorkCharacter,
|
||||
container.get(Service.WORK_CHARACTER_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_WORK_CHARACTER_NAME, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_WORK_CHARACTER_NAME>(
|
||||
partial,
|
||||
WorkCharacterName,
|
||||
container.get(Service.WORK_CHARACTER_NAME_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_WORK, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_WORK>(partial, Work, container.get(Service.WORK_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_WORK_NAME, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_WORK_NAME>(partial, WorkName, container.get(Service.WORK_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_WORK_TAG, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_WORK_TAG>(partial, WorkTag, container.get(Service.WORK_TAG_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_WORLD, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_WORLD>(partial, World, container.get(Service.WORLD_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_WORLD_NAME, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_WORLD_NAME>(partial, WorldName, container.get(Service.WORLD_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_WORLD_CHARACTER, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_WORLD_CHARACTER>(
|
||||
partial,
|
||||
WorldCharacter,
|
||||
container.get(Service.WORLD_CHARACTER_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_CREATE_WORLD_CHARACTER_NAME, (partial) =>
|
||||
create<IpcChannel.ENTITY_CREATE_WORLD_CHARACTER_NAME>(
|
||||
partial,
|
||||
WorldCharacterName,
|
||||
container.get(Service.WORLD_CHARACTER_NAME_SERIALIZER),
|
||||
),
|
||||
);
|
|
@ -0,0 +1,92 @@
|
|||
import type { EntityTarget } from 'typeorm';
|
||||
import { getRepository } from '../../core/database';
|
||||
import { Author } from '../../entities/library/author';
|
||||
import { AuthorName } from '../../entities/library/author-name';
|
||||
import { AuthorRole } from '../../entities/library/author-role';
|
||||
import { AuthorRoleName } from '../../entities/library/author-role-name';
|
||||
import { CharacterTag } from '../../entities/library/character-tag';
|
||||
import { Collection } from '../../entities/library/collection';
|
||||
import { CollectionName } from '../../entities/library/collection-name';
|
||||
import { CollectionPart } from '../../entities/library/collection-part';
|
||||
import { Copy } from '../../entities/library/copy';
|
||||
import { InteractionTag } from '../../entities/library/interaction-tag';
|
||||
import { Site } from '../../entities/library/site';
|
||||
import { SiteName } from '../../entities/library/site-name';
|
||||
import { Source } from '../../entities/library/source';
|
||||
import { Tag } from '../../entities/library/tag';
|
||||
import { TagName } from '../../entities/library/tag-name';
|
||||
import { Transformation } from '../../entities/library/transformation';
|
||||
import { TransformationType } from '../../entities/library/transformation-type';
|
||||
import { TransformationTypeName } from '../../entities/library/transformation-type-name';
|
||||
import { Work } from '../../entities/library/work';
|
||||
import { WorkAuthor } from '../../entities/library/work-author';
|
||||
import { WorkCharacter } from '../../entities/library/work-character';
|
||||
import { WorkCharacterName } from '../../entities/library/work-character-name';
|
||||
import { WorkName } from '../../entities/library/work-name';
|
||||
import { WorkTag } from '../../entities/library/work-tag';
|
||||
import { World } from '../../entities/library/world';
|
||||
import { WorldCharacter } from '../../entities/library/world-character';
|
||||
import { WorldCharacterName } from '../../entities/library/world-character-name';
|
||||
import { WorldName } from '../../entities/library/world-name';
|
||||
import { ipcServer } from '../ipc/ipc-server';
|
||||
|
||||
async function del(id: number, entityTarget: EntityTarget<unknown>): Promise<void> {
|
||||
const repository = await getRepository(entityTarget);
|
||||
await repository.delete(id);
|
||||
}
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_AUTHOR, async (id) => del(id, Author));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_AUTHOR_NAME, async (id) => del(id, AuthorName));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_AUTHOR_ROLE, async (id) => del(id, AuthorRole));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_AUTHOR_ROLE_NAME, async (id) => del(id, AuthorRoleName));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_CHARACTER_TAG, async (id) => del(id, CharacterTag));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_COLLECTION, async (id) => del(id, Collection));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_COLLECTION_NAME, async (id) => del(id, CollectionName));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_COLLECTION_PART, async (id) => del(id, CollectionPart));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_COPY, async (id) => del(id, Copy));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_INTERACTION_TAG, async (id) => del(id, InteractionTag));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_SITE, async (id) => del(id, Site));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_SITE_NAME, async (id) => del(id, SiteName));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_SOURCE, async (id) => del(id, Source));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_TAG, async (id) => del(id, Tag));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_TAG_NAME, async (id) => del(id, TagName));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_TRANSFORMATION, async (id) => del(id, Transformation));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_TRANSFORMATION_TYPE, async (id) => del(id, TransformationType));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_TRANSFORMATION_TYPE_NAME, async (id) => del(id, TransformationTypeName));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_WORK_AUTHOR, async (id) => del(id, WorkAuthor));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_WORK_CHARACTER, async (id) => del(id, WorkCharacter));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_WORK_CHARACTER_NAME, async (id) => del(id, WorkCharacterName));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_WORK, async (id) => del(id, Work));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_WORK_NAME, async (id) => del(id, WorkName));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_WORK_TAG, async (id) => del(id, WorkTag));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_WORLD, async (id) => del(id, World));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_WORLD_NAME, async (id) => del(id, WorldName));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_WORLD_CHARACTER, async (id) => del(id, WorldCharacter));
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_DELETE_WORLD_CHARACTER_NAME, async (id) => del(id, WorldCharacterName));
|
|
@ -1,20 +1,4 @@
|
|||
import { workSerializer } from '../../../shared/services/serialization/serializers/work';
|
||||
import { Database, getConnection } from '../../core/database';
|
||||
import { Work } from '../../entities/library/work';
|
||||
import { answer } from '../ipc/annotations/answer';
|
||||
|
||||
export class EntityApiIpcController implements IpcController {
|
||||
private constructor() {}
|
||||
|
||||
@answer(IpcChannel.ENTITY_GET_WORK)
|
||||
public async getWork({ id }: { id: number }): Promise<WorkSerializedInterface> {
|
||||
const connection = await getConnection(Database.LIBRARY);
|
||||
const work = await connection.manager.getRepository(Work).findOneOrFail(id);
|
||||
|
||||
return workSerializer.serialize(work);
|
||||
}
|
||||
|
||||
public get(): EntityApiIpcController {
|
||||
return new EntityApiIpcController();
|
||||
}
|
||||
}
|
||||
import './create-controller';
|
||||
import './read-controller';
|
||||
import './update-controller';
|
||||
import './delete-controller';
|
||||
|
|
|
@ -0,0 +1,274 @@
|
|||
import type { EntityTarget } from 'typeorm';
|
||||
import { container, Service } from '../../core/container';
|
||||
import { getRepository } from '../../core/database';
|
||||
import { Author } from '../../entities/library/author';
|
||||
import { AuthorName } from '../../entities/library/author-name';
|
||||
import { AuthorRole } from '../../entities/library/author-role';
|
||||
import { AuthorRoleName } from '../../entities/library/author-role-name';
|
||||
import { CharacterTag } from '../../entities/library/character-tag';
|
||||
import { Collection } from '../../entities/library/collection';
|
||||
import { CollectionName } from '../../entities/library/collection-name';
|
||||
import { CollectionPart } from '../../entities/library/collection-part';
|
||||
import { Copy } from '../../entities/library/copy';
|
||||
import { InteractionTag } from '../../entities/library/interaction-tag';
|
||||
import { Language } from '../../entities/library/language';
|
||||
import { Site } from '../../entities/library/site';
|
||||
import { SiteName } from '../../entities/library/site-name';
|
||||
import { Source } from '../../entities/library/source';
|
||||
import { Tag } from '../../entities/library/tag';
|
||||
import { TagName } from '../../entities/library/tag-name';
|
||||
import { Transformation } from '../../entities/library/transformation';
|
||||
import { TransformationType } from '../../entities/library/transformation-type';
|
||||
import { TransformationTypeName } from '../../entities/library/transformation-type-name';
|
||||
import { Work } from '../../entities/library/work';
|
||||
import { WorkAuthor } from '../../entities/library/work-author';
|
||||
import { WorkCharacter } from '../../entities/library/work-character';
|
||||
import { WorkCharacterName } from '../../entities/library/work-character-name';
|
||||
import { WorkName } from '../../entities/library/work-name';
|
||||
import { WorkTag } from '../../entities/library/work-tag';
|
||||
import { World } from '../../entities/library/world';
|
||||
import { WorldCharacter } from '../../entities/library/world-character';
|
||||
import { WorldCharacterName } from '../../entities/library/world-character-name';
|
||||
import { WorldName } from '../../entities/library/world-name';
|
||||
import { ipcServer } from '../ipc/ipc-server';
|
||||
import type { Serializer } from '../serialization/serializer';
|
||||
|
||||
type ReadSerializedType = {
|
||||
[IpcChannel.ENTITY_READ_AUTHOR]: AuthorSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_AUTHOR_NAME]: AuthorNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_AUTHOR_ROLE]: AuthorRoleSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_AUTHOR_ROLE_NAME]: AuthorRoleNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_CHARACTER_TAG]: CharacterTagSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_COLLECTION]: CollectionSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_COLLECTION_NAME]: CollectionNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_COLLECTION_PART]: CollectionPartSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_COPY]: CopySerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_INTERACTION_TAG]: InteractionTagSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_LANGUAGE]: LanguageSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_SITE]: SiteSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_SITE_NAME]: SiteNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_SOURCE]: SourceSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_TAG]: TagSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_TAG_NAME]: TagNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_TRANSFORMATION]: TransformationSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE]: TransformationTypeSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE_NAME]: TransformationTypeNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_WORK_AUTHOR]: WorkAuthorSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_WORK_CHARACTER]: WorkCharacterSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_WORK_CHARACTER_NAME]: WorkCharacterNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_WORK]: WorkSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_WORK_NAME]: WorkNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_WORK_TAG]: WorkTagSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_WORLD]: WorldSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_WORLD_NAME]: WorldNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_WORLD_CHARACTER]: WorldCharacterSerializedInterface;
|
||||
[IpcChannel.ENTITY_READ_WORLD_CHARACTER_NAME]: WorldCharacterNameSerializedInterface;
|
||||
};
|
||||
|
||||
type ReadIdType = {
|
||||
[IpcChannel.ENTITY_READ_AUTHOR]: number;
|
||||
[IpcChannel.ENTITY_READ_AUTHOR_NAME]: number;
|
||||
[IpcChannel.ENTITY_READ_AUTHOR_ROLE]: number;
|
||||
[IpcChannel.ENTITY_READ_AUTHOR_ROLE_NAME]: number;
|
||||
[IpcChannel.ENTITY_READ_CHARACTER_TAG]: number;
|
||||
[IpcChannel.ENTITY_READ_COLLECTION]: number;
|
||||
[IpcChannel.ENTITY_READ_COLLECTION_NAME]: number;
|
||||
[IpcChannel.ENTITY_READ_COLLECTION_PART]: number;
|
||||
[IpcChannel.ENTITY_READ_COPY]: number;
|
||||
[IpcChannel.ENTITY_READ_INTERACTION_TAG]: number;
|
||||
[IpcChannel.ENTITY_READ_LANGUAGE]: string;
|
||||
[IpcChannel.ENTITY_READ_SITE]: number;
|
||||
[IpcChannel.ENTITY_READ_SITE_NAME]: number;
|
||||
[IpcChannel.ENTITY_READ_SOURCE]: number;
|
||||
[IpcChannel.ENTITY_READ_TAG]: number;
|
||||
[IpcChannel.ENTITY_READ_TAG_NAME]: number;
|
||||
[IpcChannel.ENTITY_READ_TRANSFORMATION]: number;
|
||||
[IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE]: number;
|
||||
[IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE_NAME]: number;
|
||||
[IpcChannel.ENTITY_READ_WORK_AUTHOR]: number;
|
||||
[IpcChannel.ENTITY_READ_WORK_CHARACTER]: number;
|
||||
[IpcChannel.ENTITY_READ_WORK_CHARACTER_NAME]: number;
|
||||
[IpcChannel.ENTITY_READ_WORK]: number;
|
||||
[IpcChannel.ENTITY_READ_WORK_NAME]: number;
|
||||
[IpcChannel.ENTITY_READ_WORK_TAG]: number;
|
||||
[IpcChannel.ENTITY_READ_WORLD]: number;
|
||||
[IpcChannel.ENTITY_READ_WORLD_NAME]: number;
|
||||
[IpcChannel.ENTITY_READ_WORLD_CHARACTER]: number;
|
||||
[IpcChannel.ENTITY_READ_WORLD_CHARACTER_NAME]: number;
|
||||
};
|
||||
|
||||
type ReadEntityType = {
|
||||
[IpcChannel.ENTITY_READ_AUTHOR]: Author;
|
||||
[IpcChannel.ENTITY_READ_AUTHOR_NAME]: AuthorName;
|
||||
[IpcChannel.ENTITY_READ_AUTHOR_ROLE]: AuthorRole;
|
||||
[IpcChannel.ENTITY_READ_AUTHOR_ROLE_NAME]: AuthorRoleName;
|
||||
[IpcChannel.ENTITY_READ_CHARACTER_TAG]: CharacterTag;
|
||||
[IpcChannel.ENTITY_READ_COLLECTION]: Collection;
|
||||
[IpcChannel.ENTITY_READ_COLLECTION_NAME]: CollectionName;
|
||||
[IpcChannel.ENTITY_READ_COLLECTION_PART]: CollectionPart;
|
||||
[IpcChannel.ENTITY_READ_COPY]: Copy;
|
||||
[IpcChannel.ENTITY_READ_INTERACTION_TAG]: InteractionTag;
|
||||
[IpcChannel.ENTITY_READ_LANGUAGE]: Language;
|
||||
[IpcChannel.ENTITY_READ_SITE]: Site;
|
||||
[IpcChannel.ENTITY_READ_SITE_NAME]: SiteName;
|
||||
[IpcChannel.ENTITY_READ_SOURCE]: Source;
|
||||
[IpcChannel.ENTITY_READ_TAG]: Tag;
|
||||
[IpcChannel.ENTITY_READ_TAG_NAME]: TagName;
|
||||
[IpcChannel.ENTITY_READ_TRANSFORMATION]: Transformation;
|
||||
[IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE]: TransformationType;
|
||||
[IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE_NAME]: TransformationTypeName;
|
||||
[IpcChannel.ENTITY_READ_WORK_AUTHOR]: WorkAuthor;
|
||||
[IpcChannel.ENTITY_READ_WORK_CHARACTER]: WorkCharacter;
|
||||
[IpcChannel.ENTITY_READ_WORK_CHARACTER_NAME]: WorkCharacterName;
|
||||
[IpcChannel.ENTITY_READ_WORK]: Work;
|
||||
[IpcChannel.ENTITY_READ_WORK_NAME]: WorkName;
|
||||
[IpcChannel.ENTITY_READ_WORK_TAG]: WorkTag;
|
||||
[IpcChannel.ENTITY_READ_WORLD]: World;
|
||||
[IpcChannel.ENTITY_READ_WORLD_NAME]: WorldName;
|
||||
[IpcChannel.ENTITY_READ_WORLD_CHARACTER]: WorldCharacter;
|
||||
[IpcChannel.ENTITY_READ_WORLD_CHARACTER_NAME]: WorldCharacterName;
|
||||
};
|
||||
|
||||
async function read<T extends keyof ReadSerializedType>(
|
||||
id: ReadIdType[T],
|
||||
entityTarget: EntityTarget<ReadEntityType[T]>,
|
||||
// @ts-ignore -- yeah, i don't get it
|
||||
serializer: Serializer<ReadEntityType[T], ReadSerializedType[T], ReadIdType[T]>,
|
||||
): Promise<ReadSerializedType[T]> {
|
||||
const repository = await getRepository(entityTarget);
|
||||
const entity = await repository.findOneOrFail(id);
|
||||
|
||||
return serializer.serialize(entity);
|
||||
}
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_AUTHOR, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_AUTHOR>(id, Author, container.get(Service.AUTHOR_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_AUTHOR_NAME, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_AUTHOR_NAME>(id, AuthorName, container.get(Service.AUTHOR_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_AUTHOR_ROLE, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_AUTHOR_ROLE>(id, AuthorRole, container.get(Service.AUTHOR_ROLE_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_AUTHOR_ROLE_NAME, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_AUTHOR_ROLE_NAME>(id, AuthorRoleName, container.get(Service.AUTHOR_ROLE_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_CHARACTER_TAG, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_CHARACTER_TAG>(id, CharacterTag, container.get(Service.CHARACTER_TAG_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_COLLECTION, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_COLLECTION>(id, Collection, container.get(Service.COLLECTION_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_COLLECTION_NAME, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_COLLECTION_NAME>(id, CollectionName, container.get(Service.COLLECTION_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_COLLECTION_PART, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_COLLECTION_PART>(id, CollectionPart, container.get(Service.COLLECTION_PART_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_COPY, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_COPY>(id, Copy, container.get(Service.COPY_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_INTERACTION_TAG, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_INTERACTION_TAG>(id, InteractionTag, container.get(Service.INTERACTION_TAG_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_LANGUAGE, (code) =>
|
||||
read<IpcChannel.ENTITY_READ_LANGUAGE>(code, Language, container.get(Service.LANGUAGE_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_SITE, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_SITE>(id, Site, container.get(Service.SITE_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_SITE_NAME, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_SITE_NAME>(id, SiteName, container.get(Service.SITE_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_SOURCE, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_SOURCE>(id, Source, container.get(Service.SOURCE_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_TAG, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_TAG>(id, Tag, container.get(Service.TAG_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_TAG_NAME, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_TAG_NAME>(id, TagName, container.get(Service.TAG_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_TRANSFORMATION, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_TRANSFORMATION>(id, Transformation, container.get(Service.TRANSFORMATION_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE>(
|
||||
id,
|
||||
TransformationType,
|
||||
container.get(Service.TRANSFORMATION_TYPE_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE_NAME, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE_NAME>(
|
||||
id,
|
||||
TransformationTypeName,
|
||||
container.get(Service.TRANSFORMATION_TYPE_NAME_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_WORK_AUTHOR, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_WORK_AUTHOR>(id, WorkAuthor, container.get(Service.WORK_AUTHOR_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_WORK_CHARACTER, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_WORK_CHARACTER>(id, WorkCharacter, container.get(Service.WORK_CHARACTER_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_WORK_CHARACTER_NAME, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_WORK_CHARACTER_NAME>(
|
||||
id,
|
||||
WorkCharacterName,
|
||||
container.get(Service.WORK_CHARACTER_NAME_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_WORK, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_WORK>(id, Work, container.get(Service.WORK_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_WORK_NAME, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_WORK_NAME>(id, WorkName, container.get(Service.WORK_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_WORK_TAG, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_WORK_TAG>(id, WorkTag, container.get(Service.WORK_TAG_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_WORLD, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_WORLD>(id, World, container.get(Service.WORLD_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_WORLD_NAME, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_WORLD_NAME>(id, WorldName, container.get(Service.WORLD_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_WORLD_CHARACTER, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_WORLD_CHARACTER>(id, WorldCharacter, container.get(Service.WORLD_CHARACTER_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_READ_WORLD_CHARACTER_NAME, (id) =>
|
||||
read<IpcChannel.ENTITY_READ_WORLD_CHARACTER_NAME>(
|
||||
id,
|
||||
WorldCharacterName,
|
||||
container.get(Service.WORLD_CHARACTER_NAME_SERIALIZER),
|
||||
),
|
||||
);
|
|
@ -0,0 +1,281 @@
|
|||
import type { EntityTarget } from 'typeorm';
|
||||
import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity';
|
||||
import { container, Service } from '../../core/container';
|
||||
import { getRepository } from '../../core/database';
|
||||
import { Author } from '../../entities/library/author';
|
||||
import { AuthorName } from '../../entities/library/author-name';
|
||||
import { AuthorRole } from '../../entities/library/author-role';
|
||||
import { AuthorRoleName } from '../../entities/library/author-role-name';
|
||||
import { CharacterTag } from '../../entities/library/character-tag';
|
||||
import { Collection } from '../../entities/library/collection';
|
||||
import { CollectionName } from '../../entities/library/collection-name';
|
||||
import { CollectionPart } from '../../entities/library/collection-part';
|
||||
import { Copy } from '../../entities/library/copy';
|
||||
import { InteractionTag } from '../../entities/library/interaction-tag';
|
||||
import { Site } from '../../entities/library/site';
|
||||
import { SiteName } from '../../entities/library/site-name';
|
||||
import { Source } from '../../entities/library/source';
|
||||
import { Tag } from '../../entities/library/tag';
|
||||
import { TagName } from '../../entities/library/tag-name';
|
||||
import { Transformation } from '../../entities/library/transformation';
|
||||
import { TransformationType } from '../../entities/library/transformation-type';
|
||||
import { TransformationTypeName } from '../../entities/library/transformation-type-name';
|
||||
import { Work } from '../../entities/library/work';
|
||||
import { WorkAuthor } from '../../entities/library/work-author';
|
||||
import { WorkCharacter } from '../../entities/library/work-character';
|
||||
import { WorkCharacterName } from '../../entities/library/work-character-name';
|
||||
import { WorkName } from '../../entities/library/work-name';
|
||||
import { WorkTag } from '../../entities/library/work-tag';
|
||||
import { World } from '../../entities/library/world';
|
||||
import { WorldCharacter } from '../../entities/library/world-character';
|
||||
import { WorldCharacterName } from '../../entities/library/world-character-name';
|
||||
import { WorldName } from '../../entities/library/world-name';
|
||||
import { ipcServer } from '../ipc/ipc-server';
|
||||
import type { Serializer } from '../serialization/serializer';
|
||||
|
||||
type UpdateSerializedType = {
|
||||
[IpcChannel.ENTITY_UPDATE_AUTHOR]: AuthorSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_AUTHOR_NAME]: AuthorNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_AUTHOR_ROLE]: AuthorRoleSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_AUTHOR_ROLE_NAME]: AuthorRoleNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_CHARACTER_TAG]: CharacterTagSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_COLLECTION]: CollectionSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_COLLECTION_NAME]: CollectionNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_COLLECTION_PART]: CollectionPartSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_COPY]: CopySerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_INTERACTION_TAG]: InteractionTagSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_SITE]: SiteSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_SITE_NAME]: SiteNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_SOURCE]: SourceSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_TAG]: TagSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_TAG_NAME]: TagNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_TRANSFORMATION]: TransformationSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_TRANSFORMATION_TYPE]: TransformationTypeSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_TRANSFORMATION_TYPE_NAME]: TransformationTypeNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_WORK_AUTHOR]: WorkAuthorSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_WORK_CHARACTER]: WorkCharacterSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_WORK_CHARACTER_NAME]: WorkCharacterNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_WORK]: WorkSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_WORK_NAME]: WorkNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_WORK_TAG]: WorkTagSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_WORLD]: WorldSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_WORLD_NAME]: WorldNameSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_WORLD_CHARACTER]: WorldCharacterSerializedInterface;
|
||||
[IpcChannel.ENTITY_UPDATE_WORLD_CHARACTER_NAME]: WorldCharacterNameSerializedInterface;
|
||||
};
|
||||
|
||||
type UpdateEntityType = {
|
||||
[IpcChannel.ENTITY_UPDATE_AUTHOR]: Author;
|
||||
[IpcChannel.ENTITY_UPDATE_AUTHOR_NAME]: AuthorName;
|
||||
[IpcChannel.ENTITY_UPDATE_AUTHOR_ROLE]: AuthorRole;
|
||||
[IpcChannel.ENTITY_UPDATE_AUTHOR_ROLE_NAME]: AuthorRoleName;
|
||||
[IpcChannel.ENTITY_UPDATE_CHARACTER_TAG]: CharacterTag;
|
||||
[IpcChannel.ENTITY_UPDATE_COLLECTION]: Collection;
|
||||
[IpcChannel.ENTITY_UPDATE_COLLECTION_NAME]: CollectionName;
|
||||
[IpcChannel.ENTITY_UPDATE_COLLECTION_PART]: CollectionPart;
|
||||
[IpcChannel.ENTITY_UPDATE_COPY]: Copy;
|
||||
[IpcChannel.ENTITY_UPDATE_INTERACTION_TAG]: InteractionTag;
|
||||
[IpcChannel.ENTITY_UPDATE_SITE]: Site;
|
||||
[IpcChannel.ENTITY_UPDATE_SITE_NAME]: SiteName;
|
||||
[IpcChannel.ENTITY_UPDATE_SOURCE]: Source;
|
||||
[IpcChannel.ENTITY_UPDATE_TAG]: Tag;
|
||||
[IpcChannel.ENTITY_UPDATE_TAG_NAME]: TagName;
|
||||
[IpcChannel.ENTITY_UPDATE_TRANSFORMATION]: Transformation;
|
||||
[IpcChannel.ENTITY_UPDATE_TRANSFORMATION_TYPE]: TransformationType;
|
||||
[IpcChannel.ENTITY_UPDATE_TRANSFORMATION_TYPE_NAME]: TransformationTypeName;
|
||||
[IpcChannel.ENTITY_UPDATE_WORK_AUTHOR]: WorkAuthor;
|
||||
[IpcChannel.ENTITY_UPDATE_WORK_CHARACTER]: WorkCharacter;
|
||||
[IpcChannel.ENTITY_UPDATE_WORK_CHARACTER_NAME]: WorkCharacterName;
|
||||
[IpcChannel.ENTITY_UPDATE_WORK]: Work;
|
||||
[IpcChannel.ENTITY_UPDATE_WORK_NAME]: WorkName;
|
||||
[IpcChannel.ENTITY_UPDATE_WORK_TAG]: WorkTag;
|
||||
[IpcChannel.ENTITY_UPDATE_WORLD]: World;
|
||||
[IpcChannel.ENTITY_UPDATE_WORLD_NAME]: WorldName;
|
||||
[IpcChannel.ENTITY_UPDATE_WORLD_CHARACTER]: WorldCharacter;
|
||||
[IpcChannel.ENTITY_UPDATE_WORLD_CHARACTER_NAME]: WorldCharacterName;
|
||||
};
|
||||
|
||||
async function update<T extends keyof UpdateSerializedType>(
|
||||
id: number,
|
||||
partial: Partial<UpdateSerializedType[T]>,
|
||||
entityTarget: EntityTarget<UpdateEntityType[T]>,
|
||||
serializer: Serializer<UpdateEntityType[T], UpdateSerializedType[T]>,
|
||||
): Promise<UpdateSerializedType[T]> {
|
||||
const repository = await getRepository(entityTarget);
|
||||
await repository.update(id, serializer.deserialize(partial) as QueryDeepPartialEntity<UpdateEntityType[T]>);
|
||||
const entity = await repository.findOneOrFail(id);
|
||||
|
||||
return serializer.serialize(entity);
|
||||
}
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_AUTHOR, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_AUTHOR>(id, partial, Author, container.get(Service.AUTHOR_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_AUTHOR_NAME, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_AUTHOR_NAME>(id, partial, AuthorName, container.get(Service.AUTHOR_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_AUTHOR_ROLE, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_AUTHOR_ROLE>(id, partial, AuthorRole, container.get(Service.AUTHOR_ROLE_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_AUTHOR_ROLE_NAME, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_AUTHOR_ROLE_NAME>(
|
||||
id,
|
||||
partial,
|
||||
AuthorRoleName,
|
||||
container.get(Service.AUTHOR_ROLE_NAME_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_CHARACTER_TAG, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_CHARACTER_TAG>(
|
||||
id,
|
||||
partial,
|
||||
CharacterTag,
|
||||
container.get(Service.CHARACTER_TAG_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_COLLECTION, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_COLLECTION>(id, partial, Collection, container.get(Service.COLLECTION_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_COLLECTION_NAME, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_COLLECTION_NAME>(
|
||||
id,
|
||||
partial,
|
||||
CollectionName,
|
||||
container.get(Service.COLLECTION_NAME_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_COLLECTION_PART, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_COLLECTION_PART>(
|
||||
id,
|
||||
partial,
|
||||
CollectionPart,
|
||||
container.get(Service.COLLECTION_PART_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_COPY, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_COPY>(id, partial, Copy, container.get(Service.COPY_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_INTERACTION_TAG, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_INTERACTION_TAG>(
|
||||
id,
|
||||
partial,
|
||||
InteractionTag,
|
||||
container.get(Service.INTERACTION_TAG_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_SITE, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_SITE>(id, partial, Site, container.get(Service.SITE_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_SITE_NAME, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_SITE_NAME>(id, partial, SiteName, container.get(Service.SITE_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_SOURCE, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_SOURCE>(id, partial, Source, container.get(Service.SOURCE_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_TAG, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_TAG>(id, partial, Tag, container.get(Service.TAG_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_TAG_NAME, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_TAG_NAME>(id, partial, TagName, container.get(Service.TAG_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_TRANSFORMATION, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_TRANSFORMATION>(
|
||||
id,
|
||||
partial,
|
||||
Transformation,
|
||||
container.get(Service.TRANSFORMATION_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_TRANSFORMATION_TYPE, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_TRANSFORMATION_TYPE>(
|
||||
id,
|
||||
partial,
|
||||
TransformationType,
|
||||
container.get(Service.TRANSFORMATION_TYPE_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_TRANSFORMATION_TYPE_NAME, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_TRANSFORMATION_TYPE_NAME>(
|
||||
id,
|
||||
partial,
|
||||
TransformationTypeName,
|
||||
container.get(Service.TRANSFORMATION_TYPE_NAME_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_WORK_AUTHOR, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_WORK_AUTHOR>(id, partial, WorkAuthor, container.get(Service.WORK_AUTHOR_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_WORK_CHARACTER, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_WORK_CHARACTER>(
|
||||
id,
|
||||
partial,
|
||||
WorkCharacter,
|
||||
container.get(Service.WORK_CHARACTER_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_WORK_CHARACTER_NAME, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_WORK_CHARACTER_NAME>(
|
||||
id,
|
||||
partial,
|
||||
WorkCharacterName,
|
||||
container.get(Service.WORK_CHARACTER_NAME_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_WORK, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_WORK>(id, partial, Work, container.get(Service.WORK_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_WORK_NAME, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_WORK_NAME>(id, partial, WorkName, container.get(Service.WORK_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_WORK_TAG, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_WORK_TAG>(id, partial, WorkTag, container.get(Service.WORK_TAG_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_WORLD, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_WORLD>(id, partial, World, container.get(Service.WORLD_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_WORLD_NAME, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_WORLD_NAME>(id, partial, WorldName, container.get(Service.WORLD_NAME_SERIALIZER)),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_WORLD_CHARACTER, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_WORLD_CHARACTER>(
|
||||
id,
|
||||
partial,
|
||||
WorldCharacter,
|
||||
container.get(Service.WORLD_CHARACTER_SERIALIZER),
|
||||
),
|
||||
);
|
||||
|
||||
ipcServer.answer(IpcChannel.ENTITY_UPDATE_WORLD_CHARACTER_NAME, async ({ id, partial }) =>
|
||||
update<IpcChannel.ENTITY_UPDATE_WORLD_CHARACTER_NAME>(
|
||||
id,
|
||||
partial,
|
||||
WorldCharacterName,
|
||||
container.get(Service.WORLD_CHARACTER_NAME_SERIALIZER),
|
||||
),
|
||||
);
|
|
@ -1,3 +0,0 @@
|
|||
interface I18nTranslatorInterface {
|
||||
t(text: string): string;
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
import { injectable } from 'inversify';
|
||||
|
||||
@injectable()
|
||||
export class I18nTranslator implements I18nTranslatorInterface {
|
||||
public t(text: string): string {
|
||||
return text;
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
import { registerHandler } from '../ipc-server';
|
||||
|
||||
export function answer(channel: IpcChannel): IpcControllerMethodDecorator {
|
||||
return function (target: IpcController, propertyKey): void {
|
||||
registerHandler(channel, target, propertyKey);
|
||||
};
|
||||
}
|
|
@ -1,25 +1,16 @@
|
|||
import { ipcMain } from 'electron';
|
||||
import IpcMainEvent = Electron.IpcMainEvent;
|
||||
import { ipcMain, IpcMainInvokeEvent } from 'electron';
|
||||
import { container, Service } from '../../core/container';
|
||||
|
||||
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: IpcResponse = {
|
||||
id: payload.id,
|
||||
success: true,
|
||||
data: result,
|
||||
};
|
||||
event.reply(channel, response);
|
||||
})
|
||||
.catch((reason: Error) => {
|
||||
const response: IpcResponse = {
|
||||
id: payload.id,
|
||||
success: false,
|
||||
error: reason.message,
|
||||
};
|
||||
event.reply(channel, response);
|
||||
const logger = container.get(Service.LOGGER);
|
||||
|
||||
export const ipcServer: IpcServer = {
|
||||
answer<T extends IpcChannel>(channel: T, answerer: IpcHandler<IpcParameter<T>, IpcAnswer<T>>) {
|
||||
const listener = (data: IpcParameter<T>): Promise<IpcAnswer<T>> =>
|
||||
answerer(data).catch((reason: Error) => {
|
||||
void logger.exception(reason);
|
||||
throw reason;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ipcMain.handle(channel, (event: IpcMainInvokeEvent, data: IpcParameter<T>) => listener(data));
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { createInterface, Interface } from 'readline';
|
||||
import chai, { expect } from 'chai';
|
||||
import 'mocha';
|
||||
import chaiFs from 'chai-fs';
|
||||
import fc from 'fast-check';
|
||||
import fs from 'fs-extra';
|
||||
import { container } from '../../core/container';
|
||||
import 'mocha';
|
||||
import { container, Service } from '../../core/container';
|
||||
import { setDev } from '../../core/env.spec';
|
||||
import { LogLevel } from './log-level';
|
||||
|
||||
|
@ -41,20 +41,20 @@ describe('Logger Service', () => {
|
|||
const logLevelNumberArbitrary = fc.constantFrom(...logLevelsNumber);
|
||||
|
||||
it('creates log files', () => {
|
||||
const logger: LoggerInterface = container.get('logger');
|
||||
const logger = container.get(Service.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: LoggerInterface = container.get('logger');
|
||||
const logger = container.get(Service.LOGGER);
|
||||
|
||||
await logger.exception(new Error('this is an error'));
|
||||
});
|
||||
|
||||
it("default log file doesn't get bigger than 50KB @slow", async () => {
|
||||
const logger: LoggerInterface = container.get('logger');
|
||||
const logger = container.get(Service.LOGGER);
|
||||
|
||||
let prevLogFileSize = (await fs.stat(logger.getLogFile())).size;
|
||||
let minNumberOfLines = maxLogSize;
|
||||
|
@ -75,7 +75,7 @@ describe('Logger Service', () => {
|
|||
}).timeout(15000);
|
||||
|
||||
it("exception log file doesn't get bigger than 50KB @slow", async () => {
|
||||
const logger: LoggerInterface = container.get('logger');
|
||||
const logger = container.get(Service.LOGGER);
|
||||
|
||||
let prevLogFileSize = (await fs.stat(logger.getExceptionsLogFile())).size;
|
||||
let minNumberOfLines = maxLogSize;
|
||||
|
@ -96,7 +96,7 @@ describe('Logger Service', () => {
|
|||
}).timeout(15000);
|
||||
|
||||
it('logs different levels directly', () => {
|
||||
const logger: LoggerInterface = container.get('logger');
|
||||
const logger = container.get(Service.LOGGER);
|
||||
|
||||
return fc.assert(
|
||||
fc.asyncProperty(logLevelArbitrary as LogLevelArbitrary, fc.string(), async (logLevel, message) => {
|
||||
|
@ -107,12 +107,12 @@ describe('Logger Service', () => {
|
|||
}),
|
||||
{
|
||||
numRuns: 50,
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('logs different levels indirectly via the generic log function', () => {
|
||||
const logger: LoggerInterface = container.get('logger');
|
||||
const logger = container.get(Service.LOGGER);
|
||||
|
||||
return fc.assert(
|
||||
fc.asyncProperty(logLevelNumberArbitrary, fc.string(), async (logLevelNumber, message) => {
|
||||
|
@ -121,17 +121,17 @@ describe('Logger Service', () => {
|
|||
expect(lastLine).contains(message, 'the log line does not contain the message');
|
||||
expect(lastLine).contains(
|
||||
logLevels[logLevelNumber],
|
||||
`the log line does not contain the '${logLevels[logLevelNumber]}' keyword`
|
||||
`the log line does not contain the '${logLevels[logLevelNumber]}' keyword`,
|
||||
);
|
||||
}),
|
||||
{
|
||||
numRuns: 50,
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it('logs debug only in dev mode', async () => {
|
||||
const logger: LoggerInterface = container.get('logger');
|
||||
const logger = container.get(Service.LOGGER);
|
||||
|
||||
setDev();
|
||||
await logger.debug('this is a development message');
|
||||
|
@ -143,7 +143,7 @@ describe('Logger Service', () => {
|
|||
await logger.debug('this is a second development message, should not be here');
|
||||
expect(lastLine).not.contain(
|
||||
'this is a second development message, should not be here',
|
||||
'debug is logged even in non-dev mode'
|
||||
'debug is logged even in non-dev mode',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -64,9 +64,9 @@ export class Logger implements LoggerInterface {
|
|||
return Logger.writeStream(
|
||||
Readable.from(
|
||||
`[${new Date().toISOString()}] ${(error as NodeJS.ErrnoException).code ?? 'Error'}: ${error.message}
|
||||
${error.stack ?? 'no stack trace'}\n`
|
||||
${error.stack ?? 'no stack trace'}\n`,
|
||||
),
|
||||
exceptionLogFile
|
||||
exceptionLogFile,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,21 +29,18 @@ describe('Simple Mutex', () => {
|
|||
const acquireOne = mutex.acquire();
|
||||
const acquireTwo = mutex.acquire();
|
||||
const acquireThree = mutex.acquire();
|
||||
void acquireOne.then((release) =>
|
||||
useResource().then(() => {
|
||||
release();
|
||||
})
|
||||
);
|
||||
void acquireTwo.then((release) =>
|
||||
useResource().then(() => {
|
||||
release();
|
||||
})
|
||||
);
|
||||
return acquireThree.then((release) =>
|
||||
useResource().then(() => {
|
||||
release();
|
||||
})
|
||||
);
|
||||
void acquireOne.then(async (release) => {
|
||||
await useResource();
|
||||
release();
|
||||
});
|
||||
void acquireTwo.then(async (release) => {
|
||||
await useResource();
|
||||
release();
|
||||
});
|
||||
return acquireThree.then(async (release) => {
|
||||
await useResource();
|
||||
release();
|
||||
});
|
||||
});
|
||||
|
||||
it('executes consumers in the right order', async () => {
|
||||
|
@ -60,21 +57,18 @@ describe('Simple Mutex', () => {
|
|||
const acquireOne = mutex.acquire();
|
||||
const acquireTwo = mutex.acquire();
|
||||
const acquireThree = mutex.acquire();
|
||||
void acquireOne.then((release) =>
|
||||
useResource(1).then(() => {
|
||||
release();
|
||||
})
|
||||
);
|
||||
void acquireTwo.then((release) =>
|
||||
useResource(2).then(() => {
|
||||
release();
|
||||
})
|
||||
);
|
||||
return acquireThree.then((release) =>
|
||||
useResource(3).then(() => {
|
||||
release();
|
||||
})
|
||||
);
|
||||
void acquireOne.then(async (release) => {
|
||||
await useResource(1);
|
||||
release();
|
||||
});
|
||||
void acquireTwo.then(async (release) => {
|
||||
await useResource(2);
|
||||
release();
|
||||
});
|
||||
return acquireThree.then(async (release) => {
|
||||
await useResource(3);
|
||||
release();
|
||||
});
|
||||
});
|
||||
|
||||
it('correctly informs if it is currently locked', async () => {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Service } from '../../core/container';
|
||||
import { inject } from '../../core/inject';
|
||||
import type { NhentaiAppWindowInterface } from './nhentai-app-window-interface';
|
||||
|
||||
|
@ -6,7 +7,7 @@ import type { NhentaiAppWindowInterface } from './nhentai-app-window-interface';
|
|||
export class NhentaiApi implements NhentaiApiInterface {
|
||||
private readonly appWindow: NhentaiAppWindowInterface;
|
||||
|
||||
public constructor(@inject('nhentai-app-window') appWindow: NhentaiAppWindowInterface) {
|
||||
public constructor(@inject(Service.NHENTAI_APP_WINDOW) appWindow: NhentaiAppWindowInterface) {
|
||||
this.appWindow = appWindow;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,27 +1,26 @@
|
|||
import chai, { expect } from 'chai';
|
||||
import deepEqualInAnyOrder from 'deep-equal-in-any-order';
|
||||
import { describe, it, before } from 'mocha';
|
||||
import { container } from '../../core/container';
|
||||
import { before, describe, it } from 'mocha';
|
||||
import { container, Service } from '../../core/container';
|
||||
import { LoggerMock } from '../logger/logger.mock';
|
||||
import type { NhentaiAppWindowInterface } from './nhentai-app-window-interface';
|
||||
|
||||
chai.use(deepEqualInAnyOrder);
|
||||
|
||||
describe('Nhentai App Window', () => {
|
||||
before(() => {
|
||||
container.unbind('logger');
|
||||
container.bind('logger').to(LoggerMock);
|
||||
container.unbind(Service.LOGGER);
|
||||
container.bind(Service.LOGGER).to(LoggerMock);
|
||||
});
|
||||
|
||||
it('gets the gallery information from an identifier @slow', async () => {
|
||||
const nhentaiAppWindow: NhentaiAppWindowInterface = container.get('nhentai-app-window');
|
||||
const nhentaiAppWindow = container.get(Service.NHENTAI_APP_WINDOW);
|
||||
|
||||
let expectedGallery: Nhentai.Gallery = {
|
||||
url: 'https://nhentai.net/g/117300/',
|
||||
url: 'https://nhentai.net/g/107386/',
|
||||
title: {
|
||||
pre: '[Homunculus]',
|
||||
main: 'Renai Sample',
|
||||
post: '[English] [Decensored]',
|
||||
main: 'Renai Sample + Bonus Booklets',
|
||||
post: '[English] [Tankoubon version]',
|
||||
},
|
||||
artists: ['homunculus'],
|
||||
groups: [],
|
||||
|
@ -32,22 +31,27 @@ describe('Nhentai App Window', () => {
|
|||
'stockings',
|
||||
'schoolgirl uniform',
|
||||
'glasses',
|
||||
'nakadashi',
|
||||
'incest',
|
||||
'tankoubon',
|
||||
'defloration',
|
||||
'milf',
|
||||
'swimsuit',
|
||||
'ffm threesome',
|
||||
'impregnation',
|
||||
'sister',
|
||||
'schoolboy uniform',
|
||||
'bikini',
|
||||
'uncensored',
|
||||
'small breasts',
|
||||
'teacher',
|
||||
'apron',
|
||||
'inseki',
|
||||
'leg lock',
|
||||
'cousin',
|
||||
'niece',
|
||||
],
|
||||
languages: ['english', 'translated'],
|
||||
uploadTime: 1411853968970,
|
||||
uploadTime: 1404001890940,
|
||||
};
|
||||
let gallery = await nhentaiAppWindow.getGallery('117300');
|
||||
let gallery = await nhentaiAppWindow.getGallery('107386');
|
||||
expect(gallery).deep.equalInAnyOrder(expectedGallery, 'Renai Sample is not got correctly');
|
||||
|
||||
expectedGallery = {
|
||||
|
|
|
@ -5,37 +5,38 @@ import { Readable } from 'stream';
|
|||
import { URL } from 'url';
|
||||
import { createReadStream, remove } from 'fs-extra';
|
||||
import { injectable } from 'inversify';
|
||||
import { Service } from '../../core/container';
|
||||
import { inject } from '../../core/inject';
|
||||
import { CloudflareSiteAppWindow } from '../cloudflare/cloudflare-site-app-window';
|
||||
import { mergeContentSecurityPolicy } from '../session/session-util';
|
||||
import type { NhentaiAppWindowInterface } from './nhentai-app-window-interface';
|
||||
import {
|
||||
url as nhentaiUrl,
|
||||
hostname as nhentaiHostname,
|
||||
paths as nhentaiPaths,
|
||||
getFavoritePageUrl,
|
||||
nextFavoritePageSelector,
|
||||
coverLinkSelector,
|
||||
downloadLinkId,
|
||||
getGalleryId,
|
||||
favoritePageIsReady,
|
||||
galleryPageIsReady,
|
||||
getBookUrl,
|
||||
getFavoritePageUrl,
|
||||
getGalleryId,
|
||||
hostname as nhentaiHostname,
|
||||
labeledTagContainerSelector,
|
||||
loginPageIsReady,
|
||||
mainTitleSelector,
|
||||
nextFavoritePageSelector,
|
||||
pageIsReady,
|
||||
paths as nhentaiPaths,
|
||||
postTitleSelector,
|
||||
preTitleSelector,
|
||||
tagLabelArtists,
|
||||
labeledTagContainerSelector,
|
||||
tagLabelCharacters,
|
||||
tagLabelGroups,
|
||||
tagLabelLanguages,
|
||||
tagLabelParodies,
|
||||
tagLabelTags,
|
||||
tagNameSelector,
|
||||
tagSelector,
|
||||
tagLabelGroups,
|
||||
tagLabelParodies,
|
||||
tagLabelCharacters,
|
||||
tagLabelTags,
|
||||
mainTitleSelector,
|
||||
postTitleSelector,
|
||||
galleryPageIsReady,
|
||||
loginPageIsReady,
|
||||
favoritePageIsReady,
|
||||
pageIsReady,
|
||||
timeSelector,
|
||||
tagLabelLanguages,
|
||||
url as nhentaiUrl,
|
||||
} from './nhentai-util';
|
||||
|
||||
const waitInterval = 2000;
|
||||
|
@ -44,7 +45,7 @@ const waitInterval = 2000;
|
|||
export class NhentaiAppWindow extends CloudflareSiteAppWindow implements NhentaiAppWindowInterface {
|
||||
protected readyCheck = pageIsReady;
|
||||
|
||||
public constructor(@inject('logger') logger: LoggerInterface) {
|
||||
public constructor(@inject(Service.LOGGER) logger: LoggerInterface) {
|
||||
super(logger, nhentaiUrl);
|
||||
}
|
||||
|
||||
|
@ -64,8 +65,8 @@ export class NhentaiAppWindow extends CloudflareSiteAppWindow implements Nhentai
|
|||
for await (const wc of this.getFavoritePageWebContentsGenerator()) {
|
||||
bookUrls.push(
|
||||
...((await wc.executeJavaScript(
|
||||
`Array.from(document.querySelectorAll('${coverLinkSelector}')).map((el) => el.href)`
|
||||
)) as string[])
|
||||
`Array.from(document.querySelectorAll('${coverLinkSelector}')).map((el) => el.href)`,
|
||||
)) as string[]),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -80,7 +81,7 @@ export class NhentaiAppWindow extends CloudflareSiteAppWindow implements Nhentai
|
|||
})(this),
|
||||
{
|
||||
objectMode: true,
|
||||
}
|
||||
},
|
||||
);
|
||||
readable.once('end', () => {
|
||||
this.close();
|
||||
|
@ -198,7 +199,7 @@ export class NhentaiAppWindow extends CloudflareSiteAppWindow implements Nhentai
|
|||
.webContents.executeJavaScript(
|
||||
`fetch('${
|
||||
nhentaiUrl + nhentaiPaths.favorites
|
||||
}', {credentials: 'include', redirect: 'manual'}).then((res) => res.status)`
|
||||
}', {credentials: 'include', redirect: 'manual'}).then((res) => res.status)`,
|
||||
)
|
||||
.then((status: number) => status === HttpCode.OK);
|
||||
}
|
||||
|
@ -225,11 +226,11 @@ export class NhentaiAppWindow extends CloudflareSiteAppWindow implements Nhentai
|
|||
while (true) {
|
||||
yield this.getWindow().webContents;
|
||||
const hasNextPage = (await this.getWindow().webContents.executeJavaScript(
|
||||
`!!document.querySelector('${nextFavoritePageSelector}')`
|
||||
`!!document.querySelector('${nextFavoritePageSelector}')`,
|
||||
)) as boolean;
|
||||
if (hasNextPage) {
|
||||
const nextPageHref = (await this.getWindow().webContents.executeJavaScript(
|
||||
`document.querySelector('${nextFavoritePageSelector}').href`
|
||||
`document.querySelector('${nextFavoritePageSelector}').href`,
|
||||
)) as string;
|
||||
await this.loadFavoritesPageSafe(nextPageHref);
|
||||
} else {
|
||||
|
@ -245,7 +246,7 @@ export class NhentaiAppWindow extends CloudflareSiteAppWindow implements Nhentai
|
|||
const filePath = path.resolve(os.tmpdir(), fileName);
|
||||
await this.loadGalleryPageSafe(bookUrl);
|
||||
const downloadLink: string = (await this.getWindow().webContents.executeJavaScript(
|
||||
`document.getElementById('${downloadLinkId}').href`
|
||||
`document.getElementById('${downloadLinkId}').href`,
|
||||
)) as string;
|
||||
await this.downloadUrlSafe(downloadLink, filePath);
|
||||
|
||||
|
@ -283,7 +284,7 @@ export class NhentaiAppWindow extends CloudflareSiteAppWindow implements Nhentai
|
|||
(tagContainer) => Array.from(tagContainer.querySelectorAll('${tagSelector}'))
|
||||
).flat().map(
|
||||
(tagElement) => tagElement.querySelector('${tagNameSelector}').innerHTML
|
||||
)`
|
||||
)`,
|
||||
) as Promise<string[]>;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,65 +1,40 @@
|
|||
import path from 'path';
|
||||
import { createWriteStream } from 'fs-extra';
|
||||
import { container } from '../../core/container';
|
||||
import type { DialogInterface } from '../dialog/dialog-interface';
|
||||
import { answer } from '../ipc/annotations/answer';
|
||||
import type { SourceGetterInterface } from '../source/source-getter-interface';
|
||||
import { t } from '../../../shared/services/translation/t';
|
||||
import { container, Service } from '../../core/container';
|
||||
import { ipcServer } from '../ipc/ipc-server';
|
||||
|
||||
export class NhentaiIpcController implements IpcController {
|
||||
private readonly nhentaiApi: NhentaiApiInterface;
|
||||
ipcServer.answer(IpcChannel.NHENTAI_SAVE_FAVORITES, async (): Promise<void> => {
|
||||
const nhentaiApi = container.get(Service.NHENTAI_API);
|
||||
const dialog = container.get(Service.DIALOG);
|
||||
|
||||
private readonly nhentaiSourceGetter: SourceGetterInterface;
|
||||
const result = await dialog.selectFolder({
|
||||
title: t('imperatives.dialog.select_torrent_save_location'),
|
||||
});
|
||||
|
||||
private readonly translator: I18nTranslatorInterface;
|
||||
|
||||
private readonly dialog: DialogInterface;
|
||||
|
||||
private constructor(
|
||||
nhentaiApi: NhentaiApiInterface,
|
||||
nhentaiSourceGetter: SourceGetterInterface,
|
||||
translator: I18nTranslatorInterface,
|
||||
dialog: DialogInterface
|
||||
) {
|
||||
this.nhentaiApi = nhentaiApi;
|
||||
this.nhentaiSourceGetter = nhentaiSourceGetter;
|
||||
this.translator = translator;
|
||||
this.dialog = dialog;
|
||||
if (result.canceled) {
|
||||
return;
|
||||
}
|
||||
|
||||
@answer(IpcChannel.NHENTAI_SAVE_FAVORITES)
|
||||
public async nhentaiSaveFavorites(): Promise<void> {
|
||||
const result = await this.dialog.selectFolder({
|
||||
title: this.translator.t('Select torrent file save location'),
|
||||
const favoritesStream = await nhentaiApi.getFavorites();
|
||||
|
||||
return new Promise((resolve) => {
|
||||
favoritesStream.on('data', (favorite: Nhentai.Favorite) => {
|
||||
const writable = createWriteStream(path.resolve(result.filePaths[0], favorite.name));
|
||||
favorite.torrentFile.pipe(writable);
|
||||
});
|
||||
|
||||
if (result.canceled) {
|
||||
return;
|
||||
}
|
||||
favoritesStream.once('end', resolve);
|
||||
});
|
||||
});
|
||||
|
||||
const favoritesStream = await this.nhentaiApi.getFavorites();
|
||||
ipcServer.answer(
|
||||
IpcChannel.NHENTAI_GET_WORK,
|
||||
async ({ galleryId }: { galleryId: string }): Promise<WorkEntityInterface> => {
|
||||
const nhentaiSourceGetter = container.get(Service.NHENTAI_SOURCE_GETTER);
|
||||
|
||||
return new Promise((resolve) => {
|
||||
favoritesStream.on('data', (favorite: Nhentai.Favorite) => {
|
||||
const writable = createWriteStream(path.resolve(result.filePaths[0], favorite.name));
|
||||
favorite.torrentFile.pipe(writable);
|
||||
});
|
||||
|
||||
favoritesStream.once('end', resolve);
|
||||
});
|
||||
}
|
||||
|
||||
@answer(IpcChannel.NHENTAI_GET_WORK)
|
||||
public async nhentaiGetWork({ galleryId }: { galleryId: string }): Promise<WorkEntityInterface> {
|
||||
const work = await this.nhentaiSourceGetter.find(galleryId);
|
||||
const work = await nhentaiSourceGetter.find(galleryId);
|
||||
|
||||
return work;
|
||||
}
|
||||
|
||||
public get(): NhentaiIpcController {
|
||||
const nhentaiApi: NhentaiApiInterface = container.get('nhentai-api');
|
||||
const nhentaiSourceGetter: SourceGetterInterface = container.get('nhentai-source-getter');
|
||||
const translator: I18nTranslatorInterface = container.get('i18n-translator');
|
||||
const dialog: DialogInterface = container.get('dialog');
|
||||
return new NhentaiIpcController(nhentaiApi, nhentaiSourceGetter, translator, dialog);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Service } from '../../core/container';
|
||||
import { Database, getConnection } from '../../core/database';
|
||||
import { inject } from '../../core/inject';
|
||||
import { Copy } from '../../entities/library/copy';
|
||||
|
@ -18,7 +19,7 @@ async function getLanguage(nhentaiLanguageIdentifier: NhentaiRealLanguage): Prom
|
|||
export class NhentaiSourceGetter implements SourceGetterInterface {
|
||||
private nhentaiApi: NhentaiApiInterface;
|
||||
|
||||
public constructor(@inject('nhentai-api') nhentaiApi: NhentaiApiInterface) {
|
||||
public constructor(@inject(Service.NHENTAI_API) nhentaiApi: NhentaiApiInterface) {
|
||||
this.nhentaiApi = nhentaiApi;
|
||||
}
|
||||
|
||||
|
@ -49,7 +50,7 @@ export class NhentaiSourceGetter implements SourceGetterInterface {
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
);
|
||||
work.languages = Promise.all(filteredLanguages.map((language) => getLanguage(language)));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
import type { EntityTarget } from 'typeorm';
|
||||
import { getRepository } from '../../core/database';
|
||||
|
||||
export function getDeserializedEntityPromise<T>(serializedProperty: number, entityTarget: EntityTarget<T>): Promise<T>;
|
||||
export function getDeserializedEntityPromise<T>(
|
||||
serializedProperty: undefined,
|
||||
entityTarget: EntityTarget<T>,
|
||||
): undefined;
|
||||
export function getDeserializedEntityPromise<T>(serializedProperty: null, entityTarget: EntityTarget<T>): null;
|
||||
export function getDeserializedEntityPromise<T>(
|
||||
serializedProperty: number | undefined,
|
||||
entityTarget: EntityTarget<T>,
|
||||
): Promise<T> | undefined;
|
||||
export function getDeserializedEntityPromise<T>(
|
||||
serializedProperty: number | undefined | null,
|
||||
entityTarget: EntityTarget<T>,
|
||||
): Promise<T> | undefined | null;
|
||||
export function getDeserializedEntityPromise<T>(
|
||||
serializedProperty: number | undefined | null,
|
||||
entityTarget: EntityTarget<T>,
|
||||
): Promise<T> | undefined | null {
|
||||
return serializedProperty === null
|
||||
? null
|
||||
: serializedProperty
|
||||
? getRepository(entityTarget).then((repo) => repo.findOneOrFail(serializedProperty))
|
||||
: undefined;
|
||||
}
|
||||
|
||||
export function getDeserializedEntitiesPromise<T>(
|
||||
serializedProperty: number[],
|
||||
entityTarget: EntityTarget<T>,
|
||||
): Promise<T[]>;
|
||||
export function getDeserializedEntitiesPromise<T>(
|
||||
serializedProperty: undefined,
|
||||
entityTarget: EntityTarget<T>,
|
||||
): undefined;
|
||||
export function getDeserializedEntitiesPromise<T>(
|
||||
serializedProperty: number[] | undefined,
|
||||
entityTarget: EntityTarget<T>,
|
||||
): Promise<T[]> | undefined;
|
||||
export function getDeserializedEntitiesPromise<T>(
|
||||
serializedProperty: number[] | undefined,
|
||||
entityTarget: EntityTarget<T>,
|
||||
): Promise<T[]> | undefined {
|
||||
return serializedProperty
|
||||
? Promise.all(serializedProperty.map((id) => getRepository(entityTarget).then((repo) => repo.findOneOrFail(id))))
|
||||
: undefined;
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
export function serializeEntityPromise<T extends Identifier>(
|
||||
entityPromise: Promise<IdentifiableInterface<T>>,
|
||||
): Promise<number>;
|
||||
export function serializeEntityPromise<T extends Identifier>(
|
||||
entityPromise: Promise<IdentifiableInterface<T>> | null,
|
||||
): Promise<T | null>;
|
||||
export async function serializeEntityPromise<T extends Identifier>(
|
||||
entityPromise: Promise<IdentifiableInterface<T>> | null,
|
||||
): Promise<T | null> {
|
||||
return entityPromise ? (await entityPromise).id : null;
|
||||
}
|
||||
|
||||
export async function serializeEntitiesPromise<T extends Identifier>(
|
||||
entitiesPromise: Promise<Array<IdentifiableInterface<T>>>,
|
||||
): Promise<T[]> {
|
||||
return (await entitiesPromise).map((entity) => entity.id);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import { serializeEntityPromise } from './serialize-entity-promise';
|
||||
|
||||
export async function serializeName(nameEntity: NameEntityInterface): Promise<NameSerializedInterface> {
|
||||
return {
|
||||
id: nameEntity.id,
|
||||
name: nameEntity.name,
|
||||
entity: await serializeEntityPromise(nameEntity.entity),
|
||||
};
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
export abstract class Serializer<
|
||||
Entity extends IdentifiableInterface<Id>,
|
||||
Serialized extends IdentifiableInterface<Id>,
|
||||
Id extends Identifier = number,
|
||||
> {
|
||||
public abstract serialize(entity: Entity): Promise<Serialized>;
|
||||
|
||||
public abstract deserialize(partial: Partial<Serialized>): Partial<Entity>;
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Author } from '../../../entities/library/author';
|
||||
import { getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeName } from '../serialize-name';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class AuthorNameSerializer extends Serializer<AuthorNameEntityInterface, AuthorNameSerializedInterface> {
|
||||
public serialize(entity: AuthorNameEntityInterface): Promise<AuthorNameSerializedInterface> {
|
||||
return serializeName(entity);
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<AuthorNameSerializedInterface>): Partial<AuthorNameEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.name ? { name: partial.name } : {}),
|
||||
...(partial.entity ? { entity: getDeserializedEntityPromise(partial.entity, Author) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { AuthorRole } from '../../../entities/library/author-role';
|
||||
import { getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeName } from '../serialize-name';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class AuthorRoleNameSerializer extends Serializer<
|
||||
AuthorRoleNameEntityInterface,
|
||||
AuthorRoleNameSerializedInterface
|
||||
> {
|
||||
public serialize(entity: AuthorRoleNameEntityInterface): Promise<AuthorRoleNameSerializedInterface> {
|
||||
return serializeName(entity);
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<AuthorRoleNameSerializedInterface>): Partial<AuthorRoleNameEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.name ? { name: partial.name } : {}),
|
||||
...(partial.entity ? { entity: getDeserializedEntityPromise(partial.entity, AuthorRole) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { AuthorRoleName } from '../../../entities/library/author-role-name';
|
||||
import { WorkAuthor } from '../../../entities/library/work-author';
|
||||
import { getDeserializedEntitiesPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class AuthorRoleSerializer extends Serializer<AuthorRoleEntityInterface, AuthorRoleSerializedInterface> {
|
||||
public async serialize(entity: AuthorRoleEntityInterface): Promise<AuthorRoleSerializedInterface> {
|
||||
const [names, workAuthors] = await Promise.all([
|
||||
serializeEntitiesPromise(entity.names),
|
||||
serializeEntitiesPromise(entity.workAuthors),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
nameCanonical: entity.nameCanonical,
|
||||
description: entity.description,
|
||||
names,
|
||||
workAuthors,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<AuthorRoleSerializedInterface>): Partial<AuthorRoleEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.nameCanonical ? { nameCanonical: partial.nameCanonical } : {}),
|
||||
...(partial.description ? { description: partial.description } : {}),
|
||||
...(partial.names ? { names: getDeserializedEntitiesPromise(partial.names, AuthorRoleName) } : {}),
|
||||
...(partial.workAuthors ? { workAuthors: getDeserializedEntitiesPromise(partial.workAuthors, WorkAuthor) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { AuthorName } from '../../../entities/library/author-name';
|
||||
import { WorkAuthor } from '../../../entities/library/work-author';
|
||||
import { getDeserializedEntitiesPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise } from '../serialize-entity-promise.js';
|
||||
import { Serializer } from '../serializer.js';
|
||||
|
||||
@injectable()
|
||||
export class AuthorSerializer extends Serializer<AuthorEntityInterface, AuthorSerializedInterface> {
|
||||
public async serialize(entity: AuthorEntityInterface): Promise<AuthorSerializedInterface> {
|
||||
const [names, workAuthors] = await Promise.all([
|
||||
serializeEntitiesPromise(entity.names),
|
||||
serializeEntitiesPromise(entity.workAuthors),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
nameCanonical: entity.nameCanonical,
|
||||
names,
|
||||
workAuthors,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<AuthorSerializedInterface>): Partial<AuthorEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.nameCanonical ? { nameCanonical: partial.nameCanonical } : {}),
|
||||
...(partial.names ? { names: getDeserializedEntitiesPromise(partial.names, AuthorName) } : {}),
|
||||
...(partial.workAuthors ? { workAuthors: getDeserializedEntitiesPromise(partial.workAuthors, WorkAuthor) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Tag } from '../../../entities/library/tag';
|
||||
import { WorkCharacter } from '../../../entities/library/work-character';
|
||||
import { getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeEntityPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class CharacterTagSerializer extends Serializer<CharacterTagEntityInterface, CharacterTagSerializedInterface> {
|
||||
public async serialize(entity: CharacterTagEntityInterface): Promise<CharacterTagSerializedInterface> {
|
||||
const [tag, workCharacter] = await Promise.all([
|
||||
serializeEntityPromise(entity.tag),
|
||||
serializeEntityPromise(entity.workCharacter),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
weight: entity.weight,
|
||||
tag,
|
||||
workCharacter,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<CharacterTagSerializedInterface>): Partial<CharacterTagEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.weight ? { weight: partial.weight } : {}),
|
||||
...(partial.tag ? { tag: getDeserializedEntityPromise(partial.tag, Tag) } : {}),
|
||||
...(partial.workCharacter
|
||||
? { workCharacter: getDeserializedEntityPromise(partial.workCharacter, WorkCharacter) }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Collection } from '../../../entities/library/collection';
|
||||
import { getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeName } from '../serialize-name';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class CollectionNameSerializer extends Serializer<
|
||||
CollectionNameEntityInterface,
|
||||
CollectionNameSerializedInterface
|
||||
> {
|
||||
public serialize(entity: CollectionNameEntityInterface): Promise<CollectionNameSerializedInterface> {
|
||||
return serializeName(entity);
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<CollectionNameSerializedInterface>): Partial<CollectionNameEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.name ? { name: partial.name } : {}),
|
||||
...(partial.entity ? { entity: getDeserializedEntityPromise(partial.entity, Collection) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Collection } from '../../../entities/library/collection';
|
||||
import { Work } from '../../../entities/library/work';
|
||||
import { getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeEntityPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class CollectionPartSerializer extends Serializer<
|
||||
CollectionPartEntityInterface,
|
||||
CollectionPartSerializedInterface
|
||||
> {
|
||||
public async serialize(entity: CollectionPartEntityInterface): Promise<CollectionPartSerializedInterface> {
|
||||
const [collection, work] = await Promise.all([
|
||||
serializeEntityPromise(entity.collection),
|
||||
serializeEntityPromise(entity.work),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
order: entity.order,
|
||||
collection,
|
||||
work,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<CollectionPartSerializedInterface>): Partial<CollectionPartEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.order ? { order: partial.order } : {}),
|
||||
...(partial.collection ? { collection: getDeserializedEntityPromise(partial.collection, Collection) } : {}),
|
||||
...(partial.work ? { work: getDeserializedEntityPromise(partial.work, Work) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { CollectionName } from '../../../entities/library/collection-name';
|
||||
import { CollectionPart } from '../../../entities/library/collection-part';
|
||||
import { getDeserializedEntitiesPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class CollectionSerializer extends Serializer<CollectionEntityInterface, CollectionSerializedInterface> {
|
||||
public async serialize(entity: CollectionEntityInterface): Promise<CollectionSerializedInterface> {
|
||||
const [names, parts] = await Promise.all([
|
||||
serializeEntitiesPromise(entity.names),
|
||||
serializeEntitiesPromise(entity.parts),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
nameCanonical: entity.nameCanonical,
|
||||
names,
|
||||
parts,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<CollectionSerializedInterface>): Partial<CollectionEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.nameCanonical ? { nameCanonical: partial.nameCanonical } : {}),
|
||||
...(partial.names ? { names: getDeserializedEntitiesPromise(partial.names, CollectionName) } : {}),
|
||||
...(partial.parts ? { parts: getDeserializedEntitiesPromise(partial.parts, CollectionPart) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Source } from '../../../entities/library/source';
|
||||
import { Work } from '../../../entities/library/work';
|
||||
import { getDeserializedEntitiesPromise, getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise, serializeEntityPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class CopySerializer extends Serializer<CopyEntityInterface, CopySerializedInterface> {
|
||||
public async serialize(entity: CopyEntityInterface): Promise<CopySerializedInterface> {
|
||||
const [original, sources] = await Promise.all([
|
||||
serializeEntityPromise(entity.original),
|
||||
serializeEntitiesPromise(entity.sources),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
hash: entity.hash,
|
||||
location: entity.location,
|
||||
ranking: entity.ranking,
|
||||
original,
|
||||
sources,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<CopySerializedInterface>): Partial<CopyEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.hash ? { hash: partial.hash } : {}),
|
||||
...(partial.location ? { location: partial.location } : {}),
|
||||
...(partial.ranking ? { ranking: partial.ranking } : {}),
|
||||
...(partial.original ? { original: getDeserializedEntityPromise(partial.original, Work) } : {}),
|
||||
...(partial.sources ? { sources: getDeserializedEntitiesPromise(partial.sources, Source) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Tag } from '../../../entities/library/tag';
|
||||
import { WorkCharacter } from '../../../entities/library/work-character';
|
||||
import { getDeserializedEntitiesPromise, getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise, serializeEntityPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
injectable();
|
||||
export class InteractionTagSerializer extends Serializer<
|
||||
InteractionTagEntityInterface,
|
||||
InteractionTagSerializedInterface
|
||||
> {
|
||||
public async serialize(entity: InteractionTagEntityInterface): Promise<InteractionTagSerializedInterface> {
|
||||
const [tag, objectCharacters, subjectCharacters] = await Promise.all([
|
||||
serializeEntityPromise(entity.tag),
|
||||
serializeEntitiesPromise(entity.objectCharacters),
|
||||
serializeEntitiesPromise(entity.subjectCharacters),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
weight: entity.weight,
|
||||
tag,
|
||||
objectCharacters,
|
||||
subjectCharacters,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<InteractionTagSerializedInterface>): Partial<InteractionTagEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.weight ? { weight: partial.weight } : {}),
|
||||
...(partial.tag ? { tag: getDeserializedEntityPromise(partial.tag, Tag) } : {}),
|
||||
...(partial.objectCharacters
|
||||
? { objectCharacters: getDeserializedEntitiesPromise(partial.objectCharacters, WorkCharacter) }
|
||||
: {}),
|
||||
...(partial.subjectCharacters
|
||||
? { subjectCharacters: getDeserializedEntitiesPromise(partial.subjectCharacters, WorkCharacter) }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Work } from '../../../entities/library/work';
|
||||
import { getDeserializedEntitiesPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise } from '../serialize-entity-promise.js';
|
||||
import { Serializer } from '../serializer.js';
|
||||
|
||||
@injectable()
|
||||
export class LanguageSerializer extends Serializer<LanguageEntityInterface, LanguageSerializedInterface, string> {
|
||||
public async serialize(entity: LanguageEntityInterface): Promise<LanguageSerializedInterface> {
|
||||
return {
|
||||
id: entity.code,
|
||||
code: entity.code,
|
||||
works: await serializeEntitiesPromise(entity.works),
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<LanguageSerializedInterface>): Partial<LanguageEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.code ? { code: partial.code } : {}),
|
||||
...(partial.works ? { works: getDeserializedEntitiesPromise(partial.works, Work) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Site } from '../../../entities/library/site';
|
||||
import { getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeName } from '../serialize-name';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class SiteNameSerializer extends Serializer<SiteNameEntityInterface, SiteNameSerializedInterface> {
|
||||
public serialize(entity: SiteNameEntityInterface): Promise<SiteNameSerializedInterface> {
|
||||
return serializeName(entity);
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<SiteNameSerializedInterface>): Partial<SiteNameEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.name ? { name: partial.name } : {}),
|
||||
...(partial.entity ? { entity: getDeserializedEntityPromise(partial.entity, Site) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { SiteName } from '../../../entities/library/site-name';
|
||||
import { Source } from '../../../entities/library/source';
|
||||
import { getDeserializedEntitiesPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class SiteSerializer extends Serializer<SiteEntityInterface, SiteSerializedInterface> {
|
||||
public async serialize(entity: SiteEntityInterface): Promise<SiteSerializedInterface> {
|
||||
const [names, sources] = await Promise.all([
|
||||
serializeEntitiesPromise(entity.names),
|
||||
serializeEntitiesPromise(entity.sources),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
nameCanonical: entity.nameCanonical,
|
||||
names,
|
||||
sources,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<SiteSerializedInterface>): Partial<SiteEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.nameCanonical ? { nameCanonical: partial.nameCanonical } : {}),
|
||||
...(partial.names ? { names: getDeserializedEntitiesPromise(partial.names, SiteName) } : {}),
|
||||
...(partial.sources ? { sources: getDeserializedEntitiesPromise(partial.sources, Source) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Copy } from '../../../entities/library/copy';
|
||||
import { Site } from '../../../entities/library/site';
|
||||
import { getDeserializedEntitiesPromise, getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise, serializeEntityPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
injectable();
|
||||
export class SourceSerializer extends Serializer<SourceEntityInterface, SourceSerializedInterface> {
|
||||
public async serialize(entity: SourceEntityInterface): Promise<SourceSerializedInterface> {
|
||||
const [copies, site] = await Promise.all([
|
||||
serializeEntitiesPromise(entity.copies),
|
||||
serializeEntityPromise(entity.site),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
uri: entity.uri,
|
||||
copies,
|
||||
site,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<SourceSerializedInterface>): Partial<SourceEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.uri ? { uri: partial.uri } : {}),
|
||||
...(partial.site ? { site: getDeserializedEntityPromise(partial.site, Site) } : {}),
|
||||
...(partial.copies ? { copies: getDeserializedEntitiesPromise(partial.copies, Copy) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Tag } from '../../../entities/library/tag';
|
||||
import { getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeName } from '../serialize-name';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class TagNameSerializer extends Serializer<TagNameEntityInterface, TagNameSerializedInterface> {
|
||||
public serialize(entity: TagNameEntityInterface): Promise<TagNameSerializedInterface> {
|
||||
return serializeName(entity);
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<TagNameSerializedInterface>): Partial<TagNameEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.name ? { name: partial.name } : {}),
|
||||
...(partial.entity ? { entity: getDeserializedEntityPromise(partial.entity, Tag) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { CharacterTag } from '../../../entities/library/character-tag';
|
||||
import { InteractionTag } from '../../../entities/library/interaction-tag';
|
||||
import { Tag } from '../../../entities/library/tag';
|
||||
import { TagName } from '../../../entities/library/tag-name';
|
||||
import { WorkTag } from '../../../entities/library/work-tag';
|
||||
import { getDeserializedEntitiesPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class TagSerializer extends Serializer<TagEntityInterface, TagSerializedInterface> {
|
||||
public async serialize(entity: TagEntityInterface): Promise<TagSerializedInterface> {
|
||||
const [names, characterTags, children, parents, interactionTags, workTags] = await Promise.all([
|
||||
serializeEntitiesPromise(entity.names),
|
||||
serializeEntitiesPromise(entity.characterTags),
|
||||
serializeEntitiesPromise(entity.children),
|
||||
serializeEntitiesPromise(entity.parents),
|
||||
serializeEntitiesPromise(entity.interactionTags),
|
||||
serializeEntitiesPromise(entity.workTags),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
nameCanonical: entity.nameCanonical,
|
||||
description: entity.description,
|
||||
names,
|
||||
characterTags,
|
||||
children,
|
||||
parents,
|
||||
interactionTags,
|
||||
workTags,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<TagSerializedInterface>): Partial<TagEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.nameCanonical ? { nameCanonical: partial.nameCanonical } : {}),
|
||||
...(partial.description ? { description: partial.description } : {}),
|
||||
...(partial.names ? { names: getDeserializedEntitiesPromise(partial.names, TagName) } : {}),
|
||||
...(partial.children ? { children: getDeserializedEntitiesPromise(partial.children, Tag) } : {}),
|
||||
...(partial.parents ? { parents: getDeserializedEntitiesPromise(partial.parents, Tag) } : {}),
|
||||
...(partial.workTags ? { workTags: getDeserializedEntitiesPromise(partial.workTags, WorkTag) } : {}),
|
||||
...(partial.interactionTags
|
||||
? { interactionTags: getDeserializedEntitiesPromise(partial.interactionTags, InteractionTag) }
|
||||
: {}),
|
||||
...(partial.characterTags
|
||||
? { characterTags: getDeserializedEntitiesPromise(partial.characterTags, CharacterTag) }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { TransformationType } from '../../../entities/library/transformation-type';
|
||||
import { Work } from '../../../entities/library/work';
|
||||
import { getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeEntityPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class TransformationSerializer extends Serializer<
|
||||
TransformationEntityInterface,
|
||||
TransformationSerializedInterface
|
||||
> {
|
||||
public async serialize(entity: TransformationEntityInterface): Promise<TransformationSerializedInterface> {
|
||||
const [byWork, ofWork, type] = await Promise.all([
|
||||
serializeEntityPromise(entity.byWork),
|
||||
serializeEntityPromise(entity.ofWork),
|
||||
serializeEntityPromise(entity.type),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
order: entity.order,
|
||||
byWork,
|
||||
ofWork,
|
||||
type,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<TransformationSerializedInterface>): Partial<TransformationEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.order ? { order: partial.order } : {}),
|
||||
...(partial.type ? { type: getDeserializedEntityPromise(partial.type, TransformationType) } : {}),
|
||||
...(partial.ofWork ? { ofWork: getDeserializedEntityPromise(partial.ofWork, Work) } : {}),
|
||||
...(partial.byWork ? { byWork: getDeserializedEntityPromise(partial.byWork, Work) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { TransformationType } from '../../../entities/library/transformation-type';
|
||||
import { getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeName } from '../serialize-name';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class TransformationTypeNameSerializer extends Serializer<
|
||||
TransformationTypeNameEntityInterface,
|
||||
TransformationTypeNameSerializedInterface
|
||||
> {
|
||||
public serialize(entity: TransformationTypeNameEntityInterface): Promise<TransformationTypeNameSerializedInterface> {
|
||||
return serializeName(entity);
|
||||
}
|
||||
|
||||
public deserialize(
|
||||
partial: Partial<TransformationTypeNameSerializedInterface>,
|
||||
): Partial<TransformationTypeNameEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.name ? { name: partial.name } : {}),
|
||||
...(partial.entity ? { entity: getDeserializedEntityPromise(partial.entity, TransformationType) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Transformation } from '../../../entities/library/transformation';
|
||||
import { TransformationTypeName } from '../../../entities/library/transformation-type-name';
|
||||
import { getDeserializedEntitiesPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class TransformationTypeSerializer extends Serializer<
|
||||
TransformationTypeEntityInterface,
|
||||
TransformationTypeSerializedInterface
|
||||
> {
|
||||
public async serialize(entity: TransformationTypeEntityInterface): Promise<TransformationTypeSerializedInterface> {
|
||||
const [names, transformations] = await Promise.all([
|
||||
serializeEntitiesPromise(entity.names),
|
||||
serializeEntitiesPromise(entity.transformations),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
nameCanonical: entity.nameCanonical,
|
||||
description: entity.description,
|
||||
conservesTags: entity.conservesTags,
|
||||
names,
|
||||
transformations,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(
|
||||
partial: Partial<TransformationTypeSerializedInterface>,
|
||||
): Partial<TransformationTypeEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.nameCanonical ? { nameCanonical: partial.nameCanonical } : {}),
|
||||
...(partial.description ? { description: partial.description } : {}),
|
||||
...(partial.conservesTags ? { conservesTags: partial.conservesTags } : {}),
|
||||
...(partial.names ? { names: getDeserializedEntitiesPromise(partial.names, TransformationTypeName) } : {}),
|
||||
...(partial.transformations
|
||||
? { transformations: getDeserializedEntitiesPromise(partial.transformations, Transformation) }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Author } from '../../../entities/library/author';
|
||||
import { AuthorRole } from '../../../entities/library/author-role';
|
||||
import { Work } from '../../../entities/library/work';
|
||||
import { getDeserializedEntitiesPromise, getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise, serializeEntityPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class WorkAuthorSerializer extends Serializer<WorkAuthorEntityInterface, WorkAuthorSerializedInterface> {
|
||||
public async serialize(entity: WorkAuthorEntityInterface): Promise<WorkAuthorSerializedInterface> {
|
||||
const [author, work, authorRoles] = await Promise.all([
|
||||
serializeEntityPromise(entity.author),
|
||||
serializeEntityPromise(entity.work),
|
||||
serializeEntitiesPromise(entity.authorRoles),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
order: entity.order,
|
||||
author,
|
||||
work,
|
||||
authorRoles,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<WorkAuthorSerializedInterface>): Partial<WorkAuthorEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.work ? { order: partial.work } : {}),
|
||||
...(partial.work ? { work: getDeserializedEntityPromise(partial.work, Work) } : {}),
|
||||
...(partial.author ? { author: getDeserializedEntityPromise(partial.author, Author) } : {}),
|
||||
...(partial.authorRoles ? { authorRoles: getDeserializedEntitiesPromise(partial.authorRoles, AuthorRole) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { WorkCharacter } from '../../../entities/library/work-character';
|
||||
import { getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeName } from '../serialize-name';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class WorkCharacterNameSerializer extends Serializer<
|
||||
WorkCharacterNameEntityInterface,
|
||||
WorkCharacterNameSerializedInterface
|
||||
> {
|
||||
public serialize(entity: WorkCharacterNameEntityInterface): Promise<WorkCharacterNameSerializedInterface> {
|
||||
return serializeName(entity);
|
||||
}
|
||||
|
||||
public deserialize(
|
||||
partial: Partial<WorkCharacterNameSerializedInterface>,
|
||||
): Partial<WorkCharacterNameEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.name ? { name: partial.name } : {}),
|
||||
...(partial.entity ? { entity: getDeserializedEntityPromise(partial.entity, WorkCharacter) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { CharacterTag } from '../../../entities/library/character-tag';
|
||||
import { InteractionTag } from '../../../entities/library/interaction-tag';
|
||||
import { Work } from '../../../entities/library/work';
|
||||
import { WorkCharacterName } from '../../../entities/library/work-character-name';
|
||||
import { WorldCharacter } from '../../../entities/library/world-character';
|
||||
import { getDeserializedEntitiesPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class WorkCharacterSerializer extends Serializer<
|
||||
WorkCharacterEntityInterface,
|
||||
WorkCharacterSerializedInterface
|
||||
> {
|
||||
public async serialize(entity: WorkCharacterEntityInterface): Promise<WorkCharacterSerializedInterface> {
|
||||
const [names, characterTags, interactedBy, works, interactWith, worldCharacters] = await Promise.all([
|
||||
serializeEntitiesPromise(entity.names),
|
||||
serializeEntitiesPromise(entity.characterTags),
|
||||
serializeEntitiesPromise(entity.interactedBy),
|
||||
serializeEntitiesPromise(entity.works),
|
||||
serializeEntitiesPromise(entity.interactWith),
|
||||
serializeEntitiesPromise(entity.worldCharacters),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
nameCanonical: entity.nameCanonical,
|
||||
names,
|
||||
characterTags,
|
||||
interactedBy,
|
||||
works,
|
||||
interactWith,
|
||||
worldCharacters,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<WorkCharacterSerializedInterface>): Partial<WorkCharacterEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.nameCanonical ? { nameCanonical: partial.nameCanonical } : {}),
|
||||
...(partial.names ? { names: getDeserializedEntitiesPromise(partial.names, WorkCharacterName) } : {}),
|
||||
...(partial.works ? { works: getDeserializedEntitiesPromise(partial.works, Work) } : {}),
|
||||
...(partial.characterTags
|
||||
? { characterTags: getDeserializedEntitiesPromise(partial.characterTags, CharacterTag) }
|
||||
: {}),
|
||||
...(partial.worldCharacters
|
||||
? { worldCharacters: getDeserializedEntitiesPromise(partial.worldCharacters, WorldCharacter) }
|
||||
: {}),
|
||||
...(partial.interactedBy
|
||||
? { interactedBy: getDeserializedEntitiesPromise(partial.interactedBy, InteractionTag) }
|
||||
: {}),
|
||||
...(partial.interactWith
|
||||
? { interactWith: getDeserializedEntitiesPromise(partial.interactWith, InteractionTag) }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Work } from '../../../entities/library/work';
|
||||
import { getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeName } from '../serialize-name';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class WorkNameSerializer extends Serializer<WorkNameEntityInterface, WorkNameSerializedInterface> {
|
||||
public serialize(entity: WorkNameEntityInterface): Promise<WorkNameSerializedInterface> {
|
||||
return serializeName(entity);
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<WorkNameSerializedInterface>): Partial<WorkNameEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.name ? { name: partial.name } : {}),
|
||||
...(partial.entity ? { entity: getDeserializedEntityPromise(partial.entity, Work) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Copy } from '../../../entities/library/copy';
|
||||
import { Transformation } from '../../../entities/library/transformation';
|
||||
import { WorkAuthor } from '../../../entities/library/work-author';
|
||||
import { WorkCharacter } from '../../../entities/library/work-character';
|
||||
import { WorkName } from '../../../entities/library/work-name';
|
||||
import { WorkTag } from '../../../entities/library/work-tag';
|
||||
import { World } from '../../../entities/library/world';
|
||||
import { getDeserializedEntitiesPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise } from '../serialize-entity-promise.js';
|
||||
import { Serializer } from '../serializer.js';
|
||||
|
||||
@injectable()
|
||||
export class WorkSerializer extends Serializer<WorkEntityInterface, WorkSerializedInterface> {
|
||||
public async serialize(entity: WorkEntityInterface): Promise<WorkSerializedInterface> {
|
||||
const [
|
||||
languages,
|
||||
collectionParts,
|
||||
copies,
|
||||
names,
|
||||
transformationOf,
|
||||
transformedBy,
|
||||
workAuthors,
|
||||
workCharacters,
|
||||
workTags,
|
||||
worlds,
|
||||
] = await Promise.all([
|
||||
serializeEntitiesPromise(entity.languages),
|
||||
serializeEntitiesPromise(entity.collectionParts),
|
||||
serializeEntitiesPromise(entity.copies),
|
||||
serializeEntitiesPromise(entity.names),
|
||||
serializeEntitiesPromise(entity.transformationOf),
|
||||
serializeEntitiesPromise(entity.transformedBy),
|
||||
serializeEntitiesPromise(entity.workAuthors),
|
||||
serializeEntitiesPromise(entity.workCharacters),
|
||||
serializeEntitiesPromise(entity.workTags),
|
||||
serializeEntitiesPromise(entity.worlds),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
isCanonical: entity.isCanonical,
|
||||
nameCanonical: entity.nameCanonical,
|
||||
rating: entity.rating,
|
||||
releaseDate: entity.releaseDate,
|
||||
languages,
|
||||
collectionParts,
|
||||
copies,
|
||||
names,
|
||||
transformationOf,
|
||||
transformedBy,
|
||||
workAuthors,
|
||||
workCharacters,
|
||||
workTags,
|
||||
worlds,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<WorkSerializedInterface>): Partial<WorkEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.nameCanonical ? { nameCanonical: partial.nameCanonical } : {}),
|
||||
...(partial.rating ? { rating: partial.rating } : {}),
|
||||
...(partial.releaseDate ? { releaseDate: partial.releaseDate } : {}),
|
||||
...(partial.isCanonical ? { isCanonical: partial.isCanonical } : {}),
|
||||
...(partial.copies ? { copies: getDeserializedEntitiesPromise(partial.copies, Copy) } : {}),
|
||||
...(partial.names ? { names: getDeserializedEntitiesPromise(partial.names, WorkName) } : {}),
|
||||
...(partial.transformationOf
|
||||
? { transformationOf: getDeserializedEntitiesPromise(partial.transformationOf, Transformation) }
|
||||
: {}),
|
||||
...(partial.transformedBy
|
||||
? { transformedBy: getDeserializedEntitiesPromise(partial.transformedBy, Transformation) }
|
||||
: {}),
|
||||
...(partial.workAuthors ? { workAuthors: getDeserializedEntitiesPromise(partial.workAuthors, WorkAuthor) } : {}),
|
||||
...(partial.workCharacters
|
||||
? { workCharacters: getDeserializedEntitiesPromise(partial.workCharacters, WorkCharacter) }
|
||||
: {}),
|
||||
...(partial.workTags ? { workTags: getDeserializedEntitiesPromise(partial.workTags, WorkTag) } : {}),
|
||||
...(partial.worlds ? { worlds: getDeserializedEntitiesPromise(partial.worlds, World) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Tag } from '../../../entities/library/tag';
|
||||
import { Work } from '../../../entities/library/work';
|
||||
import { getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeEntityPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class WorkTagSerializer extends Serializer<WorkTagEntityInterface, WorkTagSerializedInterface> {
|
||||
public async serialize(entity: WorkTagEntityInterface): Promise<WorkTagSerializedInterface> {
|
||||
const [tag, work] = await Promise.all([serializeEntityPromise(entity.tag), serializeEntityPromise(entity.work)]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
weight: entity.weight,
|
||||
tag,
|
||||
work,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<WorkTagSerializedInterface>): Partial<WorkTagEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.weight ? { weight: partial.weight } : {}),
|
||||
...(partial.tag ? { tag: getDeserializedEntityPromise(partial.tag, Tag) } : {}),
|
||||
...(partial.work ? { work: getDeserializedEntityPromise(partial.work, Work) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { WorldCharacter } from '../../../entities/library/world-character';
|
||||
import { getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeName } from '../serialize-name';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class WorldCharacterNameSerializer extends Serializer<
|
||||
WorldCharacterNameEntityInterface,
|
||||
WorldCharacterNameSerializedInterface
|
||||
> {
|
||||
public serialize(entity: WorldCharacterNameEntityInterface): Promise<WorldCharacterNameSerializedInterface> {
|
||||
return serializeName(entity);
|
||||
}
|
||||
|
||||
public deserialize(
|
||||
partial: Partial<WorldCharacterNameSerializedInterface>,
|
||||
): Partial<WorldCharacterNameEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.name ? { name: partial.name } : {}),
|
||||
...(partial.entity ? { entity: getDeserializedEntityPromise(partial.entity, WorldCharacter) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { WorkCharacter } from '../../../entities/library/work-character';
|
||||
import { World } from '../../../entities/library/world';
|
||||
import { WorldCharacter } from '../../../entities/library/world-character';
|
||||
import { WorldCharacterName } from '../../../entities/library/world-character-name';
|
||||
import { getDeserializedEntitiesPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class WorldCharacterSerializer extends Serializer<
|
||||
WorldCharacterEntityInterface,
|
||||
WorldCharacterSerializedInterface
|
||||
> {
|
||||
public async serialize(entity: WorldCharacterEntityInterface): Promise<WorldCharacterSerializedInterface> {
|
||||
const [names, children, parents, workCharacters, worlds] = await Promise.all([
|
||||
serializeEntitiesPromise(entity.names),
|
||||
serializeEntitiesPromise(entity.children),
|
||||
serializeEntitiesPromise(entity.parents),
|
||||
serializeEntitiesPromise(entity.workCharacters),
|
||||
serializeEntitiesPromise(entity.worlds),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
nameCanonical: entity.nameCanonical,
|
||||
names,
|
||||
children,
|
||||
parents,
|
||||
workCharacters,
|
||||
worlds,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<WorldCharacterSerializedInterface>): Partial<WorldCharacterEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.nameCanonical ? { nameCanonical: partial.nameCanonical } : {}),
|
||||
...(partial.names ? { names: getDeserializedEntitiesPromise(partial.names, WorldCharacterName) } : {}),
|
||||
...(partial.children ? { children: getDeserializedEntitiesPromise(partial.children, WorldCharacter) } : {}),
|
||||
...(partial.parents ? { parents: getDeserializedEntitiesPromise(partial.parents, WorldCharacter) } : {}),
|
||||
...(partial.workCharacters
|
||||
? { workCharacters: getDeserializedEntitiesPromise(partial.workCharacters, WorkCharacter) }
|
||||
: {}),
|
||||
...(partial.worlds ? { worlds: getDeserializedEntitiesPromise(partial.worlds, World) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { World } from '../../../entities/library/world';
|
||||
import { getDeserializedEntityPromise } from '../get-deserialized';
|
||||
import { serializeName } from '../serialize-name';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class WorldNameSerializer extends Serializer<WorldNameEntityInterface, WorldNameSerializedInterface> {
|
||||
public serialize(entity: WorldNameEntityInterface): Promise<WorldNameSerializedInterface> {
|
||||
return serializeName(entity);
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<WorldNameSerializedInterface>): Partial<WorldNameEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.name ? { name: partial.name } : {}),
|
||||
...(partial.entity ? { entity: getDeserializedEntityPromise(partial.entity, World) } : {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
import { injectable } from 'inversify';
|
||||
import { Work } from '../../../entities/library/work';
|
||||
import { World } from '../../../entities/library/world';
|
||||
import { WorldCharacter } from '../../../entities/library/world-character';
|
||||
import { WorldName } from '../../../entities/library/world-name';
|
||||
import { getDeserializedEntitiesPromise } from '../get-deserialized';
|
||||
import { serializeEntitiesPromise } from '../serialize-entity-promise';
|
||||
import { Serializer } from '../serializer';
|
||||
|
||||
@injectable()
|
||||
export class WorldSerializer extends Serializer<WorldEntityInterface, WorldSerializedInterface> {
|
||||
public async serialize(entity: WorldEntityInterface): Promise<WorldSerializedInterface> {
|
||||
const [names, children, parents, works, worldCharacters] = await Promise.all([
|
||||
serializeEntitiesPromise(entity.names),
|
||||
serializeEntitiesPromise(entity.children),
|
||||
serializeEntitiesPromise(entity.parents),
|
||||
serializeEntitiesPromise(entity.works),
|
||||
serializeEntitiesPromise(entity.worldCharacters),
|
||||
]);
|
||||
|
||||
return {
|
||||
id: entity.id,
|
||||
nameCanonical: entity.nameCanonical,
|
||||
names,
|
||||
children,
|
||||
parents,
|
||||
works,
|
||||
worldCharacters,
|
||||
};
|
||||
}
|
||||
|
||||
public deserialize(partial: Partial<WorldSerializedInterface>): Partial<WorldEntityInterface> {
|
||||
return {
|
||||
...(partial.id ? { id: partial.id } : {}),
|
||||
...(partial.nameCanonical ? { nameCanonical: partial.nameCanonical } : {}),
|
||||
...(partial.names ? { names: getDeserializedEntitiesPromise(partial.names, WorldName) } : {}),
|
||||
...(partial.children ? { children: getDeserializedEntitiesPromise(partial.children, World) } : {}),
|
||||
...(partial.parents ? { parents: getDeserializedEntitiesPromise(partial.parents, World) } : {}),
|
||||
...(partial.works ? { works: getDeserializedEntitiesPromise(partial.works, Work) } : {}),
|
||||
...(partial.worldCharacters
|
||||
? { worldCharacters: getDeserializedEntitiesPromise(partial.worldCharacters, WorldCharacter) }
|
||||
: {}),
|
||||
};
|
||||
}
|
||||
}
|
|
@ -11,7 +11,7 @@ function stringifyCspHeader(csp: ContentSecurityPolicy): string {
|
|||
return Object.entries(csp)
|
||||
.map(
|
||||
(directive: [string, Session.CspValue[] | undefined]) =>
|
||||
`${directive[0]} ${directive[1] ? directive[1]?.join(' ') : ''}`
|
||||
`${directive[0]} ${directive[1] ? directive[1]?.join(' ') : ''}`,
|
||||
)
|
||||
.join('; ');
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import { expect } from 'chai';
|
||||
import 'mocha';
|
||||
import { container } from '../../core/container';
|
||||
import { container, Service } from '../../core/container';
|
||||
|
||||
describe('Store Service', function () {
|
||||
this.timeout(10000);
|
||||
|
||||
it('loads saved data', () => {
|
||||
const store: StoreInterface = container.get('store');
|
||||
const store: StoreInterface = container.get(Service.STORE);
|
||||
const testData = {
|
||||
something: 'gaga',
|
||||
somethingElse: 0,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import App from './renderer/App.svelte';
|
||||
|
||||
new App({
|
||||
target: document.querySelector('#app'),
|
||||
target: document.querySelector('#app') as Element,
|
||||
});
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
import NhentaiSaveFavorites from './components/modules/NhentaiSaveFavorites.svelte';
|
||||
</script>
|
||||
|
||||
<main>
|
||||
<NhentaiSaveFavorites />
|
||||
<NhentaiGetWork />
|
||||
</main>
|
||||
|
||||
<style>
|
||||
:global(:root) {
|
||||
--color-white: #fff;
|
||||
|
@ -43,8 +48,3 @@
|
|||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
|
||||
<main>
|
||||
<NhentaiSaveFavorites></NhentaiSaveFavorites>
|
||||
<NhentaiGetWork />
|
||||
</main>
|
||||
|
|
|
@ -1,16 +1,48 @@
|
|||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import { entityApi } from '../../services/api';
|
||||
import { onDestroy } from 'svelte';
|
||||
import { workRepository } from '../../store/repositories/entities/work-repository';
|
||||
|
||||
export let id;
|
||||
export let id = 0;
|
||||
|
||||
/** @type {WorkSerializedInterface | undefined} */
|
||||
let work;
|
||||
let unsubscribe = () => {};
|
||||
|
||||
onMount(() => {
|
||||
entityApi.fetchWork(id).then((workSerialized) => {
|
||||
work = workSerialized;
|
||||
});
|
||||
$: unsubscribe = workRepository.subscribe(id, (serialized) => {
|
||||
work = serialized;
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
unsubscribe();
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="work">{#if work}{JSON.stringify(work)}{/if}</div>
|
||||
<div class="work">
|
||||
{#if work}
|
||||
<dl>
|
||||
<div>
|
||||
<dt>id</dt>
|
||||
<dd>{work?.id}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<dt>name</dt>
|
||||
<dd>{work?.nameCanonical}</dd>
|
||||
</div>
|
||||
<div>
|
||||
<input
|
||||
type="text"
|
||||
on:change="{(input) => {
|
||||
workRepository.update(id, (w) => {
|
||||
w.nameCanonical = input.target.value;
|
||||
return w;
|
||||
});
|
||||
}}"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<dt>languages</dt>
|
||||
<dd>{work?.languages.join(', ')}</dd>
|
||||
</div>
|
||||
</dl>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
<button class="button" on:click|preventDefault>
|
||||
<slot />
|
||||
</button>
|
||||
|
||||
<style>
|
||||
.button {
|
||||
border: none;
|
||||
|
@ -9,7 +13,3 @@
|
|||
outline-color: var(--color-accent-light);
|
||||
}
|
||||
</style>
|
||||
|
||||
<button class="button" on:click|preventDefault>
|
||||
<slot></slot>
|
||||
</button>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<script>
|
||||
import Work from '../content/Work.svelte';
|
||||
import { t } from '../../../shared/services/translation/t';
|
||||
import { nhentaiGetWork } from '../../services/api';
|
||||
import Work from '../content/Work.svelte';
|
||||
import SvelteButton from '../elements/SvelteButton.svelte';
|
||||
import { t } from '../../services/utils';
|
||||
|
||||
let galleryId;
|
||||
let work;
|
||||
|
@ -13,9 +13,10 @@
|
|||
</script>
|
||||
|
||||
<div class="nhentai-get-work">
|
||||
<label><input type="text" placeholder="177013" bind:value="{galleryId}" /></label
|
||||
><SvelteButton on:click="{handleClick}">{t('Get')}</SvelteButton>
|
||||
<input type="text" placeholder="177013" bind:value="{galleryId}" /><SvelteButton on:click="{handleClick}"
|
||||
>{t('labels.actions.get')}</SvelteButton
|
||||
>
|
||||
{#if work}
|
||||
<Work id="{work.id}" />
|
||||
<Work id="{work.id}" />
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
<script>
|
||||
import { t } from '../../services/utils';
|
||||
import SvelteButton from '../elements/SvelteButton.svelte';
|
||||
import { t } from '../../../shared/services/translation/t';
|
||||
import { nhentaiSaveFavorites } from '../../services/api';
|
||||
import SvelteButton from '../elements/SvelteButton.svelte';
|
||||
|
||||
function handleClick() {
|
||||
nhentaiSaveFavorites();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
|
||||
<div class="nhentai-login">
|
||||
<SvelteButton on:click="{handleClick}">{ t('Save nhentai Favorites') }</SvelteButton>
|
||||
<SvelteButton on:click="{handleClick}">{t('labels.actions.save_nhentai_favorites')}</SvelteButton>
|
||||
</div>
|
||||
|
|
|
@ -1,15 +1,493 @@
|
|||
import { ipcClient } from './ipc-client';
|
||||
|
||||
export function nhentaiSaveFavorites(): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.NHENTAI_SAVE_FAVORITES) as Promise<void>;
|
||||
return ipcClient.ask(IpcChannel.NHENTAI_SAVE_FAVORITES, undefined);
|
||||
}
|
||||
|
||||
export function nhentaiGetWork(galleryId: string): Promise<WorkEntityInterface> {
|
||||
return ipcClient.ask(IpcChannel.NHENTAI_GET_WORK, { galleryId }) as Promise<WorkEntityInterface>;
|
||||
return ipcClient.ask(IpcChannel.NHENTAI_GET_WORK, { galleryId });
|
||||
}
|
||||
|
||||
type IpcChannelEntityRead =
|
||||
| IpcChannel.ENTITY_READ_AUTHOR
|
||||
| IpcChannel.ENTITY_READ_AUTHOR_NAME
|
||||
| IpcChannel.ENTITY_READ_AUTHOR_ROLE
|
||||
| IpcChannel.ENTITY_READ_AUTHOR_ROLE_NAME
|
||||
| IpcChannel.ENTITY_READ_CHARACTER_TAG
|
||||
| IpcChannel.ENTITY_READ_COLLECTION
|
||||
| IpcChannel.ENTITY_READ_COLLECTION_NAME
|
||||
| IpcChannel.ENTITY_READ_COLLECTION_PART
|
||||
| IpcChannel.ENTITY_READ_COPY
|
||||
| IpcChannel.ENTITY_READ_INTERACTION_TAG
|
||||
| IpcChannel.ENTITY_READ_LANGUAGE
|
||||
| IpcChannel.ENTITY_READ_SITE
|
||||
| IpcChannel.ENTITY_READ_SITE_NAME
|
||||
| IpcChannel.ENTITY_READ_SOURCE
|
||||
| IpcChannel.ENTITY_READ_TAG
|
||||
| IpcChannel.ENTITY_READ_TAG_NAME
|
||||
| IpcChannel.ENTITY_READ_TRANSFORMATION
|
||||
| IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE
|
||||
| IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE_NAME
|
||||
| IpcChannel.ENTITY_READ_WORK_AUTHOR
|
||||
| IpcChannel.ENTITY_READ_WORK_CHARACTER
|
||||
| IpcChannel.ENTITY_READ_WORK_CHARACTER_NAME
|
||||
| IpcChannel.ENTITY_READ_WORK
|
||||
| IpcChannel.ENTITY_READ_WORK_NAME
|
||||
| IpcChannel.ENTITY_READ_WORK_TAG
|
||||
| IpcChannel.ENTITY_READ_WORLD
|
||||
| IpcChannel.ENTITY_READ_WORLD_NAME
|
||||
| IpcChannel.ENTITY_READ_WORLD_CHARACTER
|
||||
| IpcChannel.ENTITY_READ_WORLD_CHARACTER_NAME;
|
||||
|
||||
/**
|
||||
* when there are duplicate requests to the same entity, the existing promise is returned
|
||||
*
|
||||
* this promise is deleted once resolved, this is not a cache!
|
||||
*/
|
||||
const entityReadPromiseCollector: {
|
||||
[channel in IpcChannelEntityRead]: {
|
||||
[identifier in Identifier]?: Promise<IpcAnswer<channel>>;
|
||||
};
|
||||
} = {
|
||||
[IpcChannel.ENTITY_READ_AUTHOR]: {},
|
||||
[IpcChannel.ENTITY_READ_AUTHOR_NAME]: {},
|
||||
[IpcChannel.ENTITY_READ_AUTHOR_ROLE]: {},
|
||||
[IpcChannel.ENTITY_READ_AUTHOR_ROLE_NAME]: {},
|
||||
[IpcChannel.ENTITY_READ_CHARACTER_TAG]: {},
|
||||
[IpcChannel.ENTITY_READ_COLLECTION]: {},
|
||||
[IpcChannel.ENTITY_READ_COLLECTION_NAME]: {},
|
||||
[IpcChannel.ENTITY_READ_COLLECTION_PART]: {},
|
||||
[IpcChannel.ENTITY_READ_COPY]: {},
|
||||
[IpcChannel.ENTITY_READ_INTERACTION_TAG]: {},
|
||||
[IpcChannel.ENTITY_READ_LANGUAGE]: {},
|
||||
[IpcChannel.ENTITY_READ_SITE]: {},
|
||||
[IpcChannel.ENTITY_READ_SITE_NAME]: {},
|
||||
[IpcChannel.ENTITY_READ_SOURCE]: {},
|
||||
[IpcChannel.ENTITY_READ_TAG]: {},
|
||||
[IpcChannel.ENTITY_READ_TAG_NAME]: {},
|
||||
[IpcChannel.ENTITY_READ_TRANSFORMATION]: {},
|
||||
[IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE]: {},
|
||||
[IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE_NAME]: {},
|
||||
[IpcChannel.ENTITY_READ_WORK_AUTHOR]: {},
|
||||
[IpcChannel.ENTITY_READ_WORK_CHARACTER]: {},
|
||||
[IpcChannel.ENTITY_READ_WORK_CHARACTER_NAME]: {},
|
||||
[IpcChannel.ENTITY_READ_WORK]: {},
|
||||
[IpcChannel.ENTITY_READ_WORK_NAME]: {},
|
||||
[IpcChannel.ENTITY_READ_WORK_TAG]: {},
|
||||
[IpcChannel.ENTITY_READ_WORLD]: {},
|
||||
[IpcChannel.ENTITY_READ_WORLD_NAME]: {},
|
||||
[IpcChannel.ENTITY_READ_WORLD_CHARACTER]: {},
|
||||
[IpcChannel.ENTITY_READ_WORLD_CHARACTER_NAME]: {},
|
||||
};
|
||||
|
||||
function readCollected<T extends IpcChannelEntityRead>(channel: T, identifier: IpcParameter<T>): Promise<IpcAnswer<T>> {
|
||||
if (entityReadPromiseCollector[channel][identifier] === undefined) {
|
||||
// @ts-ignore -- no fucking clue how to type this correctly
|
||||
entityReadPromiseCollector[channel][identifier] = ipcClient.ask<T>(channel, identifier).then((value) => {
|
||||
delete entityReadPromiseCollector[channel][identifier];
|
||||
return value;
|
||||
});
|
||||
}
|
||||
return entityReadPromiseCollector[channel][identifier] as unknown as Promise<IpcAnswer<T>>;
|
||||
}
|
||||
|
||||
export const entityApi = {
|
||||
fetchWork(id: number): Promise<WorkSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_GET_WORK, { id });
|
||||
createAuthor(data: Partial<AuthorSerializedInterface>): Promise<AuthorSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_AUTHOR, data);
|
||||
},
|
||||
createAuthorName(data: Partial<AuthorNameSerializedInterface>): Promise<AuthorNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_AUTHOR_NAME, data);
|
||||
},
|
||||
createAuthorRole(data: Partial<AuthorRoleSerializedInterface>): Promise<AuthorRoleSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_AUTHOR_ROLE, data);
|
||||
},
|
||||
createAuthorRoleName(data: Partial<AuthorRoleNameSerializedInterface>): Promise<AuthorRoleNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_AUTHOR_ROLE_NAME, data);
|
||||
},
|
||||
createCharacterTag(data: Partial<CharacterTagSerializedInterface>): Promise<CharacterTagSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_CHARACTER_TAG, data);
|
||||
},
|
||||
createCollection(data: Partial<CollectionSerializedInterface>): Promise<CollectionSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_COLLECTION, data);
|
||||
},
|
||||
createCollectionName(data: Partial<CollectionNameSerializedInterface>): Promise<CollectionNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_COLLECTION_NAME, data);
|
||||
},
|
||||
createCollectionPart(data: Partial<CollectionPartSerializedInterface>): Promise<CollectionPartSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_COLLECTION_PART, data);
|
||||
},
|
||||
createCopy(data: Partial<CopySerializedInterface>): Promise<CopySerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_COPY, data);
|
||||
},
|
||||
createInteractionTag(data: Partial<InteractionTagSerializedInterface>): Promise<InteractionTagSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_INTERACTION_TAG, data);
|
||||
},
|
||||
createSite(data: Partial<SiteSerializedInterface>): Promise<SiteSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_SITE, data);
|
||||
},
|
||||
createSiteName(data: Partial<SiteNameSerializedInterface>): Promise<SiteNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_SITE_NAME, data);
|
||||
},
|
||||
createSource(data: Partial<SourceSerializedInterface>): Promise<SourceSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_SOURCE, data);
|
||||
},
|
||||
createTag(data: Partial<TagSerializedInterface>): Promise<TagSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_TAG, data);
|
||||
},
|
||||
createTagName(data: Partial<TagNameSerializedInterface>): Promise<TagNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_TAG_NAME, data);
|
||||
},
|
||||
createTransformation(data: Partial<TransformationSerializedInterface>): Promise<TransformationSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_TRANSFORMATION, data);
|
||||
},
|
||||
createTransformationType(
|
||||
data: Partial<TransformationTypeSerializedInterface>,
|
||||
): Promise<TransformationTypeSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_TRANSFORMATION_TYPE, data);
|
||||
},
|
||||
createTransformationTypeName(
|
||||
data: Partial<TransformationTypeNameSerializedInterface>,
|
||||
): Promise<TransformationTypeNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_TRANSFORMATION_TYPE_NAME, data);
|
||||
},
|
||||
createWorkAuthor(data: Partial<WorkAuthorSerializedInterface>): Promise<WorkAuthorSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_WORK_AUTHOR, data);
|
||||
},
|
||||
createWorkCharacter(data: Partial<WorkCharacterSerializedInterface>): Promise<WorkCharacterSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_WORK_CHARACTER, data);
|
||||
},
|
||||
createWorkCharacterName(
|
||||
data: Partial<WorkCharacterNameSerializedInterface>,
|
||||
): Promise<WorkCharacterNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_WORK_CHARACTER_NAME, data);
|
||||
},
|
||||
createWork(data: Partial<WorkSerializedInterface>): Promise<WorkSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_WORK, data);
|
||||
},
|
||||
createWorkName(data: Partial<WorkNameSerializedInterface>): Promise<WorkNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_WORK_NAME, data);
|
||||
},
|
||||
createWorkTag(data: Partial<WorkTagSerializedInterface>): Promise<WorkTagSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_WORK_TAG, data);
|
||||
},
|
||||
createWorld(data: Partial<WorldSerializedInterface>): Promise<WorldSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_WORLD, data);
|
||||
},
|
||||
createWorldName(data: Partial<WorldNameSerializedInterface>): Promise<WorldNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_WORLD_NAME, data);
|
||||
},
|
||||
createWorldCharacter(data: Partial<WorldCharacterSerializedInterface>): Promise<WorldCharacterSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_WORLD_CHARACTER, data);
|
||||
},
|
||||
createWorldCharacterName(
|
||||
data: Partial<WorldCharacterNameSerializedInterface>,
|
||||
): Promise<WorldCharacterNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_CREATE_WORLD_CHARACTER_NAME, data);
|
||||
},
|
||||
|
||||
readAuthor(id: number): Promise<AuthorSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_AUTHOR, id);
|
||||
},
|
||||
readAuthorName(id: number): Promise<AuthorNameSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_AUTHOR_NAME, id);
|
||||
},
|
||||
readAuthorRole(id: number): Promise<AuthorRoleSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_AUTHOR_ROLE, id);
|
||||
},
|
||||
readAuthorRoleName(id: number): Promise<AuthorRoleNameSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_AUTHOR_ROLE_NAME, id);
|
||||
},
|
||||
readCharacterTag(id: number): Promise<CharacterTagSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_CHARACTER_TAG, id);
|
||||
},
|
||||
readCollection(id: number): Promise<CollectionSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_COLLECTION, id);
|
||||
},
|
||||
readCollectionName(id: number): Promise<CollectionNameSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_COLLECTION_NAME, id);
|
||||
},
|
||||
readCollectionPart(id: number): Promise<CollectionPartSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_COLLECTION_PART, id);
|
||||
},
|
||||
readCopy(id: number): Promise<CopySerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_COPY, id);
|
||||
},
|
||||
readInteractionTag(id: number): Promise<InteractionTagSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_INTERACTION_TAG, id);
|
||||
},
|
||||
readLanguage(code: string): Promise<LanguageSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_LANGUAGE, code);
|
||||
},
|
||||
readSite(id: number): Promise<SiteSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_SITE, id);
|
||||
},
|
||||
readSiteName(id: number): Promise<SiteNameSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_SITE_NAME, id);
|
||||
},
|
||||
readSource(id: number): Promise<SourceSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_SOURCE, id);
|
||||
},
|
||||
readTag(id: number): Promise<TagSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_TAG, id);
|
||||
},
|
||||
readTagName(id: number): Promise<TagNameSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_TAG_NAME, id);
|
||||
},
|
||||
readTransformation(id: number): Promise<TransformationSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_TRANSFORMATION, id);
|
||||
},
|
||||
readTransformationType(id: number): Promise<TransformationTypeSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE, id);
|
||||
},
|
||||
readTransformationTypeName(id: number): Promise<TransformationTypeNameSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_TRANSFORMATION_TYPE_NAME, id);
|
||||
},
|
||||
readWorkAuthor(id: number): Promise<WorkAuthorSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_WORK_AUTHOR, id);
|
||||
},
|
||||
readWorkCharacter(id: number): Promise<WorkCharacterSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_WORK_CHARACTER, id);
|
||||
},
|
||||
readWorkCharacterName(id: number): Promise<WorkCharacterNameSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_WORK_CHARACTER_NAME, id);
|
||||
},
|
||||
readWork(id: number): Promise<WorkSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_WORK, id);
|
||||
},
|
||||
readWorkName(id: number): Promise<WorkNameSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_WORK_NAME, id);
|
||||
},
|
||||
readWorkTag(id: number): Promise<WorkTagSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_WORK_TAG, id);
|
||||
},
|
||||
readWorld(id: number): Promise<WorldSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_WORLD, id);
|
||||
},
|
||||
readWorldName(id: number): Promise<WorldNameSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_WORLD_NAME, id);
|
||||
},
|
||||
readWorldCharacter(id: number): Promise<WorldCharacterSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_WORLD_CHARACTER, id);
|
||||
},
|
||||
readWorldCharacterName(id: number): Promise<WorldCharacterNameSerializedInterface> {
|
||||
return readCollected(IpcChannel.ENTITY_READ_WORLD_CHARACTER_NAME, id);
|
||||
},
|
||||
|
||||
updateAuthor(id: number, partial: Partial<AuthorSerializedInterface>): Promise<AuthorSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_AUTHOR, { id, partial });
|
||||
},
|
||||
updateAuthorName(
|
||||
id: number,
|
||||
partial: Partial<AuthorNameSerializedInterface>,
|
||||
): Promise<AuthorNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_AUTHOR_NAME, { id, partial });
|
||||
},
|
||||
updateAuthorRole(
|
||||
id: number,
|
||||
partial: Partial<AuthorRoleSerializedInterface>,
|
||||
): Promise<AuthorRoleSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_AUTHOR_ROLE, { id, partial });
|
||||
},
|
||||
updateAuthorRoleName(
|
||||
id: number,
|
||||
partial: Partial<AuthorRoleNameSerializedInterface>,
|
||||
): Promise<AuthorRoleNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_AUTHOR_ROLE_NAME, { id, partial });
|
||||
},
|
||||
updateCharacterTag(
|
||||
id: number,
|
||||
partial: Partial<CharacterTagSerializedInterface>,
|
||||
): Promise<CharacterTagSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_CHARACTER_TAG, { id, partial });
|
||||
},
|
||||
updateCollection(
|
||||
id: number,
|
||||
partial: Partial<CollectionSerializedInterface>,
|
||||
): Promise<CollectionSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_COLLECTION, { id, partial });
|
||||
},
|
||||
updateCollectionName(
|
||||
id: number,
|
||||
partial: Partial<CollectionNameSerializedInterface>,
|
||||
): Promise<CollectionNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_COLLECTION_NAME, { id, partial });
|
||||
},
|
||||
updateCollectionPart(
|
||||
id: number,
|
||||
partial: Partial<CollectionPartSerializedInterface>,
|
||||
): Promise<CollectionPartSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_COLLECTION_PART, { id, partial });
|
||||
},
|
||||
updateCopy(id: number, partial: Partial<CopySerializedInterface>): Promise<CopySerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_COPY, { id, partial });
|
||||
},
|
||||
updateInteractionTag(
|
||||
id: number,
|
||||
partial: Partial<InteractionTagSerializedInterface>,
|
||||
): Promise<InteractionTagSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_INTERACTION_TAG, { id, partial });
|
||||
},
|
||||
updateSite(id: number, partial: Partial<SiteSerializedInterface>): Promise<SiteSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_SITE, { id, partial });
|
||||
},
|
||||
updateSiteName(id: number, partial: Partial<SiteNameSerializedInterface>): Promise<SiteNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_SITE_NAME, { id, partial });
|
||||
},
|
||||
updateSource(id: number, partial: Partial<SourceSerializedInterface>): Promise<SourceSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_SOURCE, { id, partial });
|
||||
},
|
||||
updateTag(id: number, partial: Partial<TagSerializedInterface>): Promise<TagSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_TAG, { id, partial });
|
||||
},
|
||||
updateTagName(id: number, partial: Partial<TagNameSerializedInterface>): Promise<TagNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_TAG_NAME, { id, partial });
|
||||
},
|
||||
updateTransformation(
|
||||
id: number,
|
||||
partial: Partial<TransformationSerializedInterface>,
|
||||
): Promise<TransformationSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_TRANSFORMATION, { id, partial });
|
||||
},
|
||||
updateTransformationType(
|
||||
id: number,
|
||||
partial: Partial<TransformationTypeSerializedInterface>,
|
||||
): Promise<TransformationTypeSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_TRANSFORMATION_TYPE, { id, partial });
|
||||
},
|
||||
updateTransformationTypeName(
|
||||
id: number,
|
||||
partial: Partial<TransformationTypeNameSerializedInterface>,
|
||||
): Promise<TransformationTypeNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_TRANSFORMATION_TYPE_NAME, { id, partial });
|
||||
},
|
||||
updateWorkAuthor(
|
||||
id: number,
|
||||
partial: Partial<WorkAuthorSerializedInterface>,
|
||||
): Promise<WorkAuthorSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_WORK_AUTHOR, { id, partial });
|
||||
},
|
||||
updateWorkCharacter(
|
||||
id: number,
|
||||
partial: Partial<WorkCharacterSerializedInterface>,
|
||||
): Promise<WorkCharacterSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_WORK_CHARACTER, { id, partial });
|
||||
},
|
||||
updateWorkCharacterName(
|
||||
id: number,
|
||||
partial: Partial<WorkCharacterNameSerializedInterface>,
|
||||
): Promise<WorkCharacterNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_WORK_CHARACTER_NAME, { id, partial });
|
||||
},
|
||||
updateWork(id: number, partial: Partial<WorkSerializedInterface>): Promise<WorkSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_WORK, { id, partial });
|
||||
},
|
||||
updateWorkName(id: number, partial: Partial<WorkNameSerializedInterface>): Promise<WorkNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_WORK_NAME, { id, partial });
|
||||
},
|
||||
updateWorkTag(id: number, partial: Partial<WorkTagSerializedInterface>): Promise<WorkTagSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_WORK_TAG, { id, partial });
|
||||
},
|
||||
updateWorld(id: number, partial: Partial<WorldSerializedInterface>): Promise<WorldSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_WORLD, { id, partial });
|
||||
},
|
||||
updateWorldName(id: number, partial: Partial<WorldNameSerializedInterface>): Promise<WorldNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_WORLD_NAME, { id, partial });
|
||||
},
|
||||
updateWorldCharacter(
|
||||
id: number,
|
||||
partial: Partial<WorldCharacterSerializedInterface>,
|
||||
): Promise<WorldCharacterSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_WORLD_CHARACTER, { id, partial });
|
||||
},
|
||||
updateWorldCharacterName(
|
||||
id: number,
|
||||
partial: Partial<WorldCharacterNameSerializedInterface>,
|
||||
): Promise<WorldCharacterNameSerializedInterface> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_UPDATE_WORLD_CHARACTER_NAME, { id, partial });
|
||||
},
|
||||
|
||||
deleteAuthor(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_AUTHOR, id);
|
||||
},
|
||||
deleteAuthorName(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_AUTHOR_NAME, id);
|
||||
},
|
||||
deleteAuthorRole(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_AUTHOR_ROLE, id);
|
||||
},
|
||||
deleteAuthorRoleName(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_AUTHOR_ROLE_NAME, id);
|
||||
},
|
||||
deleteCharacterTag(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_CHARACTER_TAG, id);
|
||||
},
|
||||
deleteCollection(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_COLLECTION, id);
|
||||
},
|
||||
deleteCollectionName(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_COLLECTION_NAME, id);
|
||||
},
|
||||
deleteCollectionPart(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_COLLECTION_PART, id);
|
||||
},
|
||||
deleteCopy(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_COPY, id);
|
||||
},
|
||||
deleteInteractionTag(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_INTERACTION_TAG, id);
|
||||
},
|
||||
deleteSite(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_SITE, id);
|
||||
},
|
||||
deleteSiteName(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_SITE_NAME, id);
|
||||
},
|
||||
deleteSource(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_SOURCE, id);
|
||||
},
|
||||
deleteTag(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_TAG, id);
|
||||
},
|
||||
deleteTagName(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_TAG_NAME, id);
|
||||
},
|
||||
deleteTransformation(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_TRANSFORMATION, id);
|
||||
},
|
||||
deleteTransformationType(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_TRANSFORMATION_TYPE, id);
|
||||
},
|
||||
deleteTransformationTypeName(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_TRANSFORMATION_TYPE_NAME, id);
|
||||
},
|
||||
deleteWorkAuthor(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_WORK_AUTHOR, id);
|
||||
},
|
||||
deleteWorkCharacter(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_WORK_CHARACTER, id);
|
||||
},
|
||||
deleteWorkCharacterName(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_WORK_CHARACTER_NAME, id);
|
||||
},
|
||||
deleteWork(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_WORK, id);
|
||||
},
|
||||
deleteWorkName(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_WORK_NAME, id);
|
||||
},
|
||||
deleteWorkTag(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_WORK_TAG, id);
|
||||
},
|
||||
deleteWorld(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_WORLD, id);
|
||||
},
|
||||
deleteWorldName(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_WORLD_NAME, id);
|
||||
},
|
||||
deleteWorldCharacter(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_WORLD_CHARACTER, id);
|
||||
},
|
||||
deleteWorldCharacterName(id: number): Promise<void> {
|
||||
return ipcClient.ask(IpcChannel.ENTITY_DELETE_WORLD_CHARACTER_NAME, id);
|
||||
},
|
||||
};
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
export abstract class EventBusEvent extends Event {
|
||||
protected constructor(type: EventType, eventInit?: EventInit) {
|
||||
super(type, eventInit);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue