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_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.handlebars]
|
||||||
|
insert_final_newline = false
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
# except these file types
|
# except these file types
|
||||||
!*.js
|
!*.js
|
||||||
!*.ts
|
!*.ts
|
||||||
|
!*.svelte
|
||||||
|
|
||||||
# but ignore stuff from .gitignore
|
# but ignore stuff from .gitignore
|
||||||
node_modules
|
node_modules
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{
|
{
|
||||||
"root": true,
|
"root": true,
|
||||||
"plugins": ["@typescript-eslint", "import"],
|
"plugins": ["@typescript-eslint", "import", "promise", "svelte3"],
|
||||||
"extends": ["eslint:recommended", "prettier", "plugin:import/recommended"],
|
"extends": ["eslint:recommended", "prettier", "plugin:import/recommended", "plugin:promise/recommended"],
|
||||||
"parserOptions": {
|
"parserOptions": {
|
||||||
"ecmaVersion": 2019,
|
"ecmaVersion": 2020,
|
||||||
"sourceType": "module"
|
"sourceType": "module"
|
||||||
},
|
},
|
||||||
"env": {
|
"env": {
|
||||||
|
@ -91,16 +91,24 @@
|
||||||
"order": "asc"
|
"order": "asc"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
|
||||||
|
"promise/valid-params": "off",
|
||||||
|
"promise/always-return": "off"
|
||||||
},
|
},
|
||||||
"overrides": [
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": ["src/**/*.*"],
|
||||||
|
"rules": {
|
||||||
|
"no-console": "warn"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"files": ["**/*.ts"],
|
"files": ["**/*.ts"],
|
||||||
"extends": [
|
"extends": [
|
||||||
"plugin:@typescript-eslint/eslint-recommended",
|
"plugin:@typescript-eslint/eslint-recommended",
|
||||||
"plugin:@typescript-eslint/recommended",
|
"plugin:@typescript-eslint/recommended",
|
||||||
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
||||||
"prettier/@typescript-eslint",
|
|
||||||
"plugin:import/typescript",
|
"plugin:import/typescript",
|
||||||
"plugin:import/electron"
|
"plugin:import/electron"
|
||||||
],
|
],
|
||||||
|
@ -115,7 +123,6 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"rules": {
|
"rules": {
|
||||||
"no-console": "warn",
|
|
||||||
"no-magic-numbers": "off",
|
"no-magic-numbers": "off",
|
||||||
"no-shadow": "off",
|
"no-shadow": "off",
|
||||||
|
|
||||||
|
@ -183,7 +190,7 @@
|
||||||
{
|
{
|
||||||
"selector": "interface",
|
"selector": "interface",
|
||||||
"format": ["PascalCase"],
|
"format": ["PascalCase"],
|
||||||
"suffix": ["Interface"]
|
"suffix": ["Interface", "Function"]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"@typescript-eslint/explicit-member-accessibility": "warn",
|
"@typescript-eslint/explicit-member-accessibility": "warn",
|
||||||
|
@ -198,7 +205,10 @@
|
||||||
"allowNullish": false
|
"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"
|
"project": "./tsconfig.renderer.json"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"files": ["**/*.svelte"],
|
||||||
|
"processor": "svelte3/svelte3"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"files": ["src/shared/types/**/*"],
|
"files": ["src/shared/types/**/*"],
|
||||||
"rules": {
|
"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
|
# except these file types
|
||||||
!*.html
|
|
||||||
!*.handlebars
|
!*.handlebars
|
||||||
!*.json
|
!*.json
|
||||||
!*.yml
|
!*.yml
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
trailingComma: 'es5'
|
trailingComma: all
|
||||||
tabWidth: 2
|
tabWidth: 2
|
||||||
semi: true
|
semi: true
|
||||||
singleQuote: true
|
singleQuote: true
|
||||||
|
@ -6,13 +6,10 @@ quoteProps: consistent
|
||||||
arrowParens: always
|
arrowParens: always
|
||||||
printWidth: 120
|
printWidth: 120
|
||||||
endOfLine: lf
|
endOfLine: lf
|
||||||
|
|
||||||
|
svelteStrictMode: true
|
||||||
|
|
||||||
overrides:
|
overrides:
|
||||||
- files: '*.svelte'
|
|
||||||
options:
|
|
||||||
parser: html
|
|
||||||
- files: '*.handlebars'
|
|
||||||
options:
|
|
||||||
parser: html
|
|
||||||
- files: '*.drawio'
|
- files: '*.drawio'
|
||||||
options:
|
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. [Formatting and Linters](CONTRIBUTING.md#formatting-and-linters)
|
||||||
1. [Testing](CONTRIBUTING.md#testing)
|
1. [Testing](CONTRIBUTING.md#testing)
|
||||||
1. [Updating](CONTRIBUTING.md#updating-dependencies)
|
1. [Updating](CONTRIBUTING.md#updating-dependencies)
|
||||||
|
1. [Frontend](CONTRIBUTING.md#frontend)
|
||||||
|
1. [Translation](CONTRIBUTING.md#translation)
|
||||||
1. [Design](CONTRIBUTING.md#design)
|
1. [Design](CONTRIBUTING.md#design)
|
||||||
|
|
||||||
## Currently Most Wanted
|
## 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.
|
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
|
## 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).
|
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.
|
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/)
|
- spies, stubs and mocks are provided by [Sinon.JS](https://sinonjs.org/)
|
||||||
- HTTP server mocking is done by [nock](https://github.com/nock/nock)
|
- 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)
|
- 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 `@types/node` package
|
||||||
- the electron version in the `target` field of the [webpack config](scripts/webpack.config.js)
|
- 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 `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
|
## 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",
|
"main": "src/main.js",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "12"
|
"node": "14",
|
||||||
|
"npm": "7"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"prepare": "husky install",
|
||||||
"postinstall": "npm run rebuild",
|
"postinstall": "npm run rebuild",
|
||||||
"postupdate": "npm run rebuild",
|
"postupdate": "npm run rebuild",
|
||||||
"start": "electron . --enable-logging --env=dev",
|
"start": "electron . --enable-logging --env=dev",
|
||||||
|
@ -45,69 +47,68 @@
|
||||||
"prepush": "npm run build && npm run coverage"
|
"prepush": "npm run build && npm run coverage"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"better-sqlite3": "^7.1.2",
|
"better-sqlite3": "^7.4.0",
|
||||||
"electron-squirrel-startup": "^1.0.0",
|
"electron-squirrel-startup": "^1.0.0",
|
||||||
"fs-extra": "^9.1.0",
|
"fs-extra": "^10.0.0",
|
||||||
"inversify": "^5.0.1",
|
"intl-messageformat": "^9.6.14",
|
||||||
|
"inversify": "^5.1.1",
|
||||||
"minimist": "^1.2.5",
|
"minimist": "^1.2.5",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"typeorm": "^0.2.30",
|
"typeorm": "^0.2.32",
|
||||||
"uuid": "^8.3.2"
|
"uuid": "^8.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@electron-forge/cli": "^6.0.0-beta.54",
|
"@electron-forge/cli": "^6.0.0-beta.55",
|
||||||
"@electron-forge/maker-squirrel": "^6.0.0-beta.54",
|
"@electron-forge/maker-squirrel": "^6.0.0-beta.55",
|
||||||
|
"@prettier/plugin-xml": "^0.13.1",
|
||||||
"@types/better-sqlite3": "^5.4.1",
|
"@types/better-sqlite3": "^5.4.1",
|
||||||
"@types/chai": "^4.2.14",
|
"@types/chai": "^4.2.18",
|
||||||
"@types/chai-fs": "^2.0.2",
|
"@types/chai-fs": "^2.0.2",
|
||||||
"@types/deep-equal-in-any-order": "^1.0.1",
|
"@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/glob": "^7.1.3",
|
||||||
"@types/minimist": "^1.2.1",
|
"@types/minimist": "^1.2.1",
|
||||||
"@types/mocha": "^8.2.0",
|
"@types/mocha": "^8.2.2",
|
||||||
"@types/node": "^12.19.15",
|
"@types/node": "^14.17.0",
|
||||||
"@types/sinon": "^9.0.10",
|
"@types/sinon": "^10.0.0",
|
||||||
"@types/uuid": "^8.3.0",
|
"@types/uuid": "^8.3.0",
|
||||||
"@types/webpack": "^4.41.26",
|
"@types/webpack": "^5.28.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^4.14.0",
|
"@typescript-eslint/eslint-plugin": "^4.24.0",
|
||||||
"@typescript-eslint/parser": "^4.14.0",
|
"@typescript-eslint/parser": "^4.24.0",
|
||||||
"chai": "^4.2.0",
|
"chai": "^4.3.4",
|
||||||
"chai-fs": "^2.0.0",
|
"chai-fs": "^2.0.0",
|
||||||
"chokidar": "^3.5.1",
|
"chokidar": "^3.5.1",
|
||||||
"concurrently": "^5.3.0",
|
"concurrently": "^6.1.0",
|
||||||
"deep-equal-in-any-order": "^1.0.28",
|
"deep-equal-in-any-order": "^1.1.4",
|
||||||
"electron": "^10.3.0",
|
"electron": "^13.0.1",
|
||||||
"electron-mocha": "^10.0.0",
|
"electron-mocha": "^10.0.0",
|
||||||
"electron-rebuild": "^2.3.4",
|
"electron-rebuild": "^2.3.5",
|
||||||
"eslint": "^7.18.0",
|
"eslint": "^7.26.0",
|
||||||
"eslint-config-prettier": "^7.2.0",
|
"eslint-config-prettier": "^8.3.0",
|
||||||
"eslint-plugin-import": "^2.22.1",
|
"eslint-plugin-import": "^2.23.2",
|
||||||
"fast-check": "^2.12.0",
|
"eslint-plugin-promise": "^5.1.0",
|
||||||
"glob": "^7.1.6",
|
"eslint-plugin-svelte3": "^3.2.0",
|
||||||
"handlebars": "^4.7.6",
|
"fast-check": "^2.14.0",
|
||||||
"husky": "^4.3.8",
|
"glob": "^7.1.7",
|
||||||
"lodash": "^4.17.20",
|
"handlebars": "^4.7.7",
|
||||||
"mocha": "^8.2.1",
|
"husky": "^6.0.0",
|
||||||
"nock": "^13.0.6",
|
"lodash": "^4.17.21",
|
||||||
|
"mocha": "^8.4.0",
|
||||||
|
"nock": "^13.0.11",
|
||||||
"nyc": "^15.1.0",
|
"nyc": "^15.1.0",
|
||||||
"prettier": "^2.2.1",
|
"prettier": "^2.3.0",
|
||||||
"sinon": "^9.2.4",
|
"prettier-plugin-svelte": "^2.3.0",
|
||||||
"svelte": "^3.31.2",
|
"sinon": "^11.1.1",
|
||||||
"svelte-loader": "^3.0.0",
|
"svelte": "^3.38.2",
|
||||||
"ts-loader": "^8.0.14",
|
"svelte-loader": "^3.1.1",
|
||||||
"typescript": "^4.1.3",
|
"ts-loader": "^9.2.0",
|
||||||
"webpack": "^5.17.0",
|
"typescript": "^4.2.4",
|
||||||
"webpack-cli": "^4.4.0"
|
"webpack": "^5.37.1",
|
||||||
|
"webpack-cli": "^4.7.0"
|
||||||
},
|
},
|
||||||
"repository": "https://git.fuwafuwa.moe/Xymorot/RenaiApp",
|
"repository": "https://git.fuwafuwa.moe/Xymorot/RenaiApp",
|
||||||
"bugs": "https://git.fuwafuwa.moe/Xymorot/RenaiApp/issues",
|
"bugs": "https://git.fuwafuwa.moe/Xymorot/RenaiApp/issues",
|
||||||
"config": {
|
"config": {
|
||||||
"forge": "scripts/forge.config.js"
|
"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') {
|
if (name !== 'Renai') {
|
||||||
throw new TypeError(
|
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 = {
|
module.exports = {
|
||||||
mode: 'production',
|
mode: 'production',
|
||||||
entry: path.resolve(__dirname, '../src/renderer.ts'),
|
entry: path.resolve(__dirname, '../src/renderer.ts'),
|
||||||
target: 'electron10-renderer',
|
target: 'electron13-renderer',
|
||||||
output: {
|
output: {
|
||||||
path: path.resolve(__dirname, '../frontend'),
|
path: path.resolve(__dirname, '../frontend'),
|
||||||
filename: 'bundle.js',
|
filename: 'bundle.js',
|
||||||
|
@ -21,14 +21,9 @@ module.exports = {
|
||||||
configFile: path.resolve('tsconfig.renderer.json'),
|
configFile: path.resolve('tsconfig.renderer.json'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
|
||||||
test: /\.mjs$/,
|
|
||||||
include: /node_modules/,
|
|
||||||
type: 'javascript/auto',
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
resolve: {
|
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 */
|
/* 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 { app } from 'electron';
|
||||||
|
import { container, Service } from './main/core/container';
|
||||||
|
import './main/core/controller';
|
||||||
import { isDev } from './main/core/env';
|
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
|
* 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
|
* https://nodejs.org/api/process.html#process_event_unhandledrejection
|
||||||
*/
|
*/
|
||||||
process.on('unhandledRejection', (reason) => {
|
process.on('unhandledRejection', (reason) => {
|
||||||
const logger: LoggerInterface = container.get('logger');
|
const logger = container.get(Service.LOGGER);
|
||||||
void logger.fatal(`Unhandled Rejection, see ${logger.getExceptionsLogFile()}`);
|
void logger.fatal(`Unhandled Rejection, see ${logger.getExceptionsLogFile()}`);
|
||||||
throw reason;
|
throw reason;
|
||||||
});
|
});
|
||||||
|
|
||||||
process.on('uncaughtException', (error) => {
|
process.on('uncaughtException', (error) => {
|
||||||
const logger: LoggerInterface = container.get('logger');
|
const logger = container.get(Service.LOGGER);
|
||||||
void logger.exception(error);
|
void logger.exception(error);
|
||||||
if (isDev()) {
|
if (isDev()) {
|
||||||
// eslint-disable-next-line no-console -- only for development purposes
|
// eslint-disable-next-line no-console -- only for development purposes
|
||||||
|
@ -26,7 +25,7 @@ process.on('uncaughtException', (error) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
async function createWindow(): Promise<void> {
|
async function createWindow(): Promise<void> {
|
||||||
const appWindowMain: AppWindowInterface = container.get('app-window-main');
|
const appWindowMain = container.get(Service.APP_WINDOW_MAIN);
|
||||||
await appWindowMain.open();
|
await appWindowMain.open();
|
||||||
|
|
||||||
appWindowMain.window?.on('closed', () => {
|
appWindowMain.window?.on('closed', () => {
|
||||||
|
@ -49,7 +48,7 @@ app.on('window-all-closed', () => {
|
||||||
app.on('activate', () => {
|
app.on('activate', () => {
|
||||||
// On OS X it"s common to re-create a window in the app when the
|
// 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.
|
// 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()) {
|
if (appWindowMain.isClosed()) {
|
||||||
void createWindow();
|
void createWindow();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,40 +1,185 @@
|
||||||
import 'reflect-metadata';
|
import 'reflect-metadata';
|
||||||
import { Container, interfaces } from 'inversify';
|
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 { MainAppWindow } from '../modules/app-window/main-app-window';
|
||||||
import { Dialog } from '../modules/dialog/dialog';
|
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 { Logger } from '../modules/logger/logger';
|
||||||
import { NhentaiApi } from '../modules/nhentai/nhentai-api';
|
import { NhentaiApi } from '../modules/nhentai/nhentai-api';
|
||||||
import '../modules/nhentai/nhentai-ipc-controller';
|
|
||||||
import { NhentaiAppWindow } from '../modules/nhentai/nhentai-app-window';
|
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 { 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 { Store } from '../modules/store/store';
|
||||||
import '../modules/entity-api/entity-api-ipc-controller';
|
|
||||||
import BindingToSyntax = interfaces.BindingToSyntax;
|
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 = {
|
export const container = {
|
||||||
original: new Container({ defaultScope: 'Singleton', skipBaseClassChecks: true }),
|
original: new Container({ defaultScope: 'Singleton', skipBaseClassChecks: true }),
|
||||||
bind<T>(key: string): BindingToSyntax<T> {
|
bind<S extends Service>(key: S): BindingToSyntax<ServiceType[S]> {
|
||||||
return this.original.bind<T>(Symbol.for(key));
|
return this.original.bind<ServiceType[S]>(Symbol.for(key));
|
||||||
},
|
},
|
||||||
unbind(key: string): void {
|
unbind(key: Service): void {
|
||||||
return this.original.unbind(Symbol.for(key));
|
return this.original.unbind(Symbol.for(key));
|
||||||
},
|
},
|
||||||
get<T>(key: string): T {
|
get<S extends Service>(key: S): ServiceType[S] {
|
||||||
return this.original.get<T>(Symbol.for(key));
|
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(Service.NHENTAI_APP_WINDOW).to(NhentaiAppWindow);
|
||||||
container.bind('nhentai-api').to(NhentaiApi);
|
container.bind(Service.NHENTAI_API).to(NhentaiApi);
|
||||||
container.bind('nhentai-source-getter').to(NhentaiSourceGetter);
|
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 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 type { BetterSqlite3ConnectionOptions } from 'typeorm/driver/better-sqlite3/BetterSqlite3ConnectionOptions';
|
||||||
import { appPath } from './app-path';
|
import { appPath } from './app-path';
|
||||||
|
|
||||||
|
@ -50,5 +50,16 @@ const connections = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export function getConnection(database: Database): Promise<Connection> {
|
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 { 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));
|
return inversifyInject(Symbol.for(key));
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,6 @@ export const maxValue = Number.MAX_SAFE_INTEGER;
|
||||||
export function PercentCheck(column: string): ClassDecorator & PropertyDecorator {
|
export function PercentCheck(column: string): ClassDecorator & PropertyDecorator {
|
||||||
return Check(
|
return Check(
|
||||||
`${column} needs to be between ${minValue} and ${maxValue}`,
|
`${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)
|
@OneToMany(() => AuthorName, (authorName: AuthorNameEntityInterface) => authorName.entity)
|
||||||
public names!: Promise<AuthorNameEntityInterface[]>;
|
public names!: Promise<AuthorNameEntityInterface[]>;
|
||||||
|
|
||||||
@OneToMany(() => WorkAuthor, (workAuthor: WorkAuthorEntityInterface) => workAuthor.author, {})
|
@OneToMany(() => WorkAuthor, (workAuthor: WorkAuthorEntityInterface) => workAuthor.author)
|
||||||
public workAuthors!: Promise<WorkAuthorEntityInterface[]>;
|
public workAuthors!: Promise<WorkAuthorEntityInterface[]>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,12 @@ import { Work } from './work';
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Language implements LanguageEntityInterface {
|
export class Language implements LanguageEntityInterface {
|
||||||
@PrimaryColumn()
|
@PrimaryColumn()
|
||||||
public code!: string;
|
public readonly code!: LangCode;
|
||||||
|
|
||||||
@ManyToMany(() => Work, (work: WorkEntityInterface) => work.languages)
|
@ManyToMany(() => Work, (work: WorkEntityInterface) => work.languages)
|
||||||
public works!: Promise<WorkEntityInterface[]>;
|
public works!: Promise<WorkEntityInterface[]>;
|
||||||
|
|
||||||
|
public get id(): LangCode {
|
||||||
|
return this.code;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ export class TransformationTypeName implements TransformationTypeNameEntityInter
|
||||||
nullable: false,
|
nullable: false,
|
||||||
onDelete: 'CASCADE',
|
onDelete: 'CASCADE',
|
||||||
onUpdate: 'CASCADE',
|
onUpdate: 'CASCADE',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
public entity!: Promise<TransformationTypeEntityInterface>;
|
public entity!: Promise<TransformationTypeEntityInterface>;
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ export class TransformationType implements TransformationTypeEntityInterface {
|
||||||
@OneToMany(
|
@OneToMany(
|
||||||
() => TransformationTypeName,
|
() => TransformationTypeName,
|
||||||
(transformationTypeName: TransformationTypeNameEntityInterface) => transformationTypeName.entity,
|
(transformationTypeName: TransformationTypeNameEntityInterface) => transformationTypeName.entity,
|
||||||
{}
|
|
||||||
)
|
)
|
||||||
public names!: Promise<TransformationTypeNameEntityInterface[]>;
|
public names!: Promise<TransformationTypeNameEntityInterface[]>;
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ export class Transformation implements TransformationEntityInterface {
|
||||||
nullable: false,
|
nullable: false,
|
||||||
onDelete: 'RESTRICT',
|
onDelete: 'RESTRICT',
|
||||||
onUpdate: 'CASCADE',
|
onUpdate: 'CASCADE',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
public type!: Promise<TransformationTypeEntityInterface>;
|
public type!: Promise<TransformationTypeEntityInterface>;
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ export class Work implements WorkEntityInterface {
|
||||||
@OneToMany(() => WorkName, (workName: WorkNameEntityInterface) => workName.entity)
|
@OneToMany(() => WorkName, (workName: WorkNameEntityInterface) => workName.entity)
|
||||||
public names!: Promise<WorkNameEntityInterface[]>;
|
public names!: Promise<WorkNameEntityInterface[]>;
|
||||||
|
|
||||||
@OneToMany(() => Copy, (copy: CopyEntityInterface) => copy.original, {})
|
@OneToMany(() => Copy, (copy: CopyEntityInterface) => copy.original)
|
||||||
public copies!: Promise<CopyEntityInterface[]>;
|
public copies!: Promise<CopyEntityInterface[]>;
|
||||||
|
|
||||||
@OneToMany(() => Transformation, (transformation: TransformationEntityInterface) => transformation.byWork)
|
@OneToMany(() => Transformation, (transformation: TransformationEntityInterface) => transformation.byWork)
|
||||||
|
|
|
@ -16,7 +16,7 @@ export class WorldCharacter implements WorldCharacterEntityInterface {
|
||||||
|
|
||||||
@OneToMany(
|
@OneToMany(
|
||||||
() => WorldCharacterName,
|
() => WorldCharacterName,
|
||||||
(worldCharacterName: WorldCharacterNameEntityInterface) => worldCharacterName.entity
|
(worldCharacterName: WorldCharacterNameEntityInterface) => worldCharacterName.entity,
|
||||||
)
|
)
|
||||||
public names!: Promise<WorldCharacterNameEntityInterface[]>;
|
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.HIRI_MOTU}')`);
|
||||||
await queryRunner.query(`INSERT INTO language VALUES('${LangCode.HUNGARIAN}')`);
|
await queryRunner.query(`INSERT INTO language VALUES('${LangCode.HUNGARIAN}')`);
|
||||||
await queryRunner.query(
|
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.INDONESIAN}')`);
|
||||||
await queryRunner.query(`INSERT INTO language VALUES('${LangCode.INTERLINGUE_OCCIDENTAL}')`);
|
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.OCCITAN}')`);
|
||||||
await queryRunner.query(`INSERT INTO language VALUES('${LangCode.OJIBWA}')`);
|
await queryRunner.query(`INSERT INTO language VALUES('${LangCode.OJIBWA}')`);
|
||||||
await queryRunner.query(
|
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.OROMO}')`);
|
||||||
await queryRunner.query(`INSERT INTO language VALUES('${LangCode.ORIYA}')`);
|
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> {
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
await queryRunner.query(
|
await queryRunner.query(
|
||||||
`CREATE TABLE "store_value" ("key" varchar PRIMARY KEY NOT NULL, "value" text NOT NULL)`,
|
`CREATE TABLE "store_value" ("key" varchar PRIMARY KEY NOT NULL, "value" text NOT NULL)`,
|
||||||
undefined
|
undefined,
|
||||||
);
|
);
|
||||||
await queryRunner.query(
|
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)`,
|
`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(() => {
|
.catch(() => {
|
||||||
void this.logger.warning(
|
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);
|
resolve(undefined);
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,7 @@ export abstract class FileAppWindow extends AppWindow {
|
||||||
logger: LoggerInterface,
|
logger: LoggerInterface,
|
||||||
uri: string,
|
uri: string,
|
||||||
options: BrowserWindowConstructorOptions = {},
|
options: BrowserWindowConstructorOptions = {},
|
||||||
loadOptions: LoadFileOptions = {}
|
loadOptions: LoadFileOptions = {},
|
||||||
) {
|
) {
|
||||||
super(logger, uri, options);
|
super(logger, uri, options);
|
||||||
this.loadOptions = loadOptions;
|
this.loadOptions = loadOptions;
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import { injectable } from 'inversify';
|
import { injectable } from 'inversify';
|
||||||
|
import { Service } from '../../core/container';
|
||||||
import { inject } from '../../core/inject';
|
import { inject } from '../../core/inject';
|
||||||
import { FileAppWindow } from './file-app-window';
|
import { FileAppWindow } from './file-app-window';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class MainAppWindow extends FileAppWindow {
|
export class MainAppWindow extends FileAppWindow {
|
||||||
public constructor(@inject('logger') logger: LoggerInterface) {
|
public constructor(@inject(Service.LOGGER) logger: LoggerInterface) {
|
||||||
super(logger, 'frontend/index.html', {
|
super(logger, 'frontend/index.html', {
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
|
contextIsolation: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ export abstract class SiteAppWindow extends UrlAppWindow implements SiteAppWindo
|
||||||
logger: LoggerInterface,
|
logger: LoggerInterface,
|
||||||
uri: string,
|
uri: string,
|
||||||
options: BrowserWindowConstructorOptions = {},
|
options: BrowserWindowConstructorOptions = {},
|
||||||
loadOptions: LoadURLOptions = {}
|
loadOptions: LoadURLOptions = {},
|
||||||
) {
|
) {
|
||||||
super(logger, uri, options, loadOptions);
|
super(logger, uri, options, loadOptions);
|
||||||
this.windowLock = new SimpleMutex();
|
this.windowLock = new SimpleMutex();
|
||||||
|
|
|
@ -16,6 +16,6 @@ interface UrlAppWindowInterface extends AppWindowInterface {
|
||||||
loadUrlSafe(
|
loadUrlSafe(
|
||||||
url: string,
|
url: string,
|
||||||
readyCheck?: (webContents: WebContents) => Promise<boolean>,
|
readyCheck?: (webContents: WebContents) => Promise<boolean>,
|
||||||
options?: LoadURLOptions
|
options?: LoadURLOptions,
|
||||||
): Promise<void>;
|
): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ export abstract class UrlAppWindow extends AppWindow implements UrlAppWindowInte
|
||||||
logger: LoggerInterface,
|
logger: LoggerInterface,
|
||||||
uri: string,
|
uri: string,
|
||||||
options: BrowserWindowConstructorOptions = {},
|
options: BrowserWindowConstructorOptions = {},
|
||||||
loadOptions: LoadURLOptions = {}
|
loadOptions: LoadURLOptions = {},
|
||||||
) {
|
) {
|
||||||
super(logger, uri, {
|
super(logger, uri, {
|
||||||
...options,
|
...options,
|
||||||
|
@ -78,36 +78,38 @@ export abstract class UrlAppWindow extends AppWindow implements UrlAppWindowInte
|
||||||
public async loadUrlSafe(
|
public async loadUrlSafe(
|
||||||
url: string,
|
url: string,
|
||||||
readyCheck?: (webContents: WebContents) => Promise<boolean>,
|
readyCheck?: (webContents: WebContents) => Promise<boolean>,
|
||||||
options?: LoadURLOptions
|
options?: LoadURLOptions,
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
return this.loadWait.then(async () => {
|
await this.loadWait;
|
||||||
let failedLoad = true;
|
let failedLoad = true;
|
||||||
while (failedLoad) {
|
while (failedLoad) {
|
||||||
await this.loadUrl(url, options).then((httpResponseCode) => {
|
const httpResponseCode = await this.loadUrl(url, options);
|
||||||
failedLoad = HttpCode.BAD_REQUEST <= httpResponseCode;
|
failedLoad = HttpCode.BAD_REQUEST <= httpResponseCode;
|
||||||
if (HttpCode.TOO_MANY_REQUESTS === httpResponseCode) {
|
switch (httpResponseCode) {
|
||||||
// go slower
|
case HttpCode.NOT_FOUND:
|
||||||
this.loadWaitTime += this.loadWaitTimeStep;
|
throw new Error(`Loading ${url} gave the unrecoverable HTTP status code ${httpResponseCode}.`);
|
||||||
// but go faster again after a time
|
case HttpCode.TOO_MANY_REQUESTS:
|
||||||
clearTimeout(this.loadWaitTimeStepResetTimeout);
|
// go slower
|
||||||
this.loadWaitTimeStepResetTimeout = setTimeout(() => {
|
this.loadWaitTime += this.loadWaitTimeStep;
|
||||||
this.loadWaitTime = 0;
|
// but go faster again after a time
|
||||||
}, this.loadWaitTimeResetTimeoutTime);
|
clearTimeout(this.loadWaitTimeStepResetTimeout);
|
||||||
}
|
this.loadWaitTimeStepResetTimeout = setTimeout(() => {
|
||||||
});
|
this.loadWaitTime = 0;
|
||||||
if (failedLoad) {
|
}, this.loadWaitTimeResetTimeoutTime);
|
||||||
await promisify(setTimeout)(this.waitInterval);
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.loadWait = promisify(setTimeout)(this.loadWaitTime);
|
if (failedLoad) {
|
||||||
if (readyCheck) {
|
await promisify(setTimeout)(this.waitInterval);
|
||||||
let isReady = await readyCheck(this.getWindow().webContents);
|
|
||||||
do {
|
|
||||||
await promisify(setTimeout)(Milliseconds.TEN);
|
|
||||||
isReady = await readyCheck(this.getWindow().webContents);
|
|
||||||
} while (!isReady);
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
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 (
|
const onDidNavigate: (event: Event, url: string, httpResponseCode: number) => void = async (
|
||||||
event,
|
event,
|
||||||
navigationUrl,
|
navigationUrl,
|
||||||
httpResponseCode
|
httpResponseCode,
|
||||||
) => {
|
) => {
|
||||||
if (!(await isCloudFlareSite(this.getWindow().webContents))) {
|
if (!(await isCloudFlareSite(this.getWindow().webContents))) {
|
||||||
this.getWindow().webContents.removeListener('did-navigate', onDidNavigate);
|
this.getWindow().webContents.removeListener('did-navigate', onDidNavigate);
|
||||||
|
|
|
@ -15,12 +15,12 @@ export const cloudflareSiteCsp: ContentSecurityPolicy = {
|
||||||
|
|
||||||
export function humanInteractionRequired(webContents: WebContents): Promise<boolean> {
|
export function humanInteractionRequired(webContents: WebContents): Promise<boolean> {
|
||||||
return webContents.executeJavaScript(
|
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>;
|
) as Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isCloudFlareSite(webContents: WebContents): Promise<boolean> {
|
export function isCloudFlareSite(webContents: WebContents): Promise<boolean> {
|
||||||
return webContents.executeJavaScript(
|
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>;
|
) as Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
export function dateObjectToString(date: Date): string {
|
export function dateObjectToString(date: Date): string {
|
||||||
return `${date.getUTCFullYear()}-${`${date.getUTCMonth()}`.padStart(2, '0')}-${`${date.getUTCDate()}`.padStart(
|
return `${date.getUTCFullYear()}-${`${date.getUTCMonth()}`.padStart(2, '0')}-${`${date.getUTCDate()}`.padStart(
|
||||||
2,
|
2,
|
||||||
'0'
|
'0',
|
||||||
)}`;
|
)}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,14 @@
|
||||||
import { dialog, OpenDialogOptions } from 'electron';
|
import { dialog, OpenDialogOptions } from 'electron';
|
||||||
import { injectable } from 'inversify';
|
import { injectable } from 'inversify';
|
||||||
import { inject } from '../../core/inject';
|
import { t } from '../../../shared/services/translation/t';
|
||||||
import type { DialogInterface } from './dialog-interface';
|
import type { DialogInterface } from './dialog-interface';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class Dialog implements DialogInterface {
|
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> {
|
public selectFolder(options: OpenDialogOptions): ReturnType<typeof dialog.showOpenDialog> {
|
||||||
return dialog.showOpenDialog({
|
return dialog.showOpenDialog({
|
||||||
...{
|
...{
|
||||||
title: this.translator.t('select a folder'),
|
title: t('imperatives.dialog.select_folder'),
|
||||||
},
|
},
|
||||||
...options,
|
...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 './create-controller';
|
||||||
import { Database, getConnection } from '../../core/database';
|
import './read-controller';
|
||||||
import { Work } from '../../entities/library/work';
|
import './update-controller';
|
||||||
import { answer } from '../ipc/annotations/answer';
|
import './delete-controller';
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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 { ipcMain, IpcMainInvokeEvent } from 'electron';
|
||||||
import IpcMainEvent = Electron.IpcMainEvent;
|
import { container, Service } from '../../core/container';
|
||||||
|
|
||||||
export function registerHandler(channel: IpcChannel, controller: IpcController, handler: string): void {
|
const logger = container.get(Service.LOGGER);
|
||||||
ipcMain.on(channel, (event: IpcMainEvent, payload: IpcPayload) => {
|
|
||||||
((controller.get() as unknown) as { [x: string]: IpcHandler })
|
export const ipcServer: IpcServer = {
|
||||||
[handler](payload.data)
|
answer<T extends IpcChannel>(channel: T, answerer: IpcHandler<IpcParameter<T>, IpcAnswer<T>>) {
|
||||||
.then((result: unknown) => {
|
const listener = (data: IpcParameter<T>): Promise<IpcAnswer<T>> =>
|
||||||
const response: IpcResponse = {
|
answerer(data).catch((reason: Error) => {
|
||||||
id: payload.id,
|
void logger.exception(reason);
|
||||||
success: true,
|
throw reason;
|
||||||
data: result,
|
|
||||||
};
|
|
||||||
event.reply(channel, response);
|
|
||||||
})
|
|
||||||
.catch((reason: Error) => {
|
|
||||||
const response: IpcResponse = {
|
|
||||||
id: payload.id,
|
|
||||||
success: false,
|
|
||||||
error: reason.message,
|
|
||||||
};
|
|
||||||
event.reply(channel, response);
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
ipcMain.handle(channel, (event: IpcMainInvokeEvent, data: IpcParameter<T>) => listener(data));
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { createInterface, Interface } from 'readline';
|
import { createInterface, Interface } from 'readline';
|
||||||
import chai, { expect } from 'chai';
|
import chai, { expect } from 'chai';
|
||||||
import 'mocha';
|
|
||||||
import chaiFs from 'chai-fs';
|
import chaiFs from 'chai-fs';
|
||||||
import fc from 'fast-check';
|
import fc from 'fast-check';
|
||||||
import fs from 'fs-extra';
|
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 { setDev } from '../../core/env.spec';
|
||||||
import { LogLevel } from './log-level';
|
import { LogLevel } from './log-level';
|
||||||
|
|
||||||
|
@ -41,20 +41,20 @@ describe('Logger Service', () => {
|
||||||
const logLevelNumberArbitrary = fc.constantFrom(...logLevelsNumber);
|
const logLevelNumberArbitrary = fc.constantFrom(...logLevelsNumber);
|
||||||
|
|
||||||
it('creates log files', () => {
|
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.getLogFile()).path('log file is not created');
|
||||||
expect(logger.getExceptionsLogFile()).path('exception log file is not created');
|
expect(logger.getExceptionsLogFile()).path('exception log file is not created');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('logs exceptions', async () => {
|
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'));
|
await logger.exception(new Error('this is an error'));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("default log file doesn't get bigger than 50KB @slow", async () => {
|
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 prevLogFileSize = (await fs.stat(logger.getLogFile())).size;
|
||||||
let minNumberOfLines = maxLogSize;
|
let minNumberOfLines = maxLogSize;
|
||||||
|
@ -75,7 +75,7 @@ describe('Logger Service', () => {
|
||||||
}).timeout(15000);
|
}).timeout(15000);
|
||||||
|
|
||||||
it("exception log file doesn't get bigger than 50KB @slow", async () => {
|
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 prevLogFileSize = (await fs.stat(logger.getExceptionsLogFile())).size;
|
||||||
let minNumberOfLines = maxLogSize;
|
let minNumberOfLines = maxLogSize;
|
||||||
|
@ -96,7 +96,7 @@ describe('Logger Service', () => {
|
||||||
}).timeout(15000);
|
}).timeout(15000);
|
||||||
|
|
||||||
it('logs different levels directly', () => {
|
it('logs different levels directly', () => {
|
||||||
const logger: LoggerInterface = container.get('logger');
|
const logger = container.get(Service.LOGGER);
|
||||||
|
|
||||||
return fc.assert(
|
return fc.assert(
|
||||||
fc.asyncProperty(logLevelArbitrary as LogLevelArbitrary, fc.string(), async (logLevel, message) => {
|
fc.asyncProperty(logLevelArbitrary as LogLevelArbitrary, fc.string(), async (logLevel, message) => {
|
||||||
|
@ -107,12 +107,12 @@ describe('Logger Service', () => {
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
numRuns: 50,
|
numRuns: 50,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('logs different levels indirectly via the generic log function', () => {
|
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(
|
return fc.assert(
|
||||||
fc.asyncProperty(logLevelNumberArbitrary, fc.string(), async (logLevelNumber, message) => {
|
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(message, 'the log line does not contain the message');
|
||||||
expect(lastLine).contains(
|
expect(lastLine).contains(
|
||||||
logLevels[logLevelNumber],
|
logLevels[logLevelNumber],
|
||||||
`the log line does not contain the '${logLevels[logLevelNumber]}' keyword`
|
`the log line does not contain the '${logLevels[logLevelNumber]}' keyword`,
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
numRuns: 50,
|
numRuns: 50,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('logs debug only in dev mode', async () => {
|
it('logs debug only in dev mode', async () => {
|
||||||
const logger: LoggerInterface = container.get('logger');
|
const logger = container.get(Service.LOGGER);
|
||||||
|
|
||||||
setDev();
|
setDev();
|
||||||
await logger.debug('this is a development message');
|
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');
|
await logger.debug('this is a second development message, should not be here');
|
||||||
expect(lastLine).not.contain(
|
expect(lastLine).not.contain(
|
||||||
'this is a second development message, should not be here',
|
'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(
|
return Logger.writeStream(
|
||||||
Readable.from(
|
Readable.from(
|
||||||
`[${new Date().toISOString()}] ${(error as NodeJS.ErrnoException).code ?? 'Error'}: ${error.message}
|
`[${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 acquireOne = mutex.acquire();
|
||||||
const acquireTwo = mutex.acquire();
|
const acquireTwo = mutex.acquire();
|
||||||
const acquireThree = mutex.acquire();
|
const acquireThree = mutex.acquire();
|
||||||
void acquireOne.then((release) =>
|
void acquireOne.then(async (release) => {
|
||||||
useResource().then(() => {
|
await useResource();
|
||||||
release();
|
release();
|
||||||
})
|
});
|
||||||
);
|
void acquireTwo.then(async (release) => {
|
||||||
void acquireTwo.then((release) =>
|
await useResource();
|
||||||
useResource().then(() => {
|
release();
|
||||||
release();
|
});
|
||||||
})
|
return acquireThree.then(async (release) => {
|
||||||
);
|
await useResource();
|
||||||
return acquireThree.then((release) =>
|
release();
|
||||||
useResource().then(() => {
|
});
|
||||||
release();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('executes consumers in the right order', async () => {
|
it('executes consumers in the right order', async () => {
|
||||||
|
@ -60,21 +57,18 @@ describe('Simple Mutex', () => {
|
||||||
const acquireOne = mutex.acquire();
|
const acquireOne = mutex.acquire();
|
||||||
const acquireTwo = mutex.acquire();
|
const acquireTwo = mutex.acquire();
|
||||||
const acquireThree = mutex.acquire();
|
const acquireThree = mutex.acquire();
|
||||||
void acquireOne.then((release) =>
|
void acquireOne.then(async (release) => {
|
||||||
useResource(1).then(() => {
|
await useResource(1);
|
||||||
release();
|
release();
|
||||||
})
|
});
|
||||||
);
|
void acquireTwo.then(async (release) => {
|
||||||
void acquireTwo.then((release) =>
|
await useResource(2);
|
||||||
useResource(2).then(() => {
|
release();
|
||||||
release();
|
});
|
||||||
})
|
return acquireThree.then(async (release) => {
|
||||||
);
|
await useResource(3);
|
||||||
return acquireThree.then((release) =>
|
release();
|
||||||
useResource(3).then(() => {
|
});
|
||||||
release();
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('correctly informs if it is currently locked', async () => {
|
it('correctly informs if it is currently locked', async () => {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { injectable } from 'inversify';
|
import { injectable } from 'inversify';
|
||||||
|
import { Service } from '../../core/container';
|
||||||
import { inject } from '../../core/inject';
|
import { inject } from '../../core/inject';
|
||||||
import type { NhentaiAppWindowInterface } from './nhentai-app-window-interface';
|
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 {
|
export class NhentaiApi implements NhentaiApiInterface {
|
||||||
private readonly appWindow: NhentaiAppWindowInterface;
|
private readonly appWindow: NhentaiAppWindowInterface;
|
||||||
|
|
||||||
public constructor(@inject('nhentai-app-window') appWindow: NhentaiAppWindowInterface) {
|
public constructor(@inject(Service.NHENTAI_APP_WINDOW) appWindow: NhentaiAppWindowInterface) {
|
||||||
this.appWindow = appWindow;
|
this.appWindow = appWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,26 @@
|
||||||
import chai, { expect } from 'chai';
|
import chai, { expect } from 'chai';
|
||||||
import deepEqualInAnyOrder from 'deep-equal-in-any-order';
|
import deepEqualInAnyOrder from 'deep-equal-in-any-order';
|
||||||
import { describe, it, before } from 'mocha';
|
import { before, describe, it } from 'mocha';
|
||||||
import { container } from '../../core/container';
|
import { container, Service } from '../../core/container';
|
||||||
import { LoggerMock } from '../logger/logger.mock';
|
import { LoggerMock } from '../logger/logger.mock';
|
||||||
import type { NhentaiAppWindowInterface } from './nhentai-app-window-interface';
|
|
||||||
|
|
||||||
chai.use(deepEqualInAnyOrder);
|
chai.use(deepEqualInAnyOrder);
|
||||||
|
|
||||||
describe('Nhentai App Window', () => {
|
describe('Nhentai App Window', () => {
|
||||||
before(() => {
|
before(() => {
|
||||||
container.unbind('logger');
|
container.unbind(Service.LOGGER);
|
||||||
container.bind('logger').to(LoggerMock);
|
container.bind(Service.LOGGER).to(LoggerMock);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('gets the gallery information from an identifier @slow', async () => {
|
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 = {
|
let expectedGallery: Nhentai.Gallery = {
|
||||||
url: 'https://nhentai.net/g/117300/',
|
url: 'https://nhentai.net/g/107386/',
|
||||||
title: {
|
title: {
|
||||||
pre: '[Homunculus]',
|
pre: '[Homunculus]',
|
||||||
main: 'Renai Sample',
|
main: 'Renai Sample + Bonus Booklets',
|
||||||
post: '[English] [Decensored]',
|
post: '[English] [Tankoubon version]',
|
||||||
},
|
},
|
||||||
artists: ['homunculus'],
|
artists: ['homunculus'],
|
||||||
groups: [],
|
groups: [],
|
||||||
|
@ -32,22 +31,27 @@ describe('Nhentai App Window', () => {
|
||||||
'stockings',
|
'stockings',
|
||||||
'schoolgirl uniform',
|
'schoolgirl uniform',
|
||||||
'glasses',
|
'glasses',
|
||||||
'nakadashi',
|
|
||||||
'incest',
|
'incest',
|
||||||
'tankoubon',
|
'tankoubon',
|
||||||
'defloration',
|
'defloration',
|
||||||
|
'milf',
|
||||||
'swimsuit',
|
'swimsuit',
|
||||||
'ffm threesome',
|
'ffm threesome',
|
||||||
|
'impregnation',
|
||||||
'sister',
|
'sister',
|
||||||
'schoolboy uniform',
|
'schoolboy uniform',
|
||||||
'bikini',
|
'bikini',
|
||||||
'uncensored',
|
'teacher',
|
||||||
'small breasts',
|
'apron',
|
||||||
|
'inseki',
|
||||||
|
'leg lock',
|
||||||
|
'cousin',
|
||||||
|
'niece',
|
||||||
],
|
],
|
||||||
languages: ['english', 'translated'],
|
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');
|
expect(gallery).deep.equalInAnyOrder(expectedGallery, 'Renai Sample is not got correctly');
|
||||||
|
|
||||||
expectedGallery = {
|
expectedGallery = {
|
||||||
|
|
|
@ -5,37 +5,38 @@ import { Readable } from 'stream';
|
||||||
import { URL } from 'url';
|
import { URL } from 'url';
|
||||||
import { createReadStream, remove } from 'fs-extra';
|
import { createReadStream, remove } from 'fs-extra';
|
||||||
import { injectable } from 'inversify';
|
import { injectable } from 'inversify';
|
||||||
|
import { Service } from '../../core/container';
|
||||||
import { inject } from '../../core/inject';
|
import { inject } from '../../core/inject';
|
||||||
import { CloudflareSiteAppWindow } from '../cloudflare/cloudflare-site-app-window';
|
import { CloudflareSiteAppWindow } from '../cloudflare/cloudflare-site-app-window';
|
||||||
import { mergeContentSecurityPolicy } from '../session/session-util';
|
import { mergeContentSecurityPolicy } from '../session/session-util';
|
||||||
import type { NhentaiAppWindowInterface } from './nhentai-app-window-interface';
|
import type { NhentaiAppWindowInterface } from './nhentai-app-window-interface';
|
||||||
import {
|
import {
|
||||||
url as nhentaiUrl,
|
|
||||||
hostname as nhentaiHostname,
|
|
||||||
paths as nhentaiPaths,
|
|
||||||
getFavoritePageUrl,
|
|
||||||
nextFavoritePageSelector,
|
|
||||||
coverLinkSelector,
|
coverLinkSelector,
|
||||||
downloadLinkId,
|
downloadLinkId,
|
||||||
getGalleryId,
|
favoritePageIsReady,
|
||||||
|
galleryPageIsReady,
|
||||||
getBookUrl,
|
getBookUrl,
|
||||||
|
getFavoritePageUrl,
|
||||||
|
getGalleryId,
|
||||||
|
hostname as nhentaiHostname,
|
||||||
|
labeledTagContainerSelector,
|
||||||
|
loginPageIsReady,
|
||||||
|
mainTitleSelector,
|
||||||
|
nextFavoritePageSelector,
|
||||||
|
pageIsReady,
|
||||||
|
paths as nhentaiPaths,
|
||||||
|
postTitleSelector,
|
||||||
preTitleSelector,
|
preTitleSelector,
|
||||||
tagLabelArtists,
|
tagLabelArtists,
|
||||||
labeledTagContainerSelector,
|
tagLabelCharacters,
|
||||||
|
tagLabelGroups,
|
||||||
|
tagLabelLanguages,
|
||||||
|
tagLabelParodies,
|
||||||
|
tagLabelTags,
|
||||||
tagNameSelector,
|
tagNameSelector,
|
||||||
tagSelector,
|
tagSelector,
|
||||||
tagLabelGroups,
|
|
||||||
tagLabelParodies,
|
|
||||||
tagLabelCharacters,
|
|
||||||
tagLabelTags,
|
|
||||||
mainTitleSelector,
|
|
||||||
postTitleSelector,
|
|
||||||
galleryPageIsReady,
|
|
||||||
loginPageIsReady,
|
|
||||||
favoritePageIsReady,
|
|
||||||
pageIsReady,
|
|
||||||
timeSelector,
|
timeSelector,
|
||||||
tagLabelLanguages,
|
url as nhentaiUrl,
|
||||||
} from './nhentai-util';
|
} from './nhentai-util';
|
||||||
|
|
||||||
const waitInterval = 2000;
|
const waitInterval = 2000;
|
||||||
|
@ -44,7 +45,7 @@ const waitInterval = 2000;
|
||||||
export class NhentaiAppWindow extends CloudflareSiteAppWindow implements NhentaiAppWindowInterface {
|
export class NhentaiAppWindow extends CloudflareSiteAppWindow implements NhentaiAppWindowInterface {
|
||||||
protected readyCheck = pageIsReady;
|
protected readyCheck = pageIsReady;
|
||||||
|
|
||||||
public constructor(@inject('logger') logger: LoggerInterface) {
|
public constructor(@inject(Service.LOGGER) logger: LoggerInterface) {
|
||||||
super(logger, nhentaiUrl);
|
super(logger, nhentaiUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,8 +65,8 @@ export class NhentaiAppWindow extends CloudflareSiteAppWindow implements Nhentai
|
||||||
for await (const wc of this.getFavoritePageWebContentsGenerator()) {
|
for await (const wc of this.getFavoritePageWebContentsGenerator()) {
|
||||||
bookUrls.push(
|
bookUrls.push(
|
||||||
...((await wc.executeJavaScript(
|
...((await wc.executeJavaScript(
|
||||||
`Array.from(document.querySelectorAll('${coverLinkSelector}')).map((el) => el.href)`
|
`Array.from(document.querySelectorAll('${coverLinkSelector}')).map((el) => el.href)`,
|
||||||
)) as string[])
|
)) as string[]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +81,7 @@ export class NhentaiAppWindow extends CloudflareSiteAppWindow implements Nhentai
|
||||||
})(this),
|
})(this),
|
||||||
{
|
{
|
||||||
objectMode: true,
|
objectMode: true,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
readable.once('end', () => {
|
readable.once('end', () => {
|
||||||
this.close();
|
this.close();
|
||||||
|
@ -198,7 +199,7 @@ export class NhentaiAppWindow extends CloudflareSiteAppWindow implements Nhentai
|
||||||
.webContents.executeJavaScript(
|
.webContents.executeJavaScript(
|
||||||
`fetch('${
|
`fetch('${
|
||||||
nhentaiUrl + nhentaiPaths.favorites
|
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);
|
.then((status: number) => status === HttpCode.OK);
|
||||||
}
|
}
|
||||||
|
@ -225,11 +226,11 @@ export class NhentaiAppWindow extends CloudflareSiteAppWindow implements Nhentai
|
||||||
while (true) {
|
while (true) {
|
||||||
yield this.getWindow().webContents;
|
yield this.getWindow().webContents;
|
||||||
const hasNextPage = (await this.getWindow().webContents.executeJavaScript(
|
const hasNextPage = (await this.getWindow().webContents.executeJavaScript(
|
||||||
`!!document.querySelector('${nextFavoritePageSelector}')`
|
`!!document.querySelector('${nextFavoritePageSelector}')`,
|
||||||
)) as boolean;
|
)) as boolean;
|
||||||
if (hasNextPage) {
|
if (hasNextPage) {
|
||||||
const nextPageHref = (await this.getWindow().webContents.executeJavaScript(
|
const nextPageHref = (await this.getWindow().webContents.executeJavaScript(
|
||||||
`document.querySelector('${nextFavoritePageSelector}').href`
|
`document.querySelector('${nextFavoritePageSelector}').href`,
|
||||||
)) as string;
|
)) as string;
|
||||||
await this.loadFavoritesPageSafe(nextPageHref);
|
await this.loadFavoritesPageSafe(nextPageHref);
|
||||||
} else {
|
} else {
|
||||||
|
@ -245,7 +246,7 @@ export class NhentaiAppWindow extends CloudflareSiteAppWindow implements Nhentai
|
||||||
const filePath = path.resolve(os.tmpdir(), fileName);
|
const filePath = path.resolve(os.tmpdir(), fileName);
|
||||||
await this.loadGalleryPageSafe(bookUrl);
|
await this.loadGalleryPageSafe(bookUrl);
|
||||||
const downloadLink: string = (await this.getWindow().webContents.executeJavaScript(
|
const downloadLink: string = (await this.getWindow().webContents.executeJavaScript(
|
||||||
`document.getElementById('${downloadLinkId}').href`
|
`document.getElementById('${downloadLinkId}').href`,
|
||||||
)) as string;
|
)) as string;
|
||||||
await this.downloadUrlSafe(downloadLink, filePath);
|
await this.downloadUrlSafe(downloadLink, filePath);
|
||||||
|
|
||||||
|
@ -283,7 +284,7 @@ export class NhentaiAppWindow extends CloudflareSiteAppWindow implements Nhentai
|
||||||
(tagContainer) => Array.from(tagContainer.querySelectorAll('${tagSelector}'))
|
(tagContainer) => Array.from(tagContainer.querySelectorAll('${tagSelector}'))
|
||||||
).flat().map(
|
).flat().map(
|
||||||
(tagElement) => tagElement.querySelector('${tagNameSelector}').innerHTML
|
(tagElement) => tagElement.querySelector('${tagNameSelector}').innerHTML
|
||||||
)`
|
)`,
|
||||||
) as Promise<string[]>;
|
) as Promise<string[]>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,65 +1,40 @@
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { createWriteStream } from 'fs-extra';
|
import { createWriteStream } from 'fs-extra';
|
||||||
import { container } from '../../core/container';
|
import { t } from '../../../shared/services/translation/t';
|
||||||
import type { DialogInterface } from '../dialog/dialog-interface';
|
import { container, Service } from '../../core/container';
|
||||||
import { answer } from '../ipc/annotations/answer';
|
import { ipcServer } from '../ipc/ipc-server';
|
||||||
import type { SourceGetterInterface } from '../source/source-getter-interface';
|
|
||||||
|
|
||||||
export class NhentaiIpcController implements IpcController {
|
ipcServer.answer(IpcChannel.NHENTAI_SAVE_FAVORITES, async (): Promise<void> => {
|
||||||
private readonly nhentaiApi: NhentaiApiInterface;
|
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;
|
if (result.canceled) {
|
||||||
|
return;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@answer(IpcChannel.NHENTAI_SAVE_FAVORITES)
|
const favoritesStream = await nhentaiApi.getFavorites();
|
||||||
public async nhentaiSaveFavorites(): Promise<void> {
|
|
||||||
const result = await this.dialog.selectFolder({
|
return new Promise((resolve) => {
|
||||||
title: this.translator.t('Select torrent file save location'),
|
favoritesStream.on('data', (favorite: Nhentai.Favorite) => {
|
||||||
|
const writable = createWriteStream(path.resolve(result.filePaths[0], favorite.name));
|
||||||
|
favorite.torrentFile.pipe(writable);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (result.canceled) {
|
favoritesStream.once('end', resolve);
|
||||||
return;
|
});
|
||||||
}
|
});
|
||||||
|
|
||||||
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) => {
|
const work = await nhentaiSourceGetter.find(galleryId);
|
||||||
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);
|
|
||||||
|
|
||||||
return work;
|
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 { injectable } from 'inversify';
|
||||||
|
import { Service } from '../../core/container';
|
||||||
import { Database, getConnection } from '../../core/database';
|
import { Database, getConnection } from '../../core/database';
|
||||||
import { inject } from '../../core/inject';
|
import { inject } from '../../core/inject';
|
||||||
import { Copy } from '../../entities/library/copy';
|
import { Copy } from '../../entities/library/copy';
|
||||||
|
@ -18,7 +19,7 @@ async function getLanguage(nhentaiLanguageIdentifier: NhentaiRealLanguage): Prom
|
||||||
export class NhentaiSourceGetter implements SourceGetterInterface {
|
export class NhentaiSourceGetter implements SourceGetterInterface {
|
||||||
private nhentaiApi: NhentaiApiInterface;
|
private nhentaiApi: NhentaiApiInterface;
|
||||||
|
|
||||||
public constructor(@inject('nhentai-api') nhentaiApi: NhentaiApiInterface) {
|
public constructor(@inject(Service.NHENTAI_API) nhentaiApi: NhentaiApiInterface) {
|
||||||
this.nhentaiApi = nhentaiApi;
|
this.nhentaiApi = nhentaiApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ export class NhentaiSourceGetter implements SourceGetterInterface {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
work.languages = Promise.all(filteredLanguages.map((language) => getLanguage(language)));
|
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)
|
return Object.entries(csp)
|
||||||
.map(
|
.map(
|
||||||
(directive: [string, Session.CspValue[] | undefined]) =>
|
(directive: [string, Session.CspValue[] | undefined]) =>
|
||||||
`${directive[0]} ${directive[1] ? directive[1]?.join(' ') : ''}`
|
`${directive[0]} ${directive[1] ? directive[1]?.join(' ') : ''}`,
|
||||||
)
|
)
|
||||||
.join('; ');
|
.join('; ');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { expect } from 'chai';
|
import { expect } from 'chai';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
import { container } from '../../core/container';
|
import { container, Service } from '../../core/container';
|
||||||
|
|
||||||
describe('Store Service', function () {
|
describe('Store Service', function () {
|
||||||
this.timeout(10000);
|
this.timeout(10000);
|
||||||
|
|
||||||
it('loads saved data', () => {
|
it('loads saved data', () => {
|
||||||
const store: StoreInterface = container.get('store');
|
const store: StoreInterface = container.get(Service.STORE);
|
||||||
const testData = {
|
const testData = {
|
||||||
something: 'gaga',
|
something: 'gaga',
|
||||||
somethingElse: 0,
|
somethingElse: 0,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import App from './renderer/App.svelte';
|
import App from './renderer/App.svelte';
|
||||||
|
|
||||||
new App({
|
new App({
|
||||||
target: document.querySelector('#app'),
|
target: document.querySelector('#app') as Element,
|
||||||
});
|
});
|
||||||
|
|
|
@ -3,6 +3,11 @@
|
||||||
import NhentaiSaveFavorites from './components/modules/NhentaiSaveFavorites.svelte';
|
import NhentaiSaveFavorites from './components/modules/NhentaiSaveFavorites.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<NhentaiSaveFavorites />
|
||||||
|
<NhentaiGetWork />
|
||||||
|
</main>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
:global(:root) {
|
:global(:root) {
|
||||||
--color-white: #fff;
|
--color-white: #fff;
|
||||||
|
@ -43,8 +48,3 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<main>
|
|
||||||
<NhentaiSaveFavorites></NhentaiSaveFavorites>
|
|
||||||
<NhentaiGetWork />
|
|
||||||
</main>
|
|
||||||
|
|
|
@ -1,16 +1,48 @@
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from 'svelte';
|
import { onDestroy } from 'svelte';
|
||||||
import { entityApi } from '../../services/api';
|
import { workRepository } from '../../store/repositories/entities/work-repository';
|
||||||
|
|
||||||
export let id;
|
export let id = 0;
|
||||||
|
|
||||||
|
/** @type {WorkSerializedInterface | undefined} */
|
||||||
let work;
|
let work;
|
||||||
|
let unsubscribe = () => {};
|
||||||
|
|
||||||
onMount(() => {
|
$: unsubscribe = workRepository.subscribe(id, (serialized) => {
|
||||||
entityApi.fetchWork(id).then((workSerialized) => {
|
work = serialized;
|
||||||
work = workSerialized;
|
});
|
||||||
});
|
|
||||||
|
onDestroy(() => {
|
||||||
|
unsubscribe();
|
||||||
});
|
});
|
||||||
</script>
|
</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>
|
<style>
|
||||||
.button {
|
.button {
|
||||||
border: none;
|
border: none;
|
||||||
|
@ -9,7 +13,3 @@
|
||||||
outline-color: var(--color-accent-light);
|
outline-color: var(--color-accent-light);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<button class="button" on:click|preventDefault>
|
|
||||||
<slot></slot>
|
|
||||||
</button>
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
<script>
|
<script>
|
||||||
import Work from '../content/Work.svelte';
|
import { t } from '../../../shared/services/translation/t';
|
||||||
import { nhentaiGetWork } from '../../services/api';
|
import { nhentaiGetWork } from '../../services/api';
|
||||||
|
import Work from '../content/Work.svelte';
|
||||||
import SvelteButton from '../elements/SvelteButton.svelte';
|
import SvelteButton from '../elements/SvelteButton.svelte';
|
||||||
import { t } from '../../services/utils';
|
|
||||||
|
|
||||||
let galleryId;
|
let galleryId;
|
||||||
let work;
|
let work;
|
||||||
|
@ -13,9 +13,10 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="nhentai-get-work">
|
<div class="nhentai-get-work">
|
||||||
<label><input type="text" placeholder="177013" bind:value="{galleryId}" /></label
|
<input type="text" placeholder="177013" bind:value="{galleryId}" /><SvelteButton on:click="{handleClick}"
|
||||||
><SvelteButton on:click="{handleClick}">{t('Get')}</SvelteButton>
|
>{t('labels.actions.get')}</SvelteButton
|
||||||
|
>
|
||||||
{#if work}
|
{#if work}
|
||||||
<Work id="{work.id}" />
|
<Work id="{work.id}" />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
<script>
|
<script>
|
||||||
import { t } from '../../services/utils';
|
import { t } from '../../../shared/services/translation/t';
|
||||||
import SvelteButton from '../elements/SvelteButton.svelte';
|
|
||||||
import { nhentaiSaveFavorites } from '../../services/api';
|
import { nhentaiSaveFavorites } from '../../services/api';
|
||||||
|
import SvelteButton from '../elements/SvelteButton.svelte';
|
||||||
|
|
||||||
function handleClick() {
|
function handleClick() {
|
||||||
nhentaiSaveFavorites();
|
nhentaiSaveFavorites();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style></style>
|
|
||||||
|
|
||||||
<div class="nhentai-login">
|
<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>
|
</div>
|
||||||
|
|
|
@ -1,15 +1,493 @@
|
||||||
import { ipcClient } from './ipc-client';
|
import { ipcClient } from './ipc-client';
|
||||||
|
|
||||||
export function nhentaiSaveFavorites(): Promise<void> {
|
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> {
|
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 = {
|
export const entityApi = {
|
||||||
fetchWork(id: number): Promise<WorkSerializedInterface> {
|
createAuthor(data: Partial<AuthorSerializedInterface>): Promise<AuthorSerializedInterface> {
|
||||||
return ipcClient.ask(IpcChannel.ENTITY_GET_WORK, { id });
|
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